WEB开发网
开发学院软件开发VC 通用Thunk 阅读

通用Thunk

 2010-07-15 20:45:23 来源:WEB开发网   
核心提示:更多详细信息 见 ThunkBase.cpp 3.栈的生长在Win32平台下,栈朝着低地址生长,通用Thunk(5),也就是说,当栈增加N ESP就减少N,(参数和返回地址也由fun(1212)准备好,而且 C::fun1 将会使用RET 4 返回到 RET_ADD,并正确的平衡堆栈,反之亦然,我们来设计这个类clas

更多详细信息 见 ThunkBase.cpp 3.栈的生长在Win32平台下,栈朝着低地址生长。也就是说,当栈增加N ESP就减少N,反之亦然。我们来设计这个类

class ThisToStd
{
public:
ThisToStd(const void *Obj = 0,int memFunc = 0);
const void *Attach(const void *newObj);
int Attach(int newMemFunc);
private:
#pragma pack( push , 1) // 强制编译器使用1字节长度对齐结构
unsigned char MOV_ECX;
const void *m_this;
unsigned char JMP;
const int m_memFunc;
#pragma pack( pop ) // 恢复对齐
};
ThisToStd:: ThisToStd(const void *Obj,int memFunc)
: MOV_ECX(0xB9),JMP(0xE9) {
 Attach(Obj); // 设置this指针
Attach(memFunc); // 设置成员函数地址(使用偏移)
}
const void* ThisToStd::Attach(const void *newObj) {
 const void *oldObj = m_this;
 m_this = newObj;
 return oldObj;
}
int ThisToStd::Attach(int newMemFunc) {
 int oldMemFunc = GetTransferDST(&JMP);
SetTransferDST(&JMP,newMemFunc);
return oldMemFunc;
}
我们以如下方式使用这个类 :typedef void ( __stdcall * fun1)(int);
class C { public : void __thiscall fun1(int){} };
C obj;
ThisToStd thunk;
thunk.Attach(&obj); // 假设 &obj = OBJ_ADD
int memFunc = PointerToInt32(&C::fun1); //假设memFunc = MF_ADD
thunk.Attach(memFunc); // thunk.m_memFunc 将被设置为MF_ADD – (&t.JMP)-5
fun1 fun = reinterpret_cast<fun1>(&thunk); //假设 &thunk = T_ADD
fun(1212); // 与 obj.fun(1212) 有同样效果
它是如何工作的,当CPU执行到 fun(1212); 机器码如下:PUSH 1212;
CALL DWORD PTR [fun];
0x50000 : … ; 假设 RET_ADD = 0x50000
// CALL DOWRD PTR [fun] 与CALL(0xE8) offset(dword) 不同
//我们只需要知道: 它将RET_ADD压栈,然后跳转到T_ADD

执行完这2条指令后,栈是这个样子 :


1212
RET_ADD <- ESP

下一条被执行的指令,是在thunk 的地址处 (T_ADD)

thunk的第1字节是 “const unsigned char MOV_ECX” –被初始化为0xB9.

紧接着的4字节是 “const void *m_this”

在 thunk.Attach(&obj); 后,m_this = OBJ_ADD

这5字节组成一条合法的指令

T_ADD : MOV ECX,OBJ_ADD

thunk的第6字节是 “const unsigned char JMP” –被初始化为0xE9.

紧接着的4字节是 “const int m_memFunc”

将被 thunk.Attach(memFunc) 修改

这5字节又组成一条合法指令

T_ADD+5 : JMP offset

offset = MF_ADD - &thunk.JMP – 5 ( 由 thunk.Attach() 和SetTransferDST 设置)

所以,这条指令执行后,下一条被执行指令将在这里:

MF_ADD : …

现在,this指正已经准备好,(参数和返回地址也由fun(1212)准备好,而且 C::fun1 将会使用RET 4 返回到 RET_ADD,并正确的平衡堆栈。

所以,它成功了!

上一页  1 2 3 4 5 6 7 8 9 10  下一页

Tags:通用 Thunk

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接