First, look the following code:
#include <iostream>
#pragma pack(push, 1)
class MachineCode {
public:
#pragma pack(pop, 1)
typedef void (__stdcall *ProcCall)(void);
class Adapter {
public:
Then, I use the following code to call X::DefProcCall function:
Adapter x;
x.Init (&Adapter::DefProcCall, &x);
ProcCall call = x.GetProcCaller();
call();
The all magic is at 'reinterpret_cast<ProcCall>(
#include <iostream>
#pragma pack(push, 1)
class MachineCode {
public:
unsigned char jmp_;
unsigned long proc_;
};#pragma pack(pop, 1)
typedef void (__stdcall *ProcCall)(void);
class Adapter {
public:
int Init(void* proc, void* pthis) {
ProcCall GetProcCaller(void) {
static void DefProcCall(void) {
private: thunk_.jmp_ = 0xE9;
thunk_.proc_ = (unsigned long)proc - ((unsigned long)pthis + sizeof(thunk_));
::FlushInstructionCache(::GetCurrentProcess(), pthis, sizeof(thunk_));
return (true);
}thunk_.proc_ = (unsigned long)proc - ((unsigned long)pthis + sizeof(thunk_));
::FlushInstructionCache(::GetCurrentProcess(), pthis, sizeof(thunk_));
return (true);
ProcCall GetProcCaller(void) {
return (reinterpret_cast<ProcCall>(&thunk_));
}static void DefProcCall(void) {
std::cout<<"in Adapter::DefProcCall.\n"<<std::endl;
}MachineCode thunk_;
};Then, I use the following code to call X::DefProcCall function:
Adapter x;
x.Init (&Adapter::DefProcCall, &x);
ProcCall call = x.GetProcCaller();
call();
The all magic is at 'reinterpret_cast<ProcCall>(
&thunk_)' in GetProcCaller member function of Adapter class and two data members in MachineCode class. Directly, generates such IA-32 code 'call dword ptr [function-address]' when C++ compiler meet 'call()' statement. Because of the function-address exactly is the address of the thunk_ which is the first data member of Adapter class. So the machine code in thunk_ has been executed.
The jmp_ data member of MachineCode class stores 0xE9 that is 'jmp' instruction in IA-32. And the proc_ data member stores relative address since the ending address of the thunk_ which in Adapter class. So whole MachineCode class generate such IA-32 code 'jmp address'.
The jmp_ data member of MachineCode class stores 0xE9 that is 'jmp' instruction in IA-32. And the proc_ data member stores relative address since the ending address of the thunk_ which in Adapter class. So whole MachineCode class generate such IA-32 code 'jmp address'.