我试图使用结构为__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)
)?
答案 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,你当然可以将它们打包到同一页面。