gpt4 book ai didi

c++ - 如何在 C++ 中使用 thunk 将此指针绑定(bind)到静态成员函数

转载 作者:太空宇宙 更新时间:2023-11-04 13:10:09 24 4
gpt4 key购买 nike

我正在尝试使用 C++ 和 Win32 API 创建一个 thunk,它将此指针绑定(bind)到静态成员函数,因此我可以将该函数用作回调。

现在,我有一个适用于 x64 的 thunk,它通过将 r9 寄存器(对应于函数的第 4 个参数)的值设置为该指针的地址来工作。

但是我对 x86 的 thunk 有问题,我尝试设置 [esp+10h] 的值(也对应于第 4 个参数)。

这是砰的一声:

#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)

下面是使用 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);
}
};

这是回调用户:

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

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

但是,当我运行程序时,它给了我失败:

Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

我该如何解决这个问题?
谢谢。

最佳答案

此失败是由 stdcall 约定引起的。调用者希望被调用者清理 3 个参数值的堆栈,而被调用者(你的回调)清理 4 个参数导致 esp 去错误的位置。此外,您不能只写入 esp+10h,因为调用者可能正在使用它。

现在这里有一个替代的想法:你不能直接将 ecx 设置为 this 并直接调用成员函数(假设它使用 stdcall 约定)?

更新:或者您可以将 This 作为静态成员函数的第一个参数,使其最接近栈顶;然后 thunk 可以修改堆栈,使其看起来像一个带有 4 个参数的 stdcall 函数调用。它看起来像

pop eax
push This
push eax
jmp func

关于c++ - 如何在 C++ 中使用 thunk 将此指针绑定(bind)到静态成员函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40318570/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com