El codigo, debería mostrar un mensaje "Exception catched!!" cuando haya una excepcion. Pero el programa sale sin más, aunque curiosamente, no crashea. Aún así la idea es que llame a mi manejador de excepciones, cosa que no hace
Aquí está mi codigo. Está escrito en FASM
Código
format pe console 4.0 section '.text' readable writable executable start: call delta_offset ;Calculates the delta offset delta_offset: pop ebp ;Save the current address of the delta_offset routine in memory sub ebp, delta_offset ;Current address of delta_offset ´- address of delta_offset at compilation time ;is equal to current address of virus body in memory. Now we can access any part of ;data embebbed in the code using [ebp+variable] finding_kernel32: mov ebx, [FS : 0x30] ;FS:0x30 is a pointer to the address of Process Environment Block (PEB) ;Now the Base Pointer (BX) points to the address of PEB in memory mov ebx, [ebx + 0x0C] ;Now we move 0x0C (12 bytes) from the address of PEB ;We get the value of ebx+0x0c, in other words, the address that has the PEB->Ldr pointer ;Now we are in Ldr structure. We move the ebx pointer following the address in the ;PEB->Ldr pointer. mov ebx, [ebx + 0x14] ; get PEB->Ldr.InMemoryOrderModuleList.Flink (1st entry) mov ebx, [ebx] ;2nd Entry mov ebx, [ebx] ;3rd Entry mov ebx, [ebx + 0x10] ; Get Kernel32 Base mov [ebp+dwKernelBase] , ebx add ebx, [ebx+0x3C] ; Start of PE header mov ebx, [ebx+0x78] ; RVA of export dir add ebx, [ebp+dwKernelBase] ; VA of export dir mov [ebp+dwExportDirectory] , ebx finding_address_of_getprocaddress: lea edx,[ebp+api_GetProcAddress] ;Load in ebp the address of the API function name. mov ecx,[ebp+len_GetProcAddress] ;Load in ecx the size of the API function name call GetFunctionAddress ;Call GetFunctionAddress mov [ebp+AGetProcAddressA] , eax ;The API function address in memory was stored by the ;GetFunctionAddress function in eax, now we save the address ;of the GetProcAddress in a variable for later use. finding_address_of_loadlibrary: lea edx,[ebp+api_LoadLibrary] ;Load in edx the API function name of LoadLibrary push edx ;edx could be a parameter for an API push dword [ebp+dwKernelBase] ;save in the stack the address of the kernel32 library ;dwKernelBase is used as handle call eax ;Calls a function by its address (eax stores it) ;Could be GetProcAddress because in the instruction in ;the line 39 it moves the address of that API from eax ;and eax has no changes until 47 line. loading_required_libraries: mov [ebp+ALoadLibraryA] , eax ;The last function could return the address of LoadLibrary in ;in eax. eax register could be used by the last function as a ;return value. ;Now the eax register contains the address of LoadLibrary lea edx , [ebp+szUser32] ;Loads in edx, the library name of User32.dll push edx ;Put the edx value in the stack as a parameter for LoadLibrary ;I believe that the function could be LoadLibrary because ;it is an API that requires a string that contains the name of ;the library that you want to load. call eax ;Call LoadLibrary API mov [ebp+hUser32], eax finding_addresses_of_apis: lea edx , [ebp+api_MessageBoxA] ;Loads in edx the address of the name of MessageBoxA API push edx ;Put the name of MessageBoxA as a parameter for a function push eax ;I belive that eax is a handle to the loaded library mov ebx,[ebp+AGetProcAddressA] ;Moves to ebx the address of GetProcAddressA call ebx ;Invokes GetProcAddressA using its address mov [ebp+AMessageBoxAA] , eax ;The last function (could be GetProcAddressA) returns the address of ;MessageBoxA in eax. We move the address of that API to a variable for ;later use. ;We start to search for functions inside ;kernel32.dll set_exception_handler: ;A simple way to set a exception handler, avoiding the ;use of APIs that increase the size of the release. push exception_handler push dword [FS:0] mov [FS:0], esp main: push 0 ;Put the HWND parameter lea edx,[ebp+szTitle] ;Put the caption of the MessageBox push edx lea edx,[ebp+szMsg] ;Put the message body of the MessageBox push edx push 0 ;Buttons type (For example MB_OK) call dword [ebp+AMessageBoxAA] ;Calls MessageBoxA API ;The following code tries to make many exceptions int3 ;Software breakpoints int3 int3 mov esi, 0 ;Access violation mov dword [esi], "fail" exit: ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; <<<<< GetFunctionAddress >>>>>> ; ; Extracts Function Address From Export Directory and returns it in eax ; ; Parameters : Function name in edx , Length in ecx ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; GetFunctionAddress: push ebx ;Save status of registers before execute the subroutine push esi ;to preserve its content. It could make some errors to the push edi ;caller function if modify the values that are common to the whole ;program mov esi, [ebp+dwExportDirectory] mov esi, [esi+0x20] ;RVA of ENT add esi, [ebp+dwKernelBase] ;VA of ENT xor ebx,ebx cld looper: inc ebx lodsd ;Load a byte from the string pointed by SI into al register add eax , [ebp+dwKernelBase] ;eax now points to the string of a function push esi ;preserve it for the outer loop mov esi,eax mov edi,edx cld ;The direction flag is clear, this means that the SI and DI pointers are ;incremented. (The instructions works to the forward direction) push ecx ;Save ecx. Why?? The next instruction named "repe" decrements the counter. ;Because the ecx contains the length of the API name, we need to save it. ;In other parts of subroutine the program uses ecx register to compare the function ;with the kernel export table. repe cmpsb ;Compare each byte of the array pointed by DS:SI with the array pointed by ES:DI ;Repeat until the counter is not equal to zero, in other words, ;it only stops when it find a difference or the counter reachs the end of the string pop ecx ;Pop the length of the string, and put it in the counter for another loop if it's needed pop esi ;Pop the last stack variable, and put it in esi. jne looper dec ebx mov eax,[ebp+dwExportDirectory] mov eax,[eax+0x24] ;RVA of EOT add eax,[ebp+dwKernelBase] ;VA of EOT movzx eax , word [ebx*2+eax] ;eax now holds the ordinal of our function mov ebx,[ebp+dwExportDirectory] mov ebx,[ebx+0x1C] ;RVA of EAT add ebx,[ebp+dwKernelBase] ;VA of EAT mov ebx,[eax*4+ebx] add ebx,[ebp+dwKernelBase] mov eax,ebx pop edi ;Restore the registers to avoid generate a problem pop esi ;in the caller function. pop ebx ret exception_handler: push 0 ;Put the HWND parameter lea edx,[ebp+szTitle] ;Put the caption of the MessageBox push edx lea edx,[ebp+szMsgException] ;Put the message body of the MessageBox push edx push 0 ;Buttons type (For example MB_OK) call dword [ebp+AMessageBoxAA] ;Calls MessageBoxA API ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Data Shit ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; szMsgException db 'Exception catched!!', 0 api_ExitProcess dd 0 szTitle: db "From the heaven",0 szMsg: db "Greetings from hell",0 szUser32 db "User32.dll",0 hUser32 dd 0 AGetProcAddressA: dd 0 api_GetProcAddress: db "GetProcAddress" len_GetProcAddress: dd $-api_GetProcAddress ALoadLibraryA: dd 0 api_LoadLibrary: db "LoadLibraryA",0 AMessageBoxAA: dd 0 api_MessageBoxA: db "MessageBoxA",0 dwKernelBase: dd 0 dwExportDirectory: dd 0
Intenté hacer el siguiente método:
Código
push exception_handler push dword [FS:0] mov [FS:0], esp
El metodo que describí funciona en este pequeño ejemplo (no es la aplicacion que estoy escribiendo):
Código
format pe console 4.0 ;on 'dos_stub.exe' include 'C:\fasm\INCLUDE\WIN32AX.inc' .data msg_caption db 'SEH handler', 0 msg_exception db 'I catched an exception!! Amazing!!', 0 .code main: ;A simple way to set a exception handler, avoiding the ;use of APIs that increase the size of the release. push exception_handler push dword [FS:0] mov [FS:0], esp mov esi, 0 mov dword [esi], "Pwnd" exit: invoke ExitProcess, 0 exception_handler: invoke MessageBox, NULL, addr msg_exception, addr msg_caption, MB_OK jmp exit ret .end main
Por que en el primer codigo no trabaja, mientras que en el segundo si lo hace??? Alguien puede decirme porqué??? Gracias de antemano, y perdon por hacerlos leer tanto. (XD).
Ah, se me olvidaba, también intenté usar SetUnhandledExceptionFilter (API) para establecer mi funcion como manejador de excepciones, pero no funciono. ¿Será qué el uso que le doy a ciertos registros afecta lo que trato de hacer??