flat assembler
Message board for the users of flat assembler.
Index
> Windows > Simple JMP Hook. Goto page 1, 2 Next |
Author |
|
Overflowz 15 Dec 2012, 14:04
Anyone?..
|
|||
15 Dec 2012, 14:04 |
|
l_inc 15 Dec 2012, 14:17
Overflowz
First, you don't have to change page permissions with VirtualProtect. WriteProcessMemory is able to handle that for you. Second, mov eax,mem32 + jmp eax is kinda overkill in terms of size. A single jmp imm32 is enough to hook. Besides the longer the hooking byte sequence, the larger the probability, you will disturb the processor at the moment it will be trying to execute the original bytes, and the hook attempt will fail. Third, if you hook a standard WinAPI function, then consider taking advantage of the hotpatch prologue, because most of the WinAPI functions are hotpatchable, which means, that they start with mov edi,edi (in rare case a different 2-bytes instruction), which is a place for a short 2-bytes jmp back for 7 bytes and are preceded by at least 5 bytes of padding, which is a place for a near 5-bytes jmp to your hook function. And finally... Quote: How can I fix this problem? Easily. Just modify your hooking code before applying it to the hooked function. In your case it would mean to write to the instruction mov eax,imm32 (mov eax,mem32 is a bad idea anyway) first and then write the result to the beginning of the function. But again, it's better to use the previously mentioned short and/or near jmp's. |
|||
15 Dec 2012, 14:17 |
|
Overflowz 15 Dec 2012, 15:00
Hi, I tried something like this:
Code: mov eax,[hookFunction] mov [hook_stub+1],eax ;$E9 + jmp location hook_stub: db $E9 ;JMP db 0xFFFFFFFF ;imm32 but it jumps to wrong location. How to calculate location ? -- But wait. now I it like this: Code: 1) MessageBoxA called, JMP to my proc. 2) change text and caption, restore original bytes, jmp there. (unhook?) this will require code to be hooked again. What I'm missing? |
|||
15 Dec 2012, 15:00 |
|
baldr 15 Dec 2012, 15:26
Overflowz,
0xE9 is opcode for jmp rel32, not imm32 (i.e. it's relative jump, not direct). You must calculate displacement beforehand (simply subtract address just after jmp from target address, and you've got it). To re-hook function you may patch return address in stack. Completely different approach involves debug API and breakpoints. |
|||
15 Dec 2012, 15:26 |
|
Overflowz 15 Dec 2012, 15:41
I honestly don't get it.
Code: mov eax,[hookFunction] sub eax,hook_stub+5 |
|||
15 Dec 2012, 15:41 |
|
Overflowz 15 Dec 2012, 16:36
Bump.. I'm trying to write static library that will redirect to hooked procedure, modify things, then return modified arguments to API. I'm just having headaches after moving from HLL to LLL.
|
|||
15 Dec 2012, 16:36 |
|
l_inc 15 Dec 2012, 16:55
baldr
Quote: 0xE9 is opcode for jmp rel32, not imm32 (i.e. it's relative jump, not direct). Actually, imm32 wouldn't mean, it's a direct jump. imm32 means only, that it's an immediate value (encoded directly in the instruction) and that it's length is 32 bits, which is true. However as long as Intel provides a separate notation for relative values, rel32 would surely be more correct. Overflowz Jump source is not your "hook_stub". Jump source is the the beginning of the hooked function (+ 5 bytes). Thus destination-source would look like this: Code: mov eax,[hookFunction] sub eax,[origFunction] sub eax,5 ;size of the jmp rel32 instruction mov [hook_stub+1],eax ;$E9 + jmp location Quote: this will require code to be hooked again. What I'm missing? Never unhook a function, until you don't need the hook anymore. If you don't wanna make use of the hotpatchability, then in general case you'd need more or less advanced code mutation engines, able to move the overwritten code from the original function, so that it remains functional at another location, where your hook function would execute it directly. The hotpatchable prologue (as described before) makes the things much easier. |
|||
15 Dec 2012, 16:55 |
|
Overflowz 15 Dec 2012, 17:23
Oh, my bad, I guess it now.
Will continue writing.. Here's what I'm trying to do. Code: 1) hook function (MessageBoxA), first 5 bytes would be JMP XXXXXX. 2) Whenever I call MessageBoxA, it will jump to hooked function, like his: proc hMessageBoxA, HWND, szText, szCap, UINT mov [szText],"Hello" mov [szCap],"World!" ret endp 3) after RET, it will return to the original MessageBoxA and execute it. I have to work very hard I guess |
|||
15 Dec 2012, 17:23 |
|
typedef 15 Dec 2012, 18:26
Here. Study this.
Code: ; ; typedef @fasm boards ; format pe gui 4.0 include 'win32ax.inc' entry WinMain section '.text' code readable executable ;----------------------------------------------------------------------------------- ; Returns absolute original function pointer. ; ; FARPROC WINAPI HookFunc(LPSTR szLibrary, LPSTR szFunctionName, LPVOID newHook); ;----------------------------------------------------------------------------------- proc HookFunc szLibrary, szFunctionName, newHook push ebx push esi push edi local oldProtect:DWORD push dword [szLibrary] call [GetModuleHandleA] push dword [szFunctionName] push eax call [GetProcAddress] mov ebx, eax mov esi, ebx add esi, -5 ; calculate address lea eax, dword[oldProtect] push eax push 0x40 ; PAGE_EXECUTE_READWRITE push 7 push esi call [VirtualProtect] cmp eax, 0 jne no_error jmp finish ; begin patch. This is simplified so you understand and not memorize. no_error: cld mov al, 0xE9 mov edi, esi stosb ; Install Jump opcode at first 'NOP' op-code mov eax, dword [newHook] sub eax, ebx stosd ; Install address. DWORD mov edi, ebx ; at LEA EDI, EDI mov ax, word [jmp_code] stosw ; Install jump code + address(WORD) at entry point(LEA EDI,EDI) lea eax, [ebx+2] ; Absolute function pointer (starts at PUSH EBP skipping - jmp finish ; the relative two byte backward jump; JMP SHORT XX) jmp_code: jmp $ - 5 finish: pop edi pop esi pop ebx mov esp, ebp pop ebp ret 4 * 3 endp ; to unhook just put NOPs on it and remember to set PAGE protection back to its normal state. ; ; TEST ; proc msgBox, hwnd, msg, title, flags ; push them again or use JMP(not good IMO) push dword [flags] push dword [title] push myText push dword [hwnd] call dword [absMsgBoxPtr] leave ret 4 * 4 ; remove original arguments endp WinMain: stdcall HookFunc, szLib, szProc, msgBox mov [absMsgBoxPtr], eax invoke MessageBoxA,0,'Hello world','Here I am',MB_OK invoke ExitProcess,0x0 section '.data' data readable writeable absMsgBoxPtr dd 0 myText db 'Hello Again Nuggah!',0 szProc db 'MessageBoxA',0 szLib db 'user32.dll',0 section '.idata' import data readable library user32,'user32.dll',\ kernel32,'kernel32.dll' include 'api/kernel32.inc' include 'api/user32.inc' |
|||
15 Dec 2012, 18:26 |
|
Overflowz 15 Dec 2012, 18:31
Thanks for sample, will study it right now!
|
|||
15 Dec 2012, 18:31 |
|
typedef 15 Dec 2012, 18:33
No problemo. I also suggest you step through it with Olly so you know what's actually going on.
|
|||
15 Dec 2012, 18:33 |
|
Overflowz 15 Dec 2012, 19:06
I understood what's going on there. it's hooking MOV EDI,EDI to jmp -5 relative, where are 5 nops patched with JMP to HookedFunction and returns original function w/o MOV EDI,EDI, just another next bytes. Is all WinAPI like that ? I'm going to try more advanced one, which will save bytes, restore, etc..
|
|||
15 Dec 2012, 19:06 |
|
typedef 15 Dec 2012, 19:11
Yes. Most if not all WINAPIs are like that.
|
|||
15 Dec 2012, 19:11 |
|
Overflowz 15 Dec 2012, 19:17
Alright, got it now how this should work, will work with it now Thank you guys.
|
|||
15 Dec 2012, 19:17 |
|
l_inc 15 Dec 2012, 20:20
Overflowz
Quote: I'm going to try more advanced one, which will save bytes, restore, etc. As I already said, to restore is not more advanced. It's more faulty. Especially, in multithreaded environment. If you wanna do the patch more advanced, then try to execute the original instructions from where you backed up them and then transfer control to the continuation of the original function. Quote: Is all WinAPI like that ? As I already said, most of the WinAPI functions are hotpatchable. But not all of them. You should always check that and in the simplest case refrain from patching an inappropriate function |
|||
15 Dec 2012, 20:20 |
|
Overflowz 15 Dec 2012, 21:06
l_inc
Thanks in advice, but where can I save original bytes for each function and access them for each procedure? I know most of them will be same(MOV EDI,EDI) but if there's different one? Thanks. |
|||
15 Dec 2012, 21:06 |
|
typedef 15 Dec 2012, 21:25
Overflowz wrote: l_inc You probably don't want to do that because then you'll have to allocate memory for each function you hook. Maybe you could make a function that finds a code cave in the process space then use linked lists. But all of this for what? It's too overkill IMO. Now, for those APIs that are not patchable like this, you can still overwrite the first 5 bytes with a JMP to a hook address that contains the hardcoded patched bytes. That is to say if you're that desperate. In which case you;d have to set up pointers/flags again. Otherwise you may want to use IAT hooks at this point. |
|||
15 Dec 2012, 21:25 |
|
Overflowz 16 Dec 2012, 11:39
I guess you're right. Thanks for tips
|
|||
16 Dec 2012, 11:39 |
|
yoshimitsu 17 Dec 2012, 00:56
l_inc wrote: First, you don't have to change page permissions with VirtualProtect. WriteProcessMemory is able to handle that for you. msdn wrote: lpBaseAddress [in] typedef wrote: Yes. Most if not all WINAPIs are like that. Functions from kernel32.dll (win7 x86 dll), which do not support hotpatching: Quote: AreFileApisANSI The list for user32.dll is even longer.. Instead of checking for the availability of hotpatching (the 5x nops could also be 5x int3, and if l_inc is correct, the mov edi,edi might differ as well, making it kinda complicated to check whether hotpatching is possible) you should probably just write a universal hook function which uses a length disassembler engine to securely save the instructions which need to get overwritten by the hook-jmp and save them to a different location and append a jmp back to the hooked function but behind the hook-jmp, creating a gate to call the original function without invoking the hook. For cleaning up just move the instructions back to their original place and free the location, where you saved them previously, afterwards if it was allocated. |
|||
17 Dec 2012, 00:56 |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.