[英]why this piece of code can get the function address from return address?
return_address
is obtain by writing a small piece of assembly code getting the ebp and hence we can get the return address by increment the ebp by 4. Here return_address
is of type int
but we can cast it to int*
return_address
是通过编写一小段获得ebp的汇编代码而获得的,因此我们可以通过将ebp加4来获得返回地址。这里return_address
是int
类型的,但可以将其return_address
为int*
int extract_function_address(int return_address) {
int *offset_address_ptr = (int*)(return_address - 5 + 1);
int offset = *offset_address_ptr;
int func_address = return_address + offset;
return func_address;
}
I use gdb
to step through it 我使用
gdb
逐步解决
(gdb) disas bar
Dump of assembler code for function bar:
0x08048304 <+0>: push %ebp
0x08048305 <+1>: mov %esp,%ebp
0x08048307 <+3>: sub $0x8,%esp
0x0804830a <+6>: mov 0xc(%ebp),%eax
0x0804830d <+9>: mov 0x8(%ebp),%edx
0x08048310 <+12>: add %edx,%eax
0x08048312 <+14>: mov %eax,-0x4(%ebp)
0x08048315 <+17>: mov -0x4(%ebp),%eax
0x08048318 <+20>: mov %eax,0x8(%ebp)
0x0804831b <+23>: mov 0x81e2460,%eax
0x08048320 <+28>: mov %eax,(%esp)
0x08048323 <+31>: call 0x8048358 <traceback>
0x08048328 <+36>: leave
0x08048329 <+37>: ret
End of assembler dump.
(gdb) disas foo
Dump of assembler code for function foo:
0x0804832a <+0>: push %ebp
0x0804832b <+1>: mov %esp,%ebp
0x0804832d <+3>: sub $0x8,%esp
0x08048330 <+6>: movl $0x11,0x4(%esp)
0x08048338 <+14>: movl $0x5,(%esp)
0x0804833f <+21>: call 0x8048304 <bar>
0x08048344 <+26>: leave
0x08048345 <+27>: ret
End of assembler dump.
I passed return address as 0x08048344
to the function. 我将返回地址作为
0x08048344
传递给了该函数。 The offset will be -64
and the return value will be 0x8048304
which is the starting address of bar. 偏移量为
-64
,返回值为0x8048304
,它是bar的起始地址。
Why is this work? 为什么要这样做?
This is the C file where bar
and foo
locate 这是
bar
和foo
所在的C文件
#include "traceback.h"
#include <stdio.h>
void bar(int x, int y)
{
int z;
z = x + y;
traceback(stdout);
}
void foo() {
bar (5,17);
}
int main (int argc, char **argv)
{
foo();
return 0;
}
I put that piece of code in traceback(FILE *fp)
. 我把这段代码放在
traceback(FILE *fp)
。
A call instruction assembles to E8 AA BB CC DD
where AA BB CC DD
is the offset of the target function from the instruction following the call, ie from the return address. 调用指令汇编到
E8 AA BB CC DD
,其中AA BB CC DD
是目标函数相对于调用后指令(即返回地址)的偏移量。 Try x/5bx 0x0804833f
in gdb to see the encoded instruction. 尝试在gdb中使用
x/5bx 0x0804833f
查看编码指令。 Note that the offset would be in little endian byte order. 请注意,偏移量将以小尾数字节顺序。
Therefore, (return_address - 5 + 1)
points to the offset of the call instruction. 因此,
(return_address - 5 + 1)
指向调用指令的偏移量。 offset = *offset_address_ptr
reads this offset from the call instruction and return_address + offset
points to the target function. offset = *offset_address_ptr
return_address + offset
从调用指令中读取此偏移量,而return_address + offset
指向目标函数。
我不确定,但是它看起来像代码在返回位置之前的指令中调用了地址。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.