2010-09-15 51 views
2
void foo(int a) 
{ printf ("In foo, a = %d\n", a); } 

unsigned char code[9]; 
* ((DWORD *) &code[0]) = 0x042444FF; /* inc dword ptr [esp+4] */ 
       code[4] = 0xe9;  /* JMP */ 
* ((DWORD *) &code[5]) = (DWORD) &foo - (DWORD) &code[0] - 9; 
void (*pf)(int/* a*/) = (void (*)(int)) &code[0]; 
pf (6); 

任何人都知道上述代码在哪里6增加了1为什么输出是“In foo,a = 7”?

+0

十六进制常量是机器码。 – starblue 2010-09-15 08:39:16

回答

3

foo(),以及你的thunk,使用__cdecl调用转换,这需要调用者在堆栈上推参数。因此,当调用pf(6)时,6通过PUSH 6指令被压入堆栈,然后通过CALL pf指令输入该thunk。当进入thunk时,6在堆栈上占用的内存位于ESP+4,即距堆栈指针寄存器ESP的当前值4个字节。 thunk的第一条指令是增加ESP+4指向的值,因此值'6'递增为'7'。 foo()然后由thunk的JMP foo指令输入。 foo()然后看到其a参数为7,而不是原来的6,因为thunk修改了foo()的调用堆栈。

+0

为什么'6'位于'ESP + 4'?而且似乎thunk正在调用'JMP(DWORD)&foo - (DWORD)&code [0] - 9'而不是'JMP foo',对吧? – COMer 2010-09-15 06:18:58

+0

@COMer因为这是C调用约定的工作原理。参数被推送到堆栈,然后返回地址。当你第一次输入你的代码时,sp指向返回地址。随着堆栈向下增长,该参数立即位于内存中的返回地址之上。返回地址是4个字节宽,因此参数在'esp + 4'。 – JeremyP 2010-09-15 08:25:13

相关问题