2014-01-05 40 views
1

return_address是通過編寫一小段彙編代碼獲取EBP獲得,因此我們可以通過4 這裏return_addressint類型獲得通過增量的返回地址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文件,其中barfoo定位

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

+0

純粹病態的好奇心,如果你打開全面優化,它仍然工作嗎? – kmort

+0

我在Makefile中使用的標誌是'CFLAGS = -Wall -Werror -gstabs -O0 -m32 -Itraceback -mpreferred-stack-boundary = 2' –

回答

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指向目標函數。

+0

哇..謝謝。對此我完全沒有想法。你知道有沒有任何參考,以便我可以閱讀更多關於它? –

+1

您可以閱讀緩衝區溢出文章中的一些相關內容,包括Aleph One的傳奇文章:[粉碎樂趣和利潤的堆棧](http://www.phrack.org/issues.html?issue=49&id=14&mode= txt) – pank4j

+0

是的。你是對的。我查看了第3-53頁的intel架構手冊http://www.cs.cmu.edu/~410/doc/intel-isr.pdf。但它總是使用相對位移?如果它使用直接地址,上面的代碼會中斷嗎? –

0

我不確定,但它看起來像代碼從返回位置之前的指令fetle呼叫地址。