chainHook library
ChainHook is my own library that I wrote somewhere around 2001 in order to intercept calls on c-style API functions. Originally it was meant for ComTrace but has since been used for Developer Playground and ieHTTPHeaders as well (and many, many others that I never came around to publish). Works on Windows 2000 and Windows XP (could be tweaked for NT4).
It uses a technique known as API patching which basically means that in order to intercept, or hook, a function, I will replace the first bytes in that function with a JMP statement. That will make the execution of the intercepted function jump to code supplied by me. Once I've done what ever I need to do (most likely some tracing) in my hook code, I will call a chain function that contains the instructions I needed to overwrite in order to make the JMP. I've only implemented support for 32-bit instructions (feel free to add 64-bit support on your own).
Ivo Ivanov wrote about it back in 2002. His article is well written and to the best of my knowledge complete. Therefore, I will not waste any time and space here to explain API patching in detail (go read what Ivo wrote).
Download
You may download the source. It is a visual Studio 2003 project and when compiled, it will generate a lib-file you may use in other projects to link against (just include the chainHookAPI.h file in any consumer app). The lib-files are linked against the runtime library with Multi-threaded Debug (/MTd) in debug and Multi-threaded (/Mt) in Release build.
You may use the code in any way you like, but use as-is and without any warranties. I've used it extensively to intercept loads and loads of exported API functions, but would probably never, ever, use it in any production environment (you may take that as a warning).
I should probably say that I only included what I needed to make ComTrace, ieHTTPHeaders, Developer Playground and some other tools. Feel free to add what you are missing.
Usage example
Below is an example on how to intercept the MessageBox function in user32.dll.
#include "stdafx.h"
#include "atlbase.h"
#include "chainHookAPI.h"
typedef int (__stdcall* procMessageBox)(HWND, LPCTSTR, LPCTSTR, UINT);
procMessageBox g_chainMessageBox = NULL;
// this is my hook - it will be called whenever any code tries to call the MessageBox function
int __stdcall MyMessageBoxHook(HWND wnd, LPCTSTR pszText, LPCTSTR pszTitle, UINT flags)
{
ATLTRACE(_T("MessageBox called: %s\n"), pszText);
return g_chainMessageBox(wnd, pszText, pszTitle, flags); // call the real function
}
int _tmain(int argc, _TCHAR* argv[])
{
// go and hook the MessageBox function
g_chainMessageBox = (procMessageBox)CHHookProc(GetCurrentProcess(), ::MessageBox, MyMessageBoxHook);
MessageBox(NULL, "Who is calling?", "ET perhaps", MB_OK);
return 0;
}