unexploitable Writeup[pwnable.tw]

0x00 unexploitable

最近在刷pwnable.tw(類似pwnable.kr,不過是臺灣的)的題,看到了一個unexploitable的題目。根據題目描述:

The original challenge is on pwnable.kr and it is solvable. This time we fix the vulnerability and now we promise that the service is unexploitable.

下載下來後丟到ida看到確實沒什麼變化,除了pwnable.kr那個題中最重要的一點syscall沒有給。

.text:0000000000400544 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:0000000000400544                 public main
.text:0000000000400544 main            proc near               ; DATA XREF: _start+1Do
.text:0000000000400544
.text:0000000000400544 buf             = byte ptr -10h
.text:0000000000400544
.text:0000000000400544                 push    rbp
.text:0000000000400545                 mov     rbp, rsp
.text:0000000000400548                 sub     rsp, 10h
.text:000000000040054C                 mov     edi, 3          ; seconds
.text:0000000000400551                 mov     eax, 0
.text:0000000000400556                 call    _sleep
.text:000000000040055B                 lea     rax, [rbp+buf]
.text:000000000040055F                 mov     edx, 100h       ; nbytes
.text:0000000000400564                 mov     rsi, rax        ; buf
.text:0000000000400567                 mov     edi, 0          ; fd
.text:000000000040056C                 mov     eax, 0
.text:0000000000400571                 call    _read
.text:0000000000400576                 leave
.text:0000000000400577                 retn
.text:0000000000400577 main            endp

0x01 思路

在pwnable.kr上這個題目用ROP和SROP均可以完成,不過有個重要個前提有syscall。這個題目刪除了這個gadget,導致題目的難度上升了一個檔次。pwnable.kr的writeup在http://weaponx.site/2017/02/28/unexploitable-Writeup-pwnable-kr/

題目給出了libc,看來是讓我們用內存泄漏來計算出system/execve等地址來執行system("/bin/sh")。通常內存泄漏最終需要調用類似puts\write等打印函數,然而程序中並沒有這些函數。只能通過syscallsyscall_id來調用需要的函數,但是又回到的最初沒有syscall的情況。

所以只能尋求一個更有創造性的方法。

0x02 尋找syscall

在libc中搜索\x0f\x0fsyscall的機器碼。可以看到在read函數中就有兩個gadget。

gdb-peda$ find "\x0f\x05"
...
libc.so.6 : 0x7ffff7b0467e (<read+14>:  syscall)
libc.so.6 : 0x7ffff7b0469b (<read+43>:  syscall)
...
gdb-peda$ print read
$1 = {<text variable, no debug info>} 0x7ffff7b04670 <read>

可以發現read函數中的syscall的距離函數入口的偏移量只有14和43,根據ASLR的原理。可以通過修改GOT表中read函數的LSB(last significant bit,最低有效位)爲0x7e或者0x9b就得到了syscall

0x03 how to exploit

第一段payload完成溢出,並調用read將第二段payload寫入bss段中,然後利用pop rbp;retleave;ret將棧遷移到bss段上。

第二段payload完成修改GOT表中read的LSB,變爲syscall。利用syscall調用write泄漏sleep的地址,計算出/bin/sh\x00的地址pop rdi;ret的地址和system的地址。最後將棧遷移到第三段payload上。

第三段payload,將/bin/sh\x00放入rdi寄存器中,完成system("/bin/sh\x00")

0x04 syscall to system

通過syscall來調用函數必須要將syscall_id放入rax寄存器中,但是經過搜索並沒有設置rax相關的gadgets。必須利用函數的返回值來設置raxread函數的返回值是讀入字符的個數,所以可以通過調用read函數來設置rax的值。

通過寫LSB得到syscallrax的值爲1,即可通過syscall調用write來泄漏內存,此時可以通過泄漏內存的字節數來控制raxsleep的返回值是0,所以可以通過調用sleep來將rax置0調用read

所以既可以通過偏移計算system的地址,也可以通過syscallsyscall_id = 59來調用execve

寫出exploit後Boom shakalaka!

[+] [sleep base] => [0x7fb74adbe680]
[+] [system] => [0x7fb74ad14102]
[+] [pop rdi ret] => [0x7fb74ad38390]
FINAL!!!
[*] Switching to interactive mode
$ cat /home/unexploitable/flag
FLAG{********************************}
$
[*] Interrupted
[*] Closed connection to chall.pwnable.tw port 10403

0x05 exploit

因爲主辦方不讓公開高分的題目,所以exploit提交到主辦方的writeup系統中了,https://pwnable.tw/writeup/20/927

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章