萌新帶你開車上p站(番外篇)

合天網安實驗室 發佈 2020-04-24T04:38:34+00:00

作者:萌新合天智匯前言:這道題目應該是pwnable.kr上Toddler's Bttle最難的題目了,涉及到相對比較難的堆利用的問題,所以拿出來分析。登錄看看源程序程序中有幾點要注意的地方:定義的OBJ結構體中一個指針4字節,buf[]數組8字節Unlink進行利用具體而言什麼


作者:萌新 合天智匯


前言:

這道題目應該是pwnable.kr上Toddler's Bttle最難的題目了,涉及到相對比較難的堆利用的問題,所以拿出來分析。

登錄

看看源程序

程序中有幾點要注意的地方:

  1. 定義的OBJ結構體中一個指針4字節,buf[]數組8字節
  2. Unlink()的過程其實就是雙向鍊表中摘下中間那一塊的過程
  3. 主函數中malloc了三個結構體,並通過指針連成了雙向鍊表A<->B<->C
  4. 列印出A的棧地址,堆地址,這兩個地址這裡記做stack,hep,待會兒在分析中會用到
  5. 漏洞在於gets函數會造成溢出,同時通過隨後的unlink()進行利用


具體而言什麼是unlink呢?

unlinked 是堆溢出中的一種常見形式,通過將雙向列表中的空閒塊拿出來與將要free的物理相鄰的塊進行合併。(將雙向鍊表上的chunk卸載下來與物理chunk合併)。Unlink漏洞的利用條件就是有3個以上的空閒chunk鍊表,其中最前面的chunk存在有堆溢出。沒錯我們這次的題目就存在這個情況

解鏈的原理相信學過數據結構的師傅們都清楚了

對照著這次的程序,BK相當於A,P相當於B,FD相當於C

這次需要用到的漏洞溢出漏洞技術稱為Dword shoot。在進行雙向鍊表的操作過程中,有溢出等的情況下,刪除的chunk的fd、bk兩個指針被惡意的改寫的話,就會在鍊表刪除的時候發生的漏洞。

對應到本題的程序,將被刪除的chunk為B,而我們可以通過溢出A來修改B的fd,bk,修改後會引發什麼漏洞呢?我們接下來詳細說明。

把二進位文件下到本地分析

要我們攻擊的最終是目的是劫持返回地址,寫入shellcode的地址,以及為了能夠溢出A,修改B的指針等操作,我們都需要看看彙編中一些關鍵量的地址


關鍵的地方:

  1. A在棧上的地址是ebp-0x14,即ebp-0x14=stack=&A
  2. 最後的ret,作用是賦值給eip寄存器,而我們要做的就是修改esp寄存器的內容為shellcode的地址
  3. 通過lea esp,[ecx-0x4]可以知道esp的值來自[ecx-4]
  4. leave指令對esp沒影響
  5. mov ecx,DWORD PTR[ebp-0x4],可知,ecx的值來自[ebp-4]
  6. 綜上,我們只需要把shellcode的地址寫到[ebp-8]地址(事實上這樣很不方便,我們下面實際上是把shellcode地址+4寫到[ebp-4]地址,這樣的話,shellcode地址+4-4,傳給esp的時候恰好就是shellcode的地址)

推論:

(1)由1得,ebp-4等於stack+0x14-0x4

(2)heap_是A在堆中的地址,加上在buf前有fd,bk鏈各個指針共8個字節,所以shellcode的地址是寫到了heap+0x8處,所以 (shellcode地址+4)=(heap+0x8)+0x4


只要實現了* (ebp-4)=&shellcode+4,則ecx就被覆蓋成了&shellcode+4,然後執行了

 0x08048603 <+212>: lea esp,[ecx-0x4]
    0x08048606 <+215>: ret

我們就拿到shell了


我們前面留下了一個問題:

被刪除的chunk為B,修改B的fd,bk,修改後會引發什麼漏洞

先舉個簡單的例子看看

設我們修改了B->fd=!!!!,B->bk=@@@@

在調用unlink(B)時,

 BK=P->bk;
 FD=P->fd;
 FD->bk=BK;
 BK->fd=FD;
對應執行的流程是這樣子的
BK=*(B+4)=@@@@ //B->bk前還有B->fd,占4字節
FD=*(B)=!!!!
*(FD+4)=*(!!!!+4)=BK=@@@@
*(BK)=*(@@@@)=FD=!!!!


通過紅色字體的關係,我們知道,修改了B的fd,bk之後,就可以在進行覆蓋操作

這裡我們設修改了B->bk=[ebp-4],B->fd=&shellcode+4

則進過unlink(B)之後會有

*(&shellcode+4+4)=[ebp-4] //這個結果無影響
* (ebp-4)=&shellcode+4 //實現了* (ebp-4)=&shellcode+4,因為*(ebp-4)覆給ecx,則ecx就被覆蓋成了&shellcode+4,然後就可以拿到shell了


接下來具體看看怎麼布局

我們知道

shellcode地址+4=heap+0x8+0x4=heap+12,來修改B->fd

ebp-4=stack+0x14-0x4=stack+16,來修改B->bk

A的buf大小是8字節,寫了shellcode地址花了4字節,因為最小單位為16字節,所以還剩16-4=12字節需要填充,我們填充12個A

綜上,得到了如下的布局

shellcode的地址是什麼呢

而heap和stack的地址每次運行時都會列印出來的


綜上,寫出exp:

上傳到伺服器

執行得到shell

值得注意的是,本題的unlink利用是比較古老的方式了,現在的glibc已經加入了很多新的保護措施

包括:

Double Free檢測

該機制不允許釋放一個已經處於free狀態的chunk。因此,當攻擊者將second chunk的size設置為-4的時候,就意味著該size的PREV_INUSE位為0,也就是說second chunk之前的first chunk(我們需要free的chunk)已經處於free狀態,那麼這時候再free(first)的話,就會報出double free錯誤。相關代碼如下:

#!c


next size非法檢測

該機制檢測next size是否在8到當前arena的整個系統內存大小之間。因此當檢測到next size為-4的時候,就會報出invalid next size錯誤。相關代碼如下:

雙鍊表衝突檢測

該機制會在執行unlink操作的時候檢測鍊表中前一個chunk的fd與後一個chunk的bk是否都指向當前需要unlink的chunk。這樣攻擊者就無法替換second chunk的fd與fd了。相關代碼如下:

也出現很多新的技巧的關於unlink的CTF題目,如:

HITCON 2014 stkof
0CTF 2016 – Zerostorage
0CTF 2015 'freenote'
HITCON CTF 2016: Secret Holder
強網杯2018 silent2

這些題目有興趣的師傅們可以自行去pwn

參考:

1.https://paper.seebug.org/papers/Archive/drops2/Linux%E5%A0%86%E6%BA%A2%E5%87%BA%E6%BC%8F%E6%B4%9E%E5%88%A9%E7%94%A8%E4%B9%8Bunlink.html

2.https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit.html

3. https://paper.seebug.org/papers/Archive/refs/2015-1029-yangkun-Gold-Mining-CTF.pdf

4. https://cysecguide.blogspot.com/2017/10/pwnablekr-unlink-solution.html

5.cft wiki

推薦實驗:

ARM漏洞利用技術五--堆溢出:

http://www.hetianlab.com/expc.do?ec=ECIDf4f4-3f86-44b4-bd4c-e1c88520adde

(通過本實驗了解堆溢出,包括intra-chunk和inter-chunk兩種類型,分別掌握其特點。)

聲明:筆者初衷用於分享與普及網絡知識,若讀者因此作出任何危害網絡安全行為後果自負,與合天智匯及原作者無關!

關鍵字: