如何在C ++中使用thunk将此指针绑定到静态成员函数 [英] How to bind this pointer to static member function using thunk in c++

查看:67
本文介绍了如何在C ++中使用thunk将此指针绑定到静态成员函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

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

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.

但是我对于x86的thunk有问题,我尝试设置[esp + 10h]的值(也对应于第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).

这是重击:

#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的类:

And here's the class that uses the 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);

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

However, when I ran the program, it gave me the failure:

运行时检查失败#0-在整个函数调用中ESP的值未正确保存.这通常是由于使用一种调用约定声明的函数和使用另一种调用约定声明的函数指针进行调用的结果.

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.

如何解决此问题?
谢谢.

How can I solve this problem?
Thanks.

推荐答案

此故障是由stdcall约定引起的.呼叫者希望被呼叫者清理3个值得堆栈的参数,而被呼叫者(您的回调)清理4个导致esp转到错误位置的参数.同样,您不能只写 esp + 10h ,因为调用者可能正在使用它.

This failure is caused by stdcall convention. 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. Also you cannot just write to esp+10h because caller might be using it.

现在这是另一种想法:您不能只是将 ecx 设置为 this 并直接调用成员函数(前提是它使用stdcall约定)?

Now here is alternative idea: can't you just set ecx to this and call member function directly (provided it uses stdcall convention)?

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

UPDATE: Or you can put This as a first argument to your static member function so it closest to a stack top; thunk then can modify stack to make it look like a stdcall function call with 4 arguments. It will look something like

pop eax
push This
push eax
jmp func

这篇关于如何在C ++中使用thunk将此指针绑定到静态成员函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆