The following code snippet implements calling the function via jmp.
This is here to verify that the difference between 'call' and 'jmp' instructions is that the former one pushes the return address to the stack before jump to the new label to execute while the later one won't. As a result we can emulate 'call' by pushing the address of the function we want to exec to the stack before 'jmp'.
If we can extract the content of eip before jmping we can push it into the stack before jmp. This would behave exactly as we use 'call' instruction I think.
// BEGIN OF THE CODE
#include
void a();
void b(int first, int last);
void c();
int
main()
{
a();
printf("In main().\n");
return 0;
}
/* stack
* |--------------|
* | Param 2 (5) |
* |--------------|
* | Param 1 (10)|
* |--------------|
* |Ret addr(stop)|
* |--------------|
*/
void a()
{
printf("In a().\n");
// The address of function b is the return address of function
// c. In turn, the address labeled by stop is the return address
// of function b.
__asm__("pushl $5; pushl $10; pushl $stop; pushl $b; jmp c");
// This line should be skipped
printf("This should not be printed.\n");
// Set a label here so we have somewhere to return after finishing
// function b()
__asm__("stop:");
printf("Ending a().\n");
}
void b(int first, int last)
{
printf("In b().\n");
printf("param: %d and %d\n", first, last);
}
// We jump here. Because c is a function, it will invoke ret after the
// execution. ret pops the return address from stack which is the
// address of function b we pushed to stack manually in advance. Thus
// function b will be executed in turn without being called explicitly.
void c()
{
printf("In c().\n");
}
// END OF THE CODE
Compile and execute, the output will be:
In a().
In c().
In b().
param: 10 and 5
Ending a().
In main().
阅读(1624) | 评论(0) | 转发(0) |