Thunk技術C++ CallBack

// callbackThunk.cpp : Defines the entry point for the console application.
//
#include "stdio.h"
#include "stdlib.h"
class A;
typedef unsigned long DWORD;
typedef unsigned char BYTE;
typedef void (*FuncA)(int a);
typedef void (A::*AFuncB)(int a);
typedef void (__stdcall *FuncB)(int a);
#pragma pack(push,1)
struct Thunk
{
    DWORD    _mov; //mov [esp+4]
    DWORD    _thisPtr; //this
    BYTE    _jump;    //call
    DWORD    _funcAdress; //adress
};
struct Thunk2
{
    BYTE    _mov; //mov ecx
    DWORD    _thisPtr; //this
    BYTE    _jump;    //call
    DWORD    _funcAdress; //adress
};
#pragma pack(pop)
class A
{
public:
    //方法: 取代第一個參數[esp+4]為this指針
    //限制: 原有的第一參數被取代, 如果funciton沒有參數就不能使用
    void init(FuncA func)
    {
        _thunk._mov = 0x042444C7;
        _thunk._thisPtr = (DWORD)this; //mov [esp+4], this
        _thunk._jump = 0xe9;
        _thunk._funcAdress = (int)func - ((DWORD)&_thunk._funcAdress + sizeof(DWORD));
    }
    //方法: 用stdcall取代thiscall,但模疑thiscall加入this指針至ecx
    void init2(AFuncB func)
    {
        _thunk2._mov = 0xb9;
        _thunk2._thisPtr = (DWORD)this; //mov ecx, this
        _thunk2._jump = 0xe9;
        DWORD memberFunction;
        __asm
        {
            push eax
            mov eax, func
            mov dword ptr [memberFunction], eax
            pop eax
        }
        _thunk2._funcAdress = memberFunction -((DWORD)&_thunk2._funcAdress + sizeof(DWORD));
    }
    static void funcA(int a)
    {
        printf("A::funcA called\n");
        A* instanceA = (A*)a; //參數其實已轉變為this指針
        instanceA->funcB(1);
    }
    void funcB(int a)
    {
        printf("A::funcB called\n");
    }
    Thunk        _thunk;
    Thunk2        _thunk2;
};
int main(int argc, char* argv[])
{
    A a;
    a.init(&A::funcA);
    FuncA func = (FuncA)(&a._thunk);
    func(1);
    a.init2(&A::funcB);
    FuncB func2 = (FuncB)(&a._thunk2);
    func2(1);
    system("pause");
    return 0;
}

你可能感兴趣的:(C++)