Darth Voidpointer
Darth Voidpointer

Reputation: 116

How to obtain instance specific detour pointer?

I am using MS Visual Studio 2022 and the MS Detours library to detour some functions. The detouring works fine, but I would like to collect some statistics per function, in a scaleable, performant and maintainable way.

Here's a simple functional example, hacked down for brevity, hopefully without mistakes added:

struct funcRef {
    const char* funcName;
    std::atomic<uint64_t> numCalls;
};
extern struct funcRef funcStats[];

#define FUNC_CALLED(name, index) \
        const int funcIndex = index; \
    funcStats[funcIndex].funcName = name; \
    std::atomic_fetch_add(&funcStats[funcIndex].numCalls, 1);


typedef void (WINAPI *KERNSIFP)(LPSYSTEM_INFO lpSystemInfo);
static KERNSIFP TrueGetNativeSystemInfo = NULL;

void WINAPI MyGetNativeSystemInfo(LPSYSTEM_INFO lpSystemInfo)
{
    FUNC_CALLED(__FUNCTION__, __COUNTER__)

    return TrueGetNativeSystemInfo(lpSystemInfo);
}

const int NUM_DETOURS = __COUNTER__;

struct funcPair {
    void *orig;
    void *fake;
};

struct funcRef funcStats[NUM_DETOURS];
struct funcPair detourFuncs[NUM_DETOURS] = {
    {(void *)&TrueGetNativeSystemInfo, MyGetNativeSystemInfo},
};

void LoadDetours()
{
    int i;

    DPRINTF(DLOG_INFO, "Detouring functions.\n");

    kern32Lib = LoadLibraryW(L"kernel32.dll");
    if (!kern32Lib)
        return;

    TrueGetNativeSystemInfo = (KERNSIFP) GetProcAddress(kern32Lib, "GetNativeSystemInfo");

    for (i = 0; i < NUM_DETOURS; i++)
        if (detourFuncs[i].orig)
            DetourFunction(detourFuncs[i].orig, detourFuncs[i].fake);
}

void UnloadDetours()
{
    int i;

    DPRINTF(DLOG_INFO, "Restoring functions.\n");

    for (i = 0; i < NUM_DETOURS; i++)
        if (detourFuncs[i].orig)
            RestoreFunction(detourFuncs[i].orig, detourFuncs[i].fake);

    FreeLibrary(kern32Lib);
}

As can be seen, in this very minimal example, I am keeping tabs of the function name, and increment a counter each time it is called. I'm relying on the preprocessor to identify the function in the global statistics structure array based on its location in the code using __COUNTER__.

This works fine, but it's a little touchy. To add or remove a function I need to touch quite a few different lines of code, it's pretty easy to make a mistake. I would also like to modularize this as I may have hundreds of detoured functions. There are a few ways I can think of, most boil down to removing that __COUNTER__ and instead having what amounts to a "this" pointer passed in to my function (or perhaps embedded on the stack?) I'm not quite sure what the best approach is.

Is there a better way to do what I'm doing?

Upvotes: 1

Views: 72

Answers (0)

Related Questions