简体   繁体   English

如何使用c ++中的thunk将此指针绑定到静态成员函数

[英]How to bind this pointer to static member function using thunk in c++

I'm trying to create a thunk with C++ and Win32 API, that binds this pointer to static member function, so I can use that function as a callback. 我正在尝试使用C ++和Win32 API创建一个thunk,它将此指针绑定到静态成员函数,因此我可以将该函数用作回调。

Now, I have a working thunk for x64, it works by setting the value of r9 register (corresponds to 4th parameter of a function) to the address of this pointer. 现在,我有一个x64的工作thunk,它的工作原理是将r9寄存器的值(对应于函数的第4个参数)设置为该指针的地址。

But I'm having a problem with thunk for x86, I tried to setting the value of [esp+10h] (also corresponds to 4th parameter). 但是我遇到了x86的thunk问题,我试图设置[esp + 10h]的值(也对应于第4个参数)。

Here's the thunk: 这是thunk:

#pragma pack(push, 1)
struct THUNK {
    DWORD mov;               // mov dword ptr[esp+10h], pThis
    DWORD pThis;
    BYTE  jmp;               // jmp relproc
    DWORD relproc;
}
#pragma pack(pop)

And here's the class that uses the thunk: 这是使用thunk的类:

class foo {
    void callback_impl(int a, int b, int c) {
        ...
    }
    static void __stdcall callback(int a, int b, int c, foo *This) {
        This->callback_impl(a, b, c);
    }
public:
    THUNK *thunk;
    foo() {
        thunk = (THUNK*)VirtualAlloc(NULL, sizeof(THUNK), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        thunk->mov = 0x102444C7;
        thunk->pThis = (DWORD)this;
        thunk->jmp = 0xe9;
        thunk->relproc = DWORD((INT_PTR)&foo::callback - ((INT_PTR)thunk + sizeof(THUNK)));
        FlushInstructionCache(GetCurrentProcess(), this, sizeof(THUNK));
    }
    ~foo() {
        VirtualFree(thunk, sizeof(THUNK), MEM_DECOMMIT);
    }
};

And here's the callback user: 这是回调用户:

void callback_user(void(__stdcall *callback)(int, int, int)) {
    ...
}

// foo f;
// callback_user((void(__stdcall*)(int, int, int))f.thunk);

However, when I ran the program, it gave me the failure: 但是,当我运行该程序时,它给了我失败:

Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. 运行时检查失败#0 - ESP的值未在函数调用中正确保存。 This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention. 这通常是调用使用一个调用约定声明的函数和使用不同调用约定声明的函数指针的结果。

How can I solve this problem? 我怎么解决这个问题?
Thanks. 谢谢。

This failure is caused by stdcall convention. 此失败是由stdcall约定引起的。 Caller expects callee to clean up 3 arguments worth of stack while callee (your callback) cleans up 4 arguments causing esp to go to wrong location. 调用者希望被调用者清理3个参数堆栈,而被调用者(你的回调)清理4个参数,导致esp进入错误的位置。 Also you cannot just write to esp+10h because caller might be using it. 此外,您不能只写入esp+10h因为调用者可能正在使用它。

Now here is alternative idea: can't you just set ecx to this and call member function directly (provided it uses stdcall convention)? 现在这里有另一种想法:你不能只将ecx设置为this并直接调用成员函数(假设它使用stdcall约定)吗?

UPDATE: Or you can put This as a first argument to your static member function so it closest to a stack top; 更新:或者您可以This作为静态成员函数的第一个参数,以使其最接近堆栈顶部; thunk then can modify stack to make it look like a stdcall function call with 4 arguments. thunk然后可以修改堆栈,使其看起来像一个带有4个参数的stdcall函数调用。 It will look something like 它看起来像

pop eax
push This
push eax
jmp func

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM