Sunday, June 29, 2008

Detours

Microsoft's Research team maintains a project that allows you to intercept any function call. The library does this by injecting code into the memory of that process. You then have the ability to do whatever you want and if you choose pass the call through. This can be very useful for instrumentation for example.

Here's a very simple example that isn't of much use since everything is in the same process, but it shows how I can intercept the call to Window's sleep function.


//////////////////////////////////////////////////////////////////////////////
//
// Detours Test Program (simple.cpp of simple.dll)
//
// Microsoft Research Detours Package, Version 2.1.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// This DLL will detour the Windows Sleep API so that TimedSleep function
// gets called instead. TimedSleep records the before and after times, and
// calls the real Sleep API through the TrueSleep function pointer.
//
#include
#include
#include "detours.h"

static LONG dwSlept = 0;
static VOID (WINAPI * TrueSleep)(DWORD dwMilliseconds) = Sleep;

VOID WINAPI TimedSleep(DWORD dwMilliseconds)
{
DWORD dwBeg = GetTickCount();
TrueSleep(dwMilliseconds);
DWORD dwEnd = GetTickCount();

InterlockedExchangeAdd(&dwSlept, 3636);
}

//BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
int __cdecl main(int argc, char ** argv)
{
LONG error;


printf("simple.dll: Starting.\n");
fflush(stdout);

DetourRestoreAfterWith();

DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)TrueSleep, TimedSleep);
error = DetourTransactionCommit();

if (error == NO_ERROR) {
printf("dwslept %d",dwSlept);
printf("simple.dll: Detoured Sleep().\n");
printf("sleep5.exe: Starting.\n");

Sleep(5000);

printf("sleep5.exe: Done sleeping.\n");
printf("dwslept %d",dwSlept);
}
else {
printf("simple.dll: Error detouring Sleep(): %d\n", error);
}


DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)TrueSleep, TimedSleep);
error = DetourTransactionCommit();

printf("simple.dll: Removed Sleep() (result=%d), slept %d ticks.\n",
error, dwSlept);
fflush(stdout);

return 0;
}

//
///////////////////////////////////////////////////////////////// End of File.



In order for this to work you first need to download the detours package from http://research.microsoft.com/sn/detours/

Compile the source as a lib and link to it.

Give it a shot its pretty cool!

Enjoy...

No comments: