dajiang_Android固件分析&漏洞审计

背景

在开发复杂的Android 应用程序时,service 工具可以用于ADB shell 中通过命令行与Binder 进行交互。使用service list 可以看到设备内所有使用Binder 的服务。

1
2
3
4
5
6
rm500:/ $ service list | grep -i dji
0 DJIBaseService: []
1 DJIService: []
83 protocol: [com.dji.protocol.IProtocolManager]
84 report: [com.dji.report.IReportManager]
108 djilink: [djilink]

升级包分析与提取

查看固件的格式,可以看到是POSIX tar 的格式。

这种格式的文件可以使用tar进行解压和提取

所以需要更改bin包的拓展名为 .tar 。

使用 “tar -xvf” 进行解压之后,可以看到 “ rm500_0205_v00.00.11.98_20221031.pro.fw.sig “ 这个文件特别大,那么文件系统就在这里面了,因为下载下来的固件的大小大约也是1.7G。

使用binwalk 查看文件的格式,由于固件太大, 所以binwalk 输出了很多信息,这里摘出部分固件描述的信息,可以看到大部分的内容是zip格式的压缩格式,并且从输出的信息来看,这就可能是android 固件中的内容,并且由于下载的这个固件是更新包,所以里面有很多app 的res 资源还有assets资源,也有boot.img 以及 recovery.img 等镜像文件。

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
tigerortiger@ubuntu ~/i/g/daji> binwalk rm500_0205_v00.00.11.98_20221031.pro.fw.sig 

DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
480 0x1E0 Zip archive data, at least v1.0 to extract, name: system.patch.dat
530 0x212 Zip archive data, at least v2.0 to extract, name: META-INF/com/android/metadata
732 0x2DC Zip archive data, at least v2.0 to extract, name: META-INF/com/google/android/update-binary
649999 0x9EB0F Zip archive data, at least v2.0 to extract, name: META-INF/com/google/android/updater-script
650625 0x9ED81 Zip archive data, at least v2.0 to extract, name: boot.img
9498728 0x90F068 Uncompressed Adobe Flash SWF file, Version 114, File size (header included) 692802466
10233785 0x9C27B9 Zip archive data, at least v2.0 to extract, name: file_contexts.bin
10247149 0x9C5BED Zip archive data, at least v2.0 to extract, name: recovery-two-step.img
31555539 0x1E17FD3 Zip archive data, at least v2.0 to extract, name: recovery.img
52863920 0x326A3B0 Zip archive data, at least v2.0 to extract, name: system.new.dat
56087091 0x357D233 Zip archive data, at least v2.0 to extract, name: META-INF/MANIFEST.MF
56113592 0x35839B8 Zip archive data, at least v2.0 to extract, name: META-INF/CERT.SF
56708341 0x3614CF5 EBML file
98144163 0x5D98FA3 gzip compressed data, ASCII, has header CRC, has 31868 bytes of extra data, has comment, last modified: 2064-08-07 20:10:06 (bogus date)
145862879 0x8B1B0DF Uncompressed Adobe Flash SWF file, Version 107, File size (header included) 284564009
161917216 0x9A6A920 Zip archive data, at least v2.0 to extract, name: META-INF/CERT.SF
179573643 0xAB4138B Uncompressed Adobe Flash SWF file, Version 110, File size (header included) 1268045105
201947399 0xC097907 MySQL MISAM index file Version 10
246485837 0xEB1134D Zip archive data, at least v2.0 to extract, name: META-INF/CERT.SF
255492818 0xF3A82D2 Zip archive data, at least v2.0 to extract, name: META-INF/CERT.SF
262679943 0xFA82D87 Cisco IOS microcode, for "p"
267586642 0xFF30C52 Zip archive data, at least v2.0 to extract, name: META-INF/CERT.SF
273966908 0x1054673C Zip archive data, at least v2.0 to extract, compressed size: 27758, uncompressed size: 78957, name: META-INF/CERT.SF
273994717 0x1054D3DD Zip archive data, at least v2.0 to extract, compressed size: 27612, uncompressed size: 78920, name: META-INF/MANIFEST.MF
280188038 0x10B35486 Zip archive data, at least v2.0 to extract, compressed size: 3298856, uncompressed size: 7852016, name: classes13.dex
283507087 0x10E5F98F Zip archive data, at least v2.0 to extract, compressed size: 16099, uncompressed size: 33924, name: classes4.dex
286805548 0x11184E2C Zip archive data, v0.0 compressed size: 422712, uncompressed size: 422712, name: res/drawable-xxhdpi-v4/launcher_main_page_background_2.webp
...
1644421087 0x6203DFDF MySQL ISAM compressed data file Version 11
1651965902 0x6276FFCE EBML file
1677644302 0x63FED20E Zip archive data, at least v2.0 to extract, name: META-INF/MANIFEST.MF
1677703331 0x63FFB8A3 Zip archive data, at least v2.0 to extract, name: META-INF/CERT.SF
1725958571 0x66E009AB Zip archive data, at least v2.0 to extract, name: system.transfer.list
1725993955 0x66E093E3 Zip archive data, at least v2.0 to extract, name: trust.img
1726425542 0x66E729C6 Zip archive data, at least v2.0 to extract, name: uboot.img
1727213555 0x66F32FF3 Zip archive data, at least v2.0 to extract, name: META-INF/com/android/otacert
1727214531 0x66F333C3 Zip archive data, at least v2.0 to extract, name: META-INF/MANIFEST.MF
1727215273 0x66F336A9 Zip archive data, at least v2.0 to extract, name: META-INF/CERT.SF
1727216088 0x66F339D8 Zip archive data, at least v2.0 to extract, name: META-INF/CERT.RSA

所以可以直接使用unzip 进行解压,解压的前提是重命名为zip 拓展名便于unzip识别。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
tigerortiger@ubuntu ~/i/g/daji> unzip rm500_0205_v00.00.11.98_20221031.pro.fw.sig.zip 
Archive: rm500_0205_v00.00.11.98_20221031.pro.fw.sig.zip
signed by SignApk
warning [rm500_0205_v00.00.11.98_20221031.pro.fw.sig.zip]: 480 extra bytes at beginning or within zipfile
(attempting to process anyway)
extracting: system.patch.dat
inflating: META-INF/com/android/metadata
inflating: META-INF/com/google/android/update-binary
inflating: META-INF/com/google/android/updater-script
inflating: boot.img
inflating: file_contexts.bin
inflating: recovery-two-step.img
inflating: recovery.img
inflating: system.new.dat
inflating: system.transfer.list
inflating: trust.img
inflating: uboot.img
inflating: META-INF/com/android/otacert
inflating: META-INF/MANIFEST.MF
inflating: META-INF/CERT.SF
inflating: META-INF/CERT.RSA

根据解压出来的信息,并且固件是升级包,因此大量的文件系统应该在system.new.dat 内,这个文件在Android 升级包中,用于描述系统分区更新的内容,通常和 system.transfer.list 和 system.patch.dat 一起使用,共同描述系统分区的更新内容和差异,从Android 5.0 开始,Google 采用了新的打包方式,不再提供system.img文件,而是通过system.new.dat 等文件实现更新。

system.new.dat 实际上是由system.transfer.list 描述的稀疏数组,需要使用特定的工具 sdat2img 转换成可挂载的 ext4 image 文件。对于想要自定义或修改ROM的用户来说,理解这些文件的作用和使用相应的工具进行操作是非常重要的。例如,使用sdat2img工具可以将system.new.dat文件转换为system.img,这样就可以对其进行修改或定制。

有关sdat2img 的信息: https://github.com/xpirt/sdat2img (将稀疏 Android 数据映像 (.dat) 转换为文件系统 ext4 映像 (.img))

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
tigerortiger@ubuntu ~/i/g/daji> python sdat2img.py system.transfer.list system.new.dat system.img
sdat2img binary - version: 1.2

Android Nougat 7.x / Oreo 8.x detected!

Skipping command erase...
Copying 1024 blocks into position 0...
Copying 683 blocks into position 1024...
Copying 143 blocks into position 1708...
Copying 198 blocks into position 1852...
Copying 639 blocks into position 2050...
Copying 163 blocks into position 2690...
Copying 185 blocks into position 2854...
Copying 37 blocks into position 3040...
Copying 295 blocks into position 3077...
Copying 208 blocks into position 3373...
Copying 9 blocks into position 3582...
Copying 111 blocks into position 3592...
Copying 70 blocks into position 3704...
Copying 4 blocks into position 3775...
Copying 1 blocks into position 3780...
Copying 1 blocks into position 3782...
Copying 1 blocks into position 3784...
...<snip>
Skipping command zero...
Done! Output image: /home/tigerortiger/iot/gujian/daji/system.img

然后就可以直接挂载到对应的目录下了

在 bin 目录下看到这个文件。

1
2
tigerortiger@ubuntu ~/i/g/d/m/bin> file djilink 
djilink: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /system/bin/linker64, BuildID[md5/uuid]=0c5df7117f458b98492c5445bb629362, stripped

漏洞审计

tinycap & setMicStatus

sub_1B3D4() 函数中可以看到格式化字符串然后调用 system函数来执行,其中的 tinycap 可执行文件在 /bin/tinycap ,而这个可执行文件主要用于调试录音功能,比如使用命令 “tinycap /sdcard/test.pcm -D 0 -d 0 -c 4 -r 48000 -b 32 -p 768 -n 10” 是用于指定各种参数然后保存到/sdcard/test.pcm 中。但看从下面的代码中可以判断其中存在命令拼接执行的问题。


sub_1B3D4() 这个函数在 sub_4A9E4() 进行调用,根据log_print 大概知道这是一个 测试的功能。

函数表


so 文件都是32位了,之前用IDA64打开,可以识别出函数符号,但是没有办法生成伪代码。

可以看到这里会调用parcel 构造binder 的数据包,根据write函数的调用,可以知道会写入四个int32 类型的数值,然偶再写入一个string16 的值,调用的 service 服务是1030 。

为了方便触发 djilink 提供的service ,可以使用 “service call djilink 1030 i32 1 i32 1 i32 1 i32 1 s16 “;echo hhhh > /sdcard/hack ;” “ 来触发。

ti_audio & setTiAudioStatus

在进行审计的过程中,还发现了其中的ti_audio 也存在同样的问题,在如下的sub_1B52C() 函数中,有关ti_audio 的作用猜测是TI 音频操作命令。

同样的,在sub_4AA6C() 可以看到 setTiAudioStatus的方法

这个setTiAudioStatus方法会在 libdijilink.so 中定义传参的方法,可以看到传入了一个int32 的值,和两个string16 的值。而这两个string16 对应的是 ti_audio 需要的两个字符串。

可以使用 “ service call djilink 1031 i32 1 s16 “; reboot ;” s16 “; reboot ;” “ 来触发root命令。

start_active_request_auth

在 sub_1B90C()函数中 存在堆栈溢出的漏洞,其中可以看到v5的值是可以是由外来输入字符决定的,另一方面 v22 局部变量会被分配到 48字节的内存。

在这里虽然使用了 strlen_chk 函数来对溢出的问题来处理,但是 -1LL 表示的是对 a1 字符串的长度检查被禁用了,这是显式地告诉编译器不要对 a1 的长度进行限制检查。

DM368Cmd

再这个功能中,可以注意到这是一个工厂测试,同样也存在执行命令问题。

在sub_34A88()函数中,会创建一个线程调用sub_34A44 函数

参考: https://icanhack.nl/blog/dji-rm500-privilege-escalation/


dajiang_Android固件分析&漏洞审计
https://tig3rhu.github.io/2024/04/06/73__dajiang__Android固件分析/
Author
Tig3rHu
Posted on
April 6, 2024
Licensed under