前言
buffer overflow 以下簡稱為 BOF。
BOF 是一個常見的攻擊手法,透過 BOF 可以達成各種不同的目的,像是:
- ret2text
- ret2shellcode
- ret2syscall
- ret2libc
本文將透過 2018-EOF 的 pwn3 來說明 ret2libc 的攻擊手法
分析題目
(題目給了一個 ELF 檔案 以及 libc.so.6)
拿到題目第一步,先丟到 IDA 中逆向
同時查看 ELF 檔案的保護狀態
這兩個線索加起來(沒有 canary, 使用 read 函數),第一個想到的就是 BOF
但是程式中並沒有現成的 function 可以用,我們的目的是 get shell
然而在題目給的 libc.so.6 中,發現了 execve
困難點
我們並不知道 libc.so.6 load 進 memory 之後的記憶體位置是多少,只知道 execve 相對於 libc.so.6 的 offset 是多少 (0xf1147)
但是程式中有一個 puts 函數,如果我們能利用他來印出 GOT 的 main 位置並且與 binary 裡面的 main 位置相減,就知道整個函式庫載入到 memory 的哪個位置了
payload
先備知識:
Linux x86-64 下的 calling convention
參數少於 7,參數從左到右放入暫存器順序為: rdi, rsi, rdx, rcx, r8, r9
1 | payload = flat([ |
如此一來程式的流程就會變成,印出 elf.got['__libc_start_main']
並且重新執行 main
接著只需要把印出的記憶體位置用 u64 打包並且減去 main 在程式中未載入時的位置就可以得知 load 到 memory 中的位移
把位移再加上用 one_gadget 找到的 execve 就大工告成了!
1 | payload2 = flat([ |
以下是完整 payload
1 | from pwn import * |