I won't go into all the interesting things you can do with API hooking as there are lots of articles on CodeProject already about that. But, here's a quick and easy way to do it under Windows CE / Windows Mobile.
You need platform builder for
pkfuncs.h and
psyscall.h and access to the private sources for
kernel.h. Fortunately for the rest of you, however, all these things can be found by some quick Internet searches, too.
This example will subvert the
GetTickCount()
API to print 12345 and then restore it to its original state.
#include <psyscall.h>
#include <pkfuncs.h>
#include <kernel.h>
DWORD WINAPI Hook_GetTickCount( VOID )
{
return 12345;
}
void SwapPFN( PFNVOID* a, PFNVOID* b )
{
PFNVOID temp = *a;
*a = *b;
*b = temp;
}
int _tmain( int argc, _TCHAR* argv[] )
{
DWORD old_permissions = ::SetProcPermissions( 0xFFFFFFFF );
::SetKMode( TRUE );
CINFO** api_sets = ( CINFO** )( UserKInfo[ KINX_APISETS ] );
CINFO* win32_api = api_sets[ SH_WIN32 ];
PFNVOID pfnHook_GetTickCount = ( PFNVOID )Hook_GetTickCount;
SwapPFN( &win32_api->m_ppMethods[ W32_GetTickCount ], &pfnHook_GetTickCount );
NKDbgPrintfW( L"Hooked: %d\r\n", ::GetTickCount() );
SwapPFN( &win32_api->m_ppMethods[ W32_GetTickCount ], &pfnHook_GetTickCount );
NKDbgPrintfW( L"Unhooked: %d\r\n", ::GetTickCount() );
::SetProcPermissions( old_permissions );
::SetKMode( FALSE );
return 0;
}
For me, this prints:
Hooked: 12345
Unhooked: 2596716
Unfortunately, the reason this is easy is because it's incomplete. While this will work for
your process, any other process that tries to call
GetTickCount()
while you've hooked it will crash and burn. Why? Because the function pointer address we put in the kernel API table is local to our process. Other processes can't access memory in our process.
The solution to that little conundrum will be posted soon!
Enjoy!
PaulH