【发布时间】:2014-01-22 16:02:41
【问题描述】:
return_address 是通过编写一小段获取 ebp 的汇编代码获得的,因此我们可以通过将 ebp 增加 4 来获得返回地址。
这里return_address 是int 类型,但我们可以将其转换为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的起始地址。
为什么会这样?
这是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;
}
我把那段代码放在traceback(FILE *fp)。
【问题讨论】:
-
纯粹病态的好奇心,如果你开启全面优化,它仍然有效吗?
-
我在Makefile中使用的标志是
CFLAGS= -Wall -Werror -gstabs -O0 -m32 -Itraceback -mpreferred-stack-boundary=2
标签: c assembly operating-system stack reverse-engineering