return_address
是通過編寫一小段彙編代碼獲取EBP獲得,因此我們可以通過4 這裏return_address
是int
類型獲得通過增量的返回地址EBP,但我們可以把它轉換爲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;
}
我用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.
我通過返回地址爲0x08048344
的功能。偏移量爲-64
,返回值爲0x8048304
,這是bar的起始地址。
爲什麼這項工作?
這是C文件,其中bar
和foo
定位
#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;
}
我把這段代碼在traceback(FILE *fp)
。
純粹病態的好奇心,如果你打開全面優化,它仍然工作嗎? – kmort
我在Makefile中使用的標誌是'CFLAGS = -Wall -Werror -gstabs -O0 -m32 -Itraceback -mpreferred-stack-boundary = 2' –