3

元の投稿:

挿入されたDLL内からメンバー関数を迂回しようとしています。フックしようとしている関数のアドレスを取得しましたが、迂回ライブラリを介してフックするための適切な構文または方法を理解できません。エラーを表示している行にエラーメッセージを付けてコメントしました。

メンバー関数フックの迂回例のソースを読みました。これがこのコードの基になっていますが、何らかの理由で機能していません。

どんな助けでも大歓迎です、ありがとう!

#include <windows.h>
#include <detours.h>

class CDetour
{
public:
    bool My_MemFn(unsigned int unk1);
    static bool (CDetour::* Real_MemFn)(unsigned int);
};

bool CDetour::My_MemFn(unsigned int unk1)
{
        /* do stuff here */
    return (this->*Real_MemFn)(unk1);
}

typedef bool (CDetour::* MemFn_t)(unsigned int unk1);

MemFn_t CDetour::Real_MemFn= *(MemFn_t *)((void*)0x23234545);

BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
    switch (dwReason)
    {
        case DLL_PROCESS_ATTACH:
        {
            DetourTransactionBegin();
            DetourUpdateThread(GetCurrentThread());
            DetourAttach(&(PVOID&)CDetour::Real_MemFn, *(PBYTE*)&CDetour::My_MemFn); // ERROR: C2440: 'type cast' : cannot convert from 'bool __thiscall CDetour::* )(unsigned int)' to 'PBYTE *'
            DetourTransactionCommit();
            break;
        }
    }

    return TRUE;
}

解決:

#include <windows.h>
#include <detours.h>

typedef void (__thiscall * CClassFunction_t)(void *__this, unsigned int unk1);
CClassFunction_t Real_CClassFunction;

void __fastcall Mine_CClassFunction(void *__this, int edx, unsigned int unk1)
{
    Real_CClassFunction(__this, unk1);
}

template<typename T>
void HookFunction(const char *module, char *signature, T &fn_real, PVOID fn_mine)
{
    HookFunction<T>(DetourFindFunction(module, signature), fn_real, fn_mine);
}

template<typename T>
void HookFunction(DWORD address, T &fn_real, PVOID fn_mine)
{
    HookFunction<T>(reinterpret_cast<PVOID>(address), fn_real, fn_mine);
}

template<typename T>
void HookFunction(PVOID target, T &fn_real, PVOID fn_mine)
{
    fn_real = reinterpret_cast<T>(target);

    HookFunction<T>(fn_real, fn_mine);
}

template<typename T>
void HookFunction(T &fn_real, PVOID fn_mine)
{
    DetourAttach(&(PVOID&)fn_real, fn_mine);
}


void ApplyHooks()
{
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());

    DWORD function_address = 0x12345678;

    HookFunction<CClassFunction_t>(address, Real_CClassFunction, Mine_CClassFunction);

    DetourTransactionCommit();
}

BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
    switch (dwReason)
    {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        {
            DisableThreadLibraryCalls(hInstance);

            CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ApplyHooks, 0, 0, 0);

            break;
        }
    }

    return TRUE;
}
4

4 に答える 4

3

何時間も検索して解決策を見つけようとした後、私はこの素敵な小さな解決策を思いつきました:

#include <windows.h>
#include <detours.h>

typedef void (__thiscall * CClassFunction_t)(void *__this, unsigned int unk1);
CClassFunction_t Real_CClassFunction;

void __fastcall Mine_CClassFunction(void *__this, int edx, unsigned int unk1)
{
    Real_CClassFunction(__this, unk1);
}

template<typename T>
void HookFunction(const char *module, char *signature, T &fn_real, PVOID fn_mine)
{
    HookFunction<T>(DetourFindFunction(module, signature), fn_real, fn_mine);
}

template<typename T>
void HookFunction(DWORD address, T &fn_real, PVOID fn_mine)
{
    HookFunction<T>(reinterpret_cast<PVOID>(address), fn_real, fn_mine);
}

template<typename T>
void HookFunction(PVOID target, T &fn_real, PVOID fn_mine)
{
    fn_real = reinterpret_cast<T>(target);

    HookFunction<T>(fn_real, fn_mine);
}

template<typename T>
void HookFunction(T &fn_real, PVOID fn_mine)
{
    DetourAttach(&(PVOID&)fn_real, fn_mine);
}


void ApplyHooks()
{
    DetourTransactionBegin();
    DetourUpdateThread(GetCurrentThread());

    DWORD function_address = 0x12345678;

    HookFunction<CClassFunction_t>(address, Real_CClassFunction, Mine_CClassFunction);

    DetourTransactionCommit();
}

BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
    switch (dwReason)
    {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        {
            DisableThreadLibraryCalls(hInstance);

            CreateThread(0, 0, (LPTHREAD_START_ROUTINE)ApplyHooks, 0, 0, 0);

            break;
        }
    }

    return TRUE;
}
于 2012-06-19T08:41:00.220 に答える
2

使用してみてください:

union {
  bool (CDetour::*lpMyFunction)(unsigned int);
  PBYTE lpAddr;
} u;

ポインタを保存して、u.lpMyFunctionから取得しますu.lpAddr

これでコンパイルの問題は解決しますか?

于 2012-06-18T16:41:09.903 に答える
0

ええ、私は実際にそれらのキャストが嫌いなので、私は自分で作りました:

// Cast a member function pointer that cannot have a reference taken to a void *
template <typename RET_TYPE, typename CLASS, typename...ARGs>
void* castToVoidPtr(RET_TYPE(CLASS::*&&pOriginalFunction)(ARGs...))
{
    union
    {
        RET_TYPE(CLASS::*pMemFn)(ARGs...);
        void* voidPtr;
    } cast = { pOriginalFunction };
    static_assert(sizeof(cast.pMemFn) == sizeof(cast.voidPtr), "Cannot cast this member function pointer to a void*.  Not the same size.");
    return cast.voidPtr;
}

// Cast a member function pointer to a void*&
template <typename RET_TYPE, typename CLASS, typename...ARGs>
void*& castToVoidPtr(RET_TYPE(CLASS::*&pOriginalFunction)(ARGs...))
{
    union
    {
        RET_TYPE(CLASS::*&pMemFn)(ARGs...);
        void*& voidPtr;
    } cast = { pOriginalFunction };
    static_assert(sizeof(cast.pMemFn) == sizeof(cast.voidPtr), "Cannot cast this member function pointer to a void*.  Not the same size.");
    return cast.voidPtr;
}

ソリューションの唯一の問題は、余分なDWORDをスタック(EDXレジスタ)にプッシュしていることです。これは不要です。これらのキャストは、使用するすべての場合に機能するはずです。私が収集したところ、複数の継承されたクラス関数では機能しません。これは、迂回に使用する可能性が高いものではなく、試してみると主張します。 。

これにより、次のことが可能になります。

DetourAttach(&castToVoidPtr(CDetour::Real_MemFn), castToVoidPtr(&CDetour::My_MemFn));
于 2015-04-19T09:16:38.003 に答える
0

"void* castToVoidPtr(RET_TYPE(CLASS::*&&pOriginalFunction)(ARGs...))"

これはまさにあなたが書きたいものですか?VS2008では、コンパイル時にエラーが発生します。

于 2015-05-05T07:26:24.087 に答える