为什么这段代码可以从返回地址获取函数地址?

时间:2014-01-05 03:50:43

标签: c assembly operating-system stack reverse-engineering

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,即条形码的起始地址。

为什么这样做?

这是barfoo找到

的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)

2 个答案:

答案 0 :(得分:2)

调用指令汇编到E8 AA BB CC DD,其中AA BB CC DD是目标函数与调用后的指令(即返回地址)的偏移量。在gdb中尝试x/5bx 0x0804833f以查看编码指令。请注意,偏移量将以小端字节顺序排列。

因此,(return_address - 5 + 1)指向调用指令的偏移量。 offset = *offset_address_ptr从调用指令读取此偏移量,return_address + offset指向目标函数。

答案 1 :(得分:0)

我不确定,但看起来代码从返回位置之前的指令中获取了call-address。