|

Introduction
There are numerous codes in the WWW to explain how to hook API functions inside a remote process. So, why creating another one?
This article is the first (I) part of a tool I'm working on. These tools won't be too complex, so there is no need for a huge class hierarchy like in almost all other codes, nor a hard coded assembly code. This tool is just a technical preview of what is possible to achieve, with QUICK and DIRTY "put your functions here" blocks.
Before you read
Okay, to be clear, when you'll open the project and have a look to the code, you'll see it is not very well polished. It doesn't compile without warning, there is only few comments (compared to production code). However, it compiles and run cleanly on WinXP and 2003 platforms, (and should also run under Win2K, but I didn't check that).
Background
I used to develop a software using DirectShow. Sadly, I run into problem with a simple synchronization object which deadlocked the application. I still think there are two things a developer might fear about.
- The first one is "memory leaks". Memory leaks are most of the time due to an oversight. They are very well covered because they are easily (automatically) corrected.
- The other one is "error handling". Error handling seems very simple at first, but most of the time, there is always the "BAD CASE" which causes the "BAD BUG".
Badly handling errors in a software leads to crash or illogic state. To compare to physic state, it is easy to predict and create a system in its stable state. However, reaching/leaving this stable state is hard to predict, because error / thread scheduling order / memory usage / dark phenomena might change parameters. Recovering from an unstable state is very hard.
I can't give a global solution to this (if anyone could, please mail me). So let's see the usual solutions:
- Error return: Never expect a function will always work. There are numerous articles about these issues.
- Thread: This is the subject of the whole project.
- Memory usage: Monitoring the memory allocated by overriding the
malloc/free/new/delete functions/operators most of time is sufficient.
- IO states: You'll need to establish a complete graph of states for handling all cases
Threads are one of the most "strange" thing. While it is possible to simulate almost all memory conditions, IO states and error returns, it is not possible to simulate the execution order of threads.
(uh, that's long!)
So to sum up, this project only focuses on one problem: data synchronisation in multithreaded environment. This article explains a technique to monitor calls to system functions. The aim of the global project is to build a deadlock detector. A deadlock occurs when, while protecting the access to a block of data (A), a thread is trying to access another protected block of data (B). This other block (B) is protected by another thread which tries to access the first protected block (A).
Then, to achieve this goal, let's split the project in small steps:
- Part 1. Hooking system functions.
- Part 2. Intercepting all calls to synchronization functions.
- Part 3. Building the logic for deadlock detection.
- Part 4. [Cosmetic] Using the map file + stack address to fetch the source code[/Cosmetic].
Part 1. Hooking system functions
I highly recommend you to read "Process-wide API spying - an ultimate hack" article by Anton Bassov and "API Hooking system" by Ivo Ivanov.
I won't dig into an n-th explanation about how to inject your code into a process. I will however explain what I chose, and how I make it works for me. The idea is to inject a DLL in a remote process so that the DLL will perform the function hijacking. The DLL is called in this project ThreadSpy.DLL. When the DLL is created, the DllMain function is called with ProcessAttach's reason. In this case, it parse the HookStruct array (defined in ThreadSpy.cpp), and replaces a given Win32 API function by a DLL supplied one.
The hook functions are defined in Hooked.cpp source file. Then, the import table of each already loaded module (like Kernel32.DLL, USER32.DLL, GDI32.DLL, etc...) is updated to replace the original function address with any supplied function.
Then a server could inject this DLL in a running process or spawn its own. The server is inside the ThreadDLD project, and is simply a WTL application which will receive message from the hooked process and inject the DLL in the hooked process. I've chosen to create the monitored process with the CreateProcess function with CREATE_SUSPENDED flag. This way, I can easily inject my DLL before any other DLL are loaded (in fact after the vital one like NTDLL and Kernel32). Then the server resume the thread, and is ready to collect the message from the DLL.
In order to intercept any newly loaded DLL in the hooked process, it is required to intercept the LoadLibrary and GetProcAddress functions. That's why those functions are always hooked.
I won't discuss about how to send a message to the server in this article, that's why I removed the code for this in the demo and source. With this demo, you could easily implement your own API hooking by changing the functions in ThreadSpy.{h,cpp} and in Hooked.cpp. This way you can easily monitor who is trying to create a file (and reject the creation if the credentials are not high enough) by adding a MyCreateFile function.
In this example, I've chosen to hook TextOutA and TextOutW so that it is visually obvious.
Credits
As I said earlier, please read:
Future...
In the second part of the project, I will try to explain how to intercept all the required functions to monitor thread creation/destructions and synchronisation objects and communicate those information to the server. This article is more a prolog to the real article. The second part is here: Thread deadlock detection (part II)
| You must Sign In to use this message board. |
|
| | Msgs 1 to 23 of 23 (Total in Forum: 23) (Refresh) | FirstPrevNext |
|
 |
|
|
 |
|
|
ive noticed that part of code needed to unhook all hooked functions doesnt fire at all, so everytime i try to free my dll, the app crashes. help?
dude, did you test it before to relase it? it doesnt work!!! at least fix it, ..next time avoid to post such codes
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hey men... its a nice article from Mr/Mrs xryl669!
However, it believe you are right about the problem with unloading the hooks.
I have added an UnHookAllModules function, which I believe was forgotten in the original sourcecode and fixed the problem for me (I also had to replace some GetModuleHandle for GetModuleHandleA...).
Regards! PDG> ====================================================================
void UnHookAllModules(HookStruct array[], const int size) { // Now replace in all the module of the current process HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,GetCurrentProcessId()); MODULEENTRY32 mod; int i; mod.dwSize = sizeof(MODULEENTRY32);
Module32First(snap,&mod); HMODULE first = mod.hModule; for (i = 0; i < size; i++) Replace(&array[i], FALSE, first); while(Module32Next(snap,&mod)) { HMODULE next = mod.hModule; if (next == hCurrentHandle) continue; for (i = 0; i < size; i++) Replace(&array[i], FALSE, next); } }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I'm try to hook all calls to LoadLibrary. But If I first call LoadLibrary to load a module then hook all the calls within that module to Kernel32::LoadLibrary, i'm too late, so calls to load submodules were made during the call to LoadLibrary.
Where's the trick?
Thanks
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
Have you got a version that handles hooking when the calling DLL uses ordinals instead of names, ie when pThunk->u1.Ordinal is valid instead of pThunk->u1.Function ?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi man, i am try get some code for Anticheat and need know if you code can help me.
Is posible using you code Hook API WriteProcessMemory when use in parameters the PID the my Game program ?
WriteProcessMemory required use the API OpenProcess.
OpenProcess Need PID the Game in memory founded using API FindWindow.
Most used API for Cheats Coders.
FindWindow GetWindowProcessID OpenProcess ProtectEx WriteProcessMemory
You think is posible detect cheats ?
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
Of course it is. Just like the rootkit revealer from Sysinternal, you can monitor the address of the functions (like FindWindow/etc...) and see if they are in the kernel32.dll address space. If not, they are hooked. To know this, get the kernel32 mapping (GetModuleInstance), size by enumerating modules, and check that GetModuleInstance(Kernel32) <&FindWindow < GetModuleInstance(Kernel32)+size of(Module) is true.
However this is a cat and mouse game. A cheater software will find the trick quickly and will patch your exe in order to remove the test.
The only solution is to cypher your code(and include the decyphering code) so the patching can not be done without loosing too much functionnality.
Good luck
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
thank you man, we think how using that.
You are expert in that.
You have some idea "How detect when clients using programs XP SPEED" ? This programas accelerate the timer and run more fast inside game.
Any idea where begin my search ?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
This is more complicated than you usually think of.
First, the XP Speeder software installs a kernel mode driver to fake the hardware timer.
If you have access to the game source code, simply don't call any function that are timer based (like clock, GetSystemTimeAsFiletime etc...) and implement a function "GetCPURealTicks" based on assembler "rdtsc" instruction (search on Codeproject, there is a lot of article on this). This instruction is not fakeable.
If you don't have access to the source code, then you'll have to create a thread that implement the above trick, and calculate the clock from your read value. Then hook all the timer based functions to feed them with the real value you've read & calculated.
Good luck...
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
|
Hello,
I am not able to make StackWalk64 work properly in my system. Am using the same codebase as used in your article (Part III). I have a WIN XP system. HAL.dll version is 5.1.2600.2180.xpsp_sp2_rtm.040803-2158. This is working fine in another system which has SP1 service pack. But not with SP2.
I have tried downloading the symbols (kernel32.pdb and ntdll.pdb) and have set _NT_SYMBOL_PATH environmental variable to point c:\winnt\system32.. But its not working. StackWalk64 is giving a stack depth of only 2. Same for StackWalk function.
Any suggestions would be of great help.
Regards Rajdeep
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I don't know why. You should analyse what StackWalk reports (errors, contexts, etc...). Can you try the memory leak detector called VLD (search for memory leak in CodeProject) to see if you have stack with this software. If you do, then change the asm code to Get EIP to the one used in VLD.
Hope it helps Sincerely, Cyril
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Thanks so much, this article is great.
But when I unhook the DLL, seems to me that the real method's adresses are corrupted or not written again, because i get an "error reading memory in 0x00003" and all that that we know are bad news.
When i unhook the DLL how can I replace the false adresses with the real ones again?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I guess there is something wrong happening here.
The HookStruct structure should hold the previous address (in the last NULL member) and it is used to avoid changing the API function address twice.
The good value should be stored in that member, so I think you should add a message box with such string ("last member address is : %08X, should be %08X", hookStructPointer->pPrevFunc, GetTrueProcAddress(GetModuleHandle("kernel32.dll"), "yourfunctionhere")) and see if they match.
If they match, then you should double check the unhooking code. If they don't match, then you should try to see where you've rewritten the last member with the wrong value. If you use the last version (part 3 of these articles), then change the ThreadSpy.cpp:287 from
// Now hook the function array[i].pPrevFunc = etTrueProcAddress(::GetModuleHandleA(array[i].szDLLName), array[i].szFuncName);
to
// Now hook the function array[i].pPrevFunc ? MessageBox(NULL, "This is strange, as the member is already initialized", "Error", 0) : array[i].pPrevFunc = etTrueProcAddress(::GetModuleHandleA(array[i].szDLLName), array[i].szFuncName);
Hope it helps, sorry for late answer.
|
| Sign In·View Thread·PermaLink | 1.00/5 (2 votes) |
|
|
|
 |
|
|
I tried to use working implementation with Notepad.exe with ThreadSpy.exe.
I have commented the overriding of Gdi32.dll code.
When i try to save the file it always give the following error "Not enough memory available to complete the program.Quit one or more applications to increase virtual memory"
Why it is prompting the above error.
Regards, Sunil Virmani
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
I have no idea. Please be more specific about what you are doing and what you have modified.
I can save the file with this version. Please confirm you can do the same with yours.
xryl669
|
| Sign In·View Thread·PermaLink | 3.00/5 (1 vote) |
|
|
|
 |
|
|
// This is an ugly function void * FindFunction(LPCSTR lpName)
Why do you call this ugly?
One problem with it occurs when functions are called in the DLL by export ordinal. See documentation for GetProcAddress. If this happens, then lpName is not a pointer to a character string and the hooked application crashes.
I can prevent the crash by adding to the start of FindFunction
if( (int)lpName < 1000 ) return NULL; Of course, this would defeat our purpose if the function called by export ordinal is the one we want to hook.
TODO:
The number 1000 is arbitrary. What would be the most appropriate?
How can we determine the export ordinals, and fix this?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi,
You're right, this is why FindFunction is an ugly function (and because it is prone to buffer overflow too). Okay, after reading GetProcAddress documentation,
From MSDN about lpName: [GetProcAddress] If this parameter is an ordinal value, it must be in the low-order word; high-order word must be zero
So, I think the code should be changed to check if the 2 first chars are zero, and if yes handle the next 2 chars as unsigned short number. I'll try this modification as soon as I release a new version.
Thanks for spotting the bug.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi xryl669,
Excuse me guies, this question is targating towards xryl669 and the dudes who has gud understading of API HiJacking !
Is it always required to HiJack these 4 functions of Kernel32.dll ??? 1. LoadLibraryA 2. LoadLibraryW 3. LoadLibraryExA 4. LoadLibraryExW 5. GetProcAddress
I am trying to HiJack "BitBlt" API from GDI32.dll, I will appriciate if u could guide me on this.
Things I have tried - - I am trying to HiJack the "BitBlt" API from GDI32.dll, so the structure for function becomes - {"Gdi32.dll" , "BitBlt" , MyBitBlt , NULL, NotHookedYet} {"Kernel32.dll", "LoadLibraryA" , MyLoadLibraryA , NULL, NotHookedYet}, {"Kernel32.dll", "LoadLibraryW" , MyLoadLibraryW , NULL, NotHookedYet}, {"Kernel32.dll", "LoadLibraryExA", MyLoadLibraryExA, NULL, NotHookedYet}, {"Kernel32.dll", "LoadLibraryExW", MyLoadLibraryExW, NULL, NotHookedYet}, {"Kernel32.dll", "GetProcAddress", MyGetProcAddress, NULL, NotHookedYet}
- Created WIN32 DLL, which is installing a global message hook. In DLLMain I am calling function for API HiJacking (HookFunctions,HookAllModules). I make sure that this code should get executed only once using synchronization (i.e by the application which is installing the hook).
- Not getting desired results as such, it seems to me BitBlt API for the application which is installing hook gets HiJacked only (my observation) ?
- Is it required to call the API HiJacking function in DLL_PROCESS_ATTACH section and restoring of HiJacking in DLL_PROCESS_DETACH section ?
Thnx for listening !
Cheers, Vishal
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
- The things you've tried are ok. The MyBitBlt function should call the initial BitBlt function for compatibility. If the module you're hooking is already mapped in the system process when the HookAllModules is called, then you don't need to hook LoadLibrary and such. LoadLibrary simply can tell you when this modules is loaded if not done yet.
- HookAllModules/HookFunctions can be called multiple times, as only the initial call will really do the hooking process.
- I highly suggest you try the code in the part 2, as it does : - Injecting the hooking dll in the debuggee process (have you done that ?) - Hook the function in all modules - Communicate with the server ( for debugging purpose, as it is not always easy to do)
- I think so
Sincerly, Cyril
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
:(Here the error output: Compiling... StdAfx.cpp Compiling... Hooked.cpp G:\x\xx\Hook0\ThreadSpy\Hooked.cpp(17) : warning C4273: 'MyLoadLibraryA' : inconsistent dll linkage. dllexport assumed. G:\x\xx\Hook0\ThreadSpy\Hooked.cpp(25) : warning C4273: 'MyLoadLibraryW' : inconsistent dll linkage. dllexport assumed. G:\x\xx\Hook0\ThreadSpy\Hooked.cpp(33) : warning C4273: 'MyLoadLibraryExA' : inconsistent dll linkage. dllexport assumed. G:\x\xx\Hook0\ThreadSpy\Hooked.cpp(41) : warning C4273: 'MyLoadLibraryExW' : inconsistent dll linkage. dllexport assumed. G:\x\xx\Hook0\ThreadSpy\Hooked.cpp(49) : warning C4273: 'MyGetProcAddress' : inconsistent dll linkage. dllexport assumed. G:\x\xx\Hook0\ThreadSpy\Hooked.cpp(62) : warning C4273: 'MyTextOutA' : inconsistent dll linkage. dllexport assumed. G:\x\xx\Hook0\ThreadSpy\Hooked.cpp(67) : warning C4273: 'MyTextOutW' : inconsistent dll linkage. dllexport assumed. ThreadSpy.cpp Generating Code... Linking... Creating library ../ThreadSpy.lib and object ../ThreadSpy.exp LINK : warning LNK4049: locally defined symbol ""int (__stdcall*__stdcall MyGetProcAddress(struct HINSTANCE__ *,char const *))(void)" (?MyGetProcAddress@@YGP6GHXZPAUHINSTANCE__@@PBD@Z)" imported LINK : warning LNK4049: locally defined symbol ""struct HINSTANCE__ * __stdcall MyLoadLibraryExW(unsigned short const *,void *,unsigned long)" (?MyLoadLibraryExW@@YGPAUHINSTANCE__@@PBGPAXK@Z)" imported LINK : warning LNK4049: locally defined symbol ""struct HINSTANCE__ * __stdcall MyLoadLibraryExA(char const *,void *,unsigned long)" (?MyLoadLibraryExA@@YGPAUHINSTANCE__@@PBDPAXK@Z)" imported LINK : warning LNK4049: locally defined symbol ""struct HINSTANCE__ * __stdcall MyLoadLibraryW(unsigned short const *)" (?MyLoadLibraryW@@YGPAUHINSTANCE__@@PBG@Z)" imported LINK : warning LNK4049: locally defined symbol ""struct HINSTANCE__ * __stdcall MyLoadLibraryA(char const *)" (?MyLoadLibraryA@@YGPAUHINSTANCE__@@PBD@Z)" imported LINK : warning LNK4049: locally defined symbol ""int __stdcall MyTextOutW(struct HDC__ *,int,int,unsigned short const *,int)" (?MyTextOutW@@YGHPAUHDC__@@HHPBGH@Z)" imported LINK : warning LNK4049: locally defined symbol ""int __stdcall MyTextOutA(struct HDC__ *,int,int,char const *,int)" (?MyTextOutA@@YGHPAUHDC__@@HHPBDH@Z)" imported
ThreadSpy.dll - 0 error(s), 14 warning(s)
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi rbrigger,
Where are the errors ??? 
It seems that u have got some warnings although [somtimes] programmers does not care abt some warnings !
Cheers, Vishal
|
| Sign In·View Thread·PermaLink | 1.00/5 (2 votes) |
|
|
|
 |
|
|
Hi
I dont have "Dbghelp.lib" and its dll also. what is alternative lib for this lib? I am looking for this on web.
Can your code inject new APi proc (new version of function in dll ) in all modules.....
I am looking for a way to prevent copy/paste of file?
can u suggest me which api i need to hook for that?
i can think of CopyFile A/w and may be createfile. Any other?
Thanks
Jetli conclusion means Coming to wrong Decision with confidence
|
| Sign In·View Thread·PermaLink | 1.20/5 (2 votes) |
|
|
|
 |
|
|
DbgHelp is in Platform SDK from MSDN (it is freely downloadable).
This code will exchange the function you're hooking by your function in all modules of the process when inserting the DLL. If you want to hook in all loaded module next, you should hook LoadLibrary too. See part II and III for more details.
You should hook CreateFile, CopyFile, MoveFile, DeleteFile, "DragAndDrop" functions (like RegisterDragDrop, etc).
Sincerly Cyril
|
| Sign In·View Thread·PermaLink | 2.33/5 (5 votes) |
|
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|