I’ve downloaded and compiled the Microsoft detouring library. Inside my project I’ve included the header file and added the .lib file as a dependency. Everything compiles without errors. Now I’ve been trying to detour DrawText, but for some reason that detoured function doesn’t get called at all. Similiarly I tried detouring the Sleep function and that worked as intended and the function I detoured to was called.
I’m not very well-versed in the business of API programming nor any other low level activities. I suspect it might have something to do with the fact that I’m trying to do this inside a console application instead of having the detouring done inside a DLL. I just find it strange that it would be able to detour Sleep in that case.
Is there something wrong with my approach or does the fault lie in the code?
#include <windows.h>
#include <stdio.h>
#include "detours.h"
int ( WINAPI *Real_DrawText )(HDC a0, LPCSTR a1, int a2, LPRECT a3, UINT a4) = DrawTextA;
int Mine_DrawText(HDC hdc, LPCSTR text, int nCount, LPRECT lpRect, UINT uOptions)
{
printf("TEST");
return Real_DrawText(hdc, text, nCount, lpRect, uOptions);
}
int main(int argc, char **argv)
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)Real_DrawText, Mine_DrawText);
DetourTransactionCommit();
printf("Calling Sleep\n");
Sleep(1000);
printf("Second callout");
Sleep(5000);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)Real_DrawText, Mine_DrawText);
DetourTransactionCommit();
return 0;
}
Based on your code-example, it seems you’re only detouring your own process. Therefore detouring DrawText doesn’t output anything. Perhaps, you need to inject your code to desired target’s process memory and detour the API call from there. For example, you can create system wide CBT hook which works kind of a.. launch point to your detouring needs. Something like this, to point you out a direction:
LRESULT CALLBACK CBTProcedure(int nCode, WPARAM wParam, LPARAM lParam) { if (nCode < 0) return CallNextHookEx(g_hHook, nCode, wParam, lParam); else if (!g_pClient) return 0; HWND hWnd = (HWND)wParam; if (!hWnd) return 0; switch (nCode) { case HCBT_ACTIVATE: /** Here, you can check up against the handle to see, * if the target window is the one you're looking for... * */ if (!g_pClient->IsRegisteredWindow(hWnd)) if (g_pClient->RegisterWindow(hWnd)) { } break; case HCBT_DESTROYWND: if (g_pClient->IsRegisteredWindow(hWnd)) g_pClient->UnregisterWindow(hWnd); break; } return 0; } bool __0XYOUROWN_API InstallHook() { // Call this one from your main process; set's up the system-wide hook. g_hHook = SetWindowsHookEx(WH_CBT, (HOOKPROC)CBTProcedure, g_hInstance, 0); /** #pragma data_seg("Shared") * HHOOK g_hHook = NULL; * #pragma data_seg() */ return g_hHook != NULL; } /** The actual DLL... * * */ BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: g_hInstance = (HINSTANCE)hModule; if (::GetModuleHandle(_T("THEDESIREDMODULE.EXE")) != NULL) { g_pClient = new Client(); if (g_pClient) { InitializeCriticalSection(&g_CriticalSection); // You can setup a critic. sec. for later synchronization... DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourAttach(&(PVOID&)Real_DrawTextW, Mine_DrawTextW); DetourTransactionCommit(); } } break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: if (::GetModuleHandle(_T("THEDESIREDMODULE.EXE")) != NULL) { if (g_pClient) { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourDetach(&(PVOID&)Real_DrawTextW, Mine_DrawTextW); DetourTransactionCommit(); delete g_pClient; g_pClient = NULL; } } break; } }