Pwn-SROP
Author: 堇姬Naup
signal機制
- kernel向process發起signal機制,Process暫時中斷,進入kernel
- 保存環境(簡單來說就是保存了各個暫存器的值,將所有東西壓入stack,並壓入signal相關訊息),這段記憶體被稱為Signal Frame
- 到signal handler處理
- 恢復環境
- 繼續執行process
signal frame
1 | struct _fpstate |
漏洞在哪?
如果我們能控制Stack的值,因為他在恢復環境時沒有驗證,所以可以任意修改來串ROP(透過偽造sigframe來調用惡意syscall)
SROP前提
- 有BOF
- 可以去系統調用signature(或用read控rax之類的)
- /bin/sh地址可以寫入並拿到該地址或是直接有目標及有位址
- syscall地址
SROP chain
如果有ret,那可以構造像是這樣的chain來呼叫多個syscall
流程
- 控制stack
- 偽造Signal Frame
- 觸發Sigreturn
- get shell
題目
1 | ; nasm -f elf64 chal.asm -o chal.o && ld chal.o -o chal |
控rax代表可以控你要syscall甚麼,而能控rax的不只有gadget,read返回值,也就是讀取的字節數可以控rax(rax包含系統調用結果)
首先根據上方asm他調用了read,隨便輸入一個他會跳到對應位置
這邊我輸入了aaa跳到了0xa616161(0xa是換行)上,因為rsi指向rsp,ret吃到rsp所以stack底部會跳過去
這邊我先放入兩個ret回最上面
再來送一個\x03
來蓋掉stack底部ret位置最低位到xor rax, rax後面
與此同時因為寫入1 byte,rax變成1,call write,寫出stack address
原本
寫掉最低位成0x03
另外因為寫入1 byte ,讓rax=1
1 | from pwn import * |
接下來我們的目標是call execve(),所以要寫入/bin/sh
另外根據上方腳本已經跳出去了,但我們如果一開始送p64(0x401000) 3次,write完後又跳回來了
1 | read = SigreturnFrame() |
讀payload進來
1 | start |
ret跳回start,讀15個byte進來
1 | syscall |
ret到syscall,現在rax=15(call sys_rt_sigreturn)
1 | read.SigreturnFrame |
回復位置成read.SigreturnFrame的樣子
再來
1 | execve = SigreturnFrame() |
回復的read先讀
1 | start |
再來ret到start,再讀15byte
1 | syscall |
ret到syscall,現在rax=15
回復成execve.SigreturnFrame
並抓到/bin/sh
get shell!!
另外適時加一些sleep防止送太快
script
1 | from pwn import * |