tags:

views:

102

answers:

1
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);

Anyone knows where in the above code 6 is incremented by 1?

+3  A: 

foo(), as well as your thunk, uses the __cdecl calling conversion, which requires the caller to push parameters on the stack. So when pf(6) is called, 6 gets pushed onto the stack via a PUSH 6 instruction, and then the thunk is entered via a CALL pf instruction. The memory that 6 occupies on the stack is located at ESP+4 when the thunk is entered, ie 4 bytes from the current value of the stack pointer register ESP. The first instruction of the thunk is to increment the value that is pointed to by ESP+4, thus the value '6' is incremented to '7'. foo() is then entered by the thunk's JMP foo instruction. foo() then sees its a parameter as 7 instead of the original 6 because the thunk modified foo()'s call stack.

Remy Lebeau - TeamB
COMer
@COMer because that is how the C calling convention works. Parameters are pushed on to the stack and then the return address. When you first enter your code the sp is pointing at the return address. As the stack grows downwards, the parameter is immediately above the return address in memory. The return address is 4 bytes wide, hence the parameter is at `esp+4`.
JeremyP