10/18/2007

Organize IA-32 machine code in C++ class

First, look the following code:

#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) {
thunk_.jmp_ = 0xE9;
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;
}

private:
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'.