r0pbaby
- Author: bruce30262
- Email: bruce30262@gmail.com
- Solver: bruce30262, bananaapple
Description
Category: Baby's First (pwnable)
Points: 1
Keyword: ROP, return-to-libc
r0pbaby_542ee6516410709a1421141501f03760.quals.shallweplayaga.me:10436
Problem
64 bit ELF. 沒開 stack guard, 不過有開 NX 和 PIE 保護
程式跑起來會先給你一個 menu, 要你輸入選項:
Welcome to an easy Return Oriented Programming challenge...
Menu:
1) Get libc address
2) Get address of a libc function
3) Nom nom r0p buffer to stack
4) Exit
輸入選項 1 會給你 libc.so.6
的 address,這個 address 存的會是真正的 libc base address
輸入選項 2 會先請你輸入 libc 裡面其中一個 function 的 symbol, 例如 system
, atoi
之類的,輸入完後會吐給你該 symbol 的 address
輸入選項 3 會先要你輸入長度,之後輸入相對應長度的字串
選項 4 為離開程式
Vulnerability
打開 IDA Pro 分析程式,會發現 main function 裡面有以下 pseudo code:
我們輸入選項 3 時,之後輸入的字串(不包含長度)會被先放到 nptr
裡面
之後會被 memcpy 到 savedregs
裡面
看看 saveregs
位於 stack 上的哪個地方
可以看到 saveregs
正好位在 rbp
上,也就是說, 複製到 saveregs
的內容,會從 rbp
開始寫入
Exploit
既然可以從 rbp
任意寫入內容,那麼方向就很明顯了
我們可以覆蓋 return address
讓程式跳到我們想要跳的地方
這題有開 NX 保護, 不過因為程式有給我們 system
的 address
所以就嘗試往 return-to-libc 的方向做 exploit
一開始想說先想辦法 leak 出 libc 的 base address
之後根據 symbol 的 offset 去猜 libc 的版本,進而構造 ROP 的 payload
不過實際操作後發現基本上 leak 不出來,因為沒有其他 memory leakage 的漏洞
當然也試想過先 leak 出不同 function 的 address, 藉由他們之間的 offset 去猜 libc 版本
但是這麼做實在很沒效率
此時 bananaapple 提出了一個很不錯的想法: 嘗試從 function 裡面去找有用的 gadget
因為 gadget 均是由 machine code 所組成
所以今天如果我要找一個 pop rdi, ret
這樣的 gadget
根據 assembly 與 machine code 間的轉換: pop rdi, ret
= 5f c3
因此只要想辦法從某個 function 裡頭找出 5f c3
這 2 個 byte
就可以把 rip 設過去
同理因為 /bin/sh
這個字串 libc 裡面也有
所以也可以用同樣的方式去找到一個 char* 指向 /bin/sh
首先利用 objdump -D
和 grep
得知 5f c3
位於 _IO_proc_open
這個 function 的開頭 + 0x34d 的位址
而 /bin/sh
則位於 _libc_intl_domainname
+ 0x242 的位址
有了這些資訊就可以透過選項 2 和選項 3 來構造 ROP chain 了
flag: W3lcome TO THE BIG L3agu3s kiddo, wasn't your first?