qwb2021-pwn

Ch33_1n'
Jul 13, 2021

Baby_diary

libc2.31下的off by null

有add、show、delete函數,漏洞點在myread和addkey過程。

myread會在輸入内容結尾追加 '\x00' 字符,addkey在size+1的位置放置算得的一字節key值(content内容纍加、位移,範圍為0x01~0x0f)。

在offbynull利用的過程中,需要覆蓋size的pre_inuse位為0,以及pre_size位,同時需要僞造fakechunk的fd、bk。既然key值與輸入的内容有關,那麽可以根據所需要覆蓋的值適當調整輸入的内容。如需要覆蓋成 '\x00',則填入全零字節;需要覆蓋成 '\x08\x00'(presize時用到),則填入全零字節和一個 '\x08'。

而fakechunk的fd、bk構造則利用largebin、fastbin殘留指針,我們只需要覆蓋最低一個字節。這裏fakechunk的大小,是通過調試確定出來的。因爲第一次從largebin取出的時候能修改fakechunk的fd位置,但這裏恆在size+1的位置放key值,因此第三字節會受影響。當size剛好為0x800的時候,key剛好為6,修改完fd后,fd的地址才是我們想要覆蓋的地址。

具體構造方式:

  1. 申請0x1000的堆塊,free到unsorted bin中備用。
  2. 再申請0x2000的chunk,觸發consolidation,0x1000的chunk被放入large bin,這時chunk的next_size_fd和next_size_bk位置已經有了chunk地址(也就是fakechunk的fd和bk位置)。直接申請空間能改好fakechunk的size和fd位置。
  3. 由於fakechunk的bk指向chunk本身,繞過unlink檢查的話只需chunk的fd位置指向fakechunk。這步可以通過fastbin殘留指針改。
  4. 通過offbynull在後面的chunk中寫好pre_size和pre_inuse位,delete觸發堆塊合并。

參考:https://bbs.pediy.com/thread-257901.htm

合并堆塊、泄露成功后,再利用tcache的next指針,申請到freehook附近進行修改即可。

exp

orw

在堆上寫shellcode

add函數:只能使用兩次。雖然限制idx為0、1,但沒有對其檢查,可為負數,繼而可越界寫。

delete函數只能使用一次:

該程式got表可改寫。應該是利用add時的越界寫來改寫got表,寫入的内容是在堆中。由於程式的NX保護也沒有開啓,可在堆棧上執行,因此可以直接寫shellcode來劫持程式流。

但add時的寫入限制了長度,最多寫8字節,不足以寫orw的shellcode。因此在寫orw之前,需要寫一段控制輸入的code,也就是read(0, buf, size)。delete觸發后,可以輸入orw的shellcode了。但是這段匯編總共13字節,需要分成兩段寫入。下面這段利用是從Nu1l戰隊的wp中學來的。

先修改free的got表。因爲這裏只能寫八字節,整個chunk有0x20大,因此需要用jmp跳轉到下一個寫入的地方,也就是寫了第二段shellcode的地方。

在沒有show的情況下我們拿不到堆地址。jmp這裏的地址又是怎麽來的呢?其實是在寫入的時候,用next。這裏的next地址是0xc180結尾的地址,也是這個chunk的下一個chunk。是用nop填充中間的空間,使得next剛好為這個地址的。

padding = '''jmp next\n''' + 'nop\n' * (0x20 + (8-len(s))-0xa) +'next:'
padding = s + asm(padding)
return padding[:8]

在add之前這兩個0x20的chunk都在fastbin中,并且相鄰。因此下一次add時就是從0xc180的位置開始寫,在這裏jmp過去,兩塊内容就連在一起了:

這樣在delete的時候,會按順序執行:

劫持成功:

之後再輸入orw的shellcode即可。

exp

--

--