Ganxo is an opensource API hooking framework. In Catalan, Ganxo means hook and is pronounced like you pronounce: "Gun show". Ganxo uses Capstone disassembler for its disassembly requirements.
- Ganxo is transactional. No hooking side effects take place until the transaction is committed
- Written in C and aims to be light and portable. Although for now only Windows is supported
- Ganxo has a rich api: simple data structures APIs, memory APIs, disassembly APIs
- Heavily documented source code which is ideal for learning how to build API hooking frameworks
-
Clone Ganxo from: http://github.com/PassingTheKnowledge/Ganxo
-
Clone the thirdparty dependencies:
git submodule update --init --recursive
-
Open Ganxo.sln solution
-
Right click and change the general configuration of the capstone project and select a supported compiler
-
Change the preprocessor settings to only have x86 and diet Capstone:
CAPSTONE_USE_SYS_DYN_MEM;CAPSTONE_X86_ATT_DISABLE;CAPSTONE_DIET;CAPSTONE_X86_REDUCE;CAPSTONE_HAS_X86
-
When ready, righ-click on the solution and "Build all"
Refer to simple.cpp and test_hook project
This is an exmaple program that hooks Sleep() and MessageBoxA()
#include <Ganxo.h>
typedef VOID(WINAPI *Sleep_proto)(DWORD);
typedef int (WINAPI *MessageBoxA_proto)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
Sleep_proto orig_Sleep = Sleep;
VOID WINAPI My_Sleep(DWORD dwMilliSecs)
{
printf("MySleep() triggered! calling original sleep...");
orig_Sleep(dwMilliSecs);
printf("done!\n");
}
MessageBoxA_proto orig_MessageBoxA = MessageBoxA;
int WINAPI my_MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
printf("MessageBoxA(hWnd=%08p, lpText='%s', lpCaption='%s', uType=%04X)\n",
hWnd, lpText, lpCaption, uType);
return IDOK;
}
int main()
{
gnx_err_t err = gnx_init();
if (err != GNX_ERR_OK)
{
printf("Failed to initialize!\n");
return -1;
}
// Create a new workspace instance
gnx_handle_t gnx;
if (gnx_open(&gnx) != GNX_ERR_OK)
{
printf("Failed to create workspace\n");
return -1;
}
gnx_handle_t transaction;
gnx_transaction_begin(gnx, &transaction);
// Hook
err = gnx_transaction_add_hook(
transaction,
(void **)&orig_Sleep,
My_Sleep);
err = gnx_transaction_add_hook(
transaction,
(void **)&orig_MessageBoxA,
my_MessageBoxA);
err = gnx_transaction_commit(transaction);
// Call hooked functions
printf("main(): calling Sleep()\n");
::Sleep(10);
MessageBoxA(0, "Hello", "Info", MB_OK);
Start a new transaction for the sake of removing the hooks, remove the hooks and commit the transaction:
// Unhook
gnx_transaction_begin(gnx, &transaction);
gnx_transaction_remove_hook(
transaction,
(void **)&orig_Sleep);
gnx_transaction_remove_hook(
transaction,
(void **)&orig_MessageBoxA);
gnx_transaction_commit(transaction);
gnx_close(gnx);
return 0;
}