为__thiscall写thunk

时间:2014-12-17 20:08:15

标签: c++ visual-c++ assembly x86

我试图使用结构为__thiscall写一个thunk。

我测试了这个结构并且它可以工作:

#pragma pack(push, 1)
struct Thunk
{
   unsigned short leaECX;       
   unsigned long pThis;     
   unsigned char movEAX;       
   unsigned long pMemFunc;    
   unsigned short jmpEAX;       
};
#pragma pack(pop)

我使用以下字节码填充此结构(我在网上找到):

//Load effective address of this to ECX
//because __thiscall expect to get 'this' in ECX
leaECX = 0x0D8D;
pThis = here goes 'this' pointer;
//Move member function pointer to EAX
movEAX = 0xB8;
pMemFunc = here goes pointer to member function;
//Jump to member function
jmpEAX = 0xE0FF;

我的问题是,movEAX和jmpEAX指令是否可以用汇编call指令的字节码替换?

如果是这样,我该怎么做?

我使用VirtualAlloc分配此结构,并标记MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE

这是一种紧凑的方式还是浪费内存(分配整页而不是sizeof(Thunk))?

1 个答案:

答案 0 :(得分:0)

您可以使用call但当然执行将返回到您的thunk,因此您之后需要更多代码。此外,如果你摆脱了mov我认为你会想要做call address变体,在这种情况下要注意使用相对编码的事实,所以你不能只是戳你的地址记忆。

您可以使用以下内容切换到相对跳转以摆脱mov

#pragma pack(push, 1)
struct Thunk
{
   unsigned short leaECX;       
   unsigned long pThis;     
   unsigned char jmp; 
   unsigned long pOffset;
};
#pragma pack(pop)

//Load effective address of this to ECX
//because __thiscall expect to get 'this' in ECX
leaECX = 0x0D8D;
pThis = here goes 'this' pointer;
jmp = 0xE9;
pOffset = (char*)address_of_member - (char*)&thunk.pOffset - 4;

由于内存保护是页面粒度,因此您至少需要一个页面(VirtualAlloc会自动向您求助)。如果你有多个thunks,你当然可以将它们打包到同一页面。