• Welcome to Valhalla Legends Archive.
 

API hooking and code injection

Started by Banana fanna fo fanna, June 01, 2003, 08:52 PM

Previous topic - Next topic

Banana fanna fo fanna

I've asked this several times on the other boards to no avail.

Basically, what I'm trying to do is change the thunk in-memory of another process to point to one of my dlls. I've figured out how to inject a dll using SetWindowsHookEx(), but now I just need to hook the API call. The function Jeffrey Richter provided doesn't work for some reason. I've googled it countless times.

Anyone have any help?

TheMinistered

#1
While I'm getting ready to leave, I will post a simple but watered down explanation.  You basically use the WriteProcessMemory function to write your machine code somewhere in the process that is actually useful.  Note: You might have to write some data, such as, the filename/path of the dll somewhere inside the process too.  The machine code loads your dll using the LoadLibrary function.  You basically have the Loader and the DLL.  The loader injects the code/data that tricks the process into loading your DLL.  I'm sorry I didn't have enough time to explain this in detail, but I have to go!  

Banana fanna fo fanna

I know, its the WriteProcessMemory params I need ;)

And also, you can just do a rundll32 entrypoint instead of a loader, makes things slightly less confusing (or more...depending on how you look at it ;))

Adron

Try to separate the problems of 1. getting the dll into the process 2. getting the process to call your dll's functions.

From what I understand, you've already solved #1 by using SetWindowsHookEx. The answer by TheMinistered seems to deal mostly with #1.

To do #2, you need to tell us a bit more about exactly what you want to hook. The easiest possibility would be if you're hooking something in the import table of the program. That can be done by a search/replace through the memory of the application from 401000 up to the first memory block that isn't commited. Search for the (pointer to the) function you want to hook and replace it with the address of your function.

It's also easy to modify internal calls in the application, but you have to beware that the address there is supposed to be relative to the location of the instruction following the call. You can of course also patch any location with some machine code to call your function, but then you're getting into the trickier code.

Things to think about: Memory protection, preserving registers, calling conventions. You don't need to use WriteProcessMemory if you do the patching from your dll after it's loaded in the target application.

indulgence

#4
If you are wanting to hijack a function midstream you will want to do the following:
1. Redirect To a stub
   - you need to find 5+ bytes you can use to redirect (N*B* if you use more you must nop after the call -- dont leave machine instructions half overwritten)
   - you WILL need to use VirtualProtect to protect the memory before you do any patching...
   - you WILL need to read the bytes you plan to overwrite to call your stub and WRITE them into the beggining of your stub
   - you *could* make a macro to return the relative address you need to create a call although its not difficult to do without the macro
   - your stub MUST be "naked" (only asm) and can then call a clean c function in your dll
2. Your stub will want to look like the following:

// begin code
nop
nop
nop
//  ^ etc.. you get the point -- as many as you will need to overwrite with the bytes from the redirect

// must preserve registers (including the flags register)
pushad
pushfd

// set up any registers you might need (fastcall uses registers -- if you are using fastcall calling convention on your clean c function)
// if not using fastcall - you will want to push your arguments
call your_clean_c_fxn

// restore the registers
popfd
popad
// -- end code
<3

indulgence

#5
dangit hit reply instead of modify -- surry :'(
<3

Banana fanna fo fanna

OK. How would I get the address of an imported function, say, USER32!MessageBoxA, so I could put my stub in there?

TheMinistered


Adron

In C/C++,  the name is the address... You can do something like:


typedef int __stcall MessageBoxFunc(HWND, LPCTSTR, LPCTSTR, UINT);

for(MessageBoxFunc **x = (MessageBoxFunc**)0x401000; <insert condition>; x++) {
  if(*x == MessageBoxA)
     *x = YourFunction;
}


Like I said before, a possible condition would be to check the size of the allocated memory starting at 0x401000. You can do that using VirtualQuery.

If you're patching a specific version of a program you could also just look up the offset to patch in the disassembly. Calls to api functions will generally look like this:


call dword ptr[<some offset>]


Then all you need to do is


*(MessageBoxFunc**)<some offset> = YourFunction;



If on the other hand you wish to be more generic, you could walk the import table of the program. The structure definitions for that can be found in winnt.h.



Banana fanna fo fanna

#9
Adron you genius :)

What would happen if it wasn't imported? Would it loop forever? At which point would I stop looping?

Sorry for all of these questions.

EDIT: missed the part about VirtualQuery...oops

Banana fanna fo fanna

It doesn't seem to find the proc in the target proces (Notepad.exe). Any suggestions? Perhaps it is dynamically loaded?

Kp

Quote from: St0rm.iD on June 04, 2003, 06:03 AM
It doesn't seem to find the proc in the target proces (Notepad.exe). Any suggestions? Perhaps it is dynamically loaded?
Post the loop you're using.  It's easier to debug when we know exactly what you're doing.
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

Banana fanna fo fanna

I found the problem. The injected DLL doesn't have priviledges to read the memory at 0x401000. I VirtualProtect()'d the memory as well.

Any suggestions?

Skywing

Quote from: St0rm.iD on June 05, 2003, 02:21 PM
I found the problem. The injected DLL doesn't have priviledges to read the memory at 0x401000. I VirtualProtect()'d the memory as well.

Any suggestions?
Maybe you gave bad parameters to VirtualProtect?  Did you check if it succeeded, and what the error code was if not?

Camel

you might want to take a peek at the source code for mousepad's d2 maphack