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.
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.
But I'm having a problem with thunk for x86, I tried to setting the value of [esp+10h] (also corresponds to 4th parameter).
Here's the 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:
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. 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. 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.
Now here is alternative idea: can't you just set ecx
to this
and call member function directly (provided it uses stdcall convention)?
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.