ADB全称为Android Debug Bridge(Android调试桥),是一种功能多样的命令行工具,可让使用者与目标设备进行通信。利用adb命令可进行各种设备操作(如安装和调试应用),并提供对 Unix shell(可用来在设备上运行各种命令)的访问权限。
adb 命令语法格式如下:
adb [ -d | -e | -s <deviceId>] <command>
参数具体含义如表2-2所示。
表2-2 参数含义
当仅有一个设备连接时,在命令中可以不指定[-d|-e|-s <serial-number>]参数,而直接使用adb <command>的方式进行操作。对于连接多个设备的情况,常见的方法是通过-s <deviceId>参数指定待连接的设备。
如果和目标设备在同一局域网中,则可以通过“IP地址+端口”的方式连接到目标设备。
adb connect host_ip[:port]
可以通过adb devices命令查看当前已经连接的设备:
$ adb devices
List of devices attached
rsnvs87d5dgewt device
a38b2e8 device
emulator-5554 device
这种场景下如果想指定a38b2e8设备来运行adb命令,则可以采用-s <deviceId>的方式:
adb -s a38b2e8 install demo.apk
通过adb命令查看目标设备应用列表的基本命令格式如下:
adb shell pm list packages [-f|-d|-e|-s|-3|-i|-u] [--user USER_ID] [FILTER]
参数显示列表见表2-3。
表2-3 参数显示列表
查看目标设备上安装的所有应用:
adb shell pm list packages
查看目标设备上安装的系统应用:
adb shell pm list packages -s
查看目标设备上用户自己安装的应用:
adb shell pm list packages -3
查看目标设备上包名中含有指定字符的应用:
adb shell pm list packages 'test'
adb命令配合am <command>命令可以实现与目标应用的交互,常用命令如表2-4所示。
表2-4 常用命令及作用
启动一个应用,命令格式如下:
adb shell am start -n com.test.demo/com.test.demo.activity
注意
可以用debug方式启动应用(am start -D -n),特别是在反编译调试应用的时候。
启动指定的服务,具体命令如下:
adb shell am startservice -n com.test.demo/com.test.demo.service
向系统发送一条指定的广播,具体命令如下:
adb shell am broadcast -a android.NET.conn.CONNECTIVITY_CHANGE
强制停止指定包名的应用进程,具体命令如下:
adb shell am force-stop com.test.demo
adb命令除了可以用于应用交互,还可以配合input命令来模拟更多的用户行为,如按键行为和输入行为。模拟按键行为的命令如下:
adb shell input keyevent <keycode>
其中,经常使用的keycode如表2-5所示。
表2-5 常用keycode及含义
模拟用户滑动屏幕行为的具体命令如下:
adb shell input swipe 500 300 100 300
这段代码模拟了用户向左滑动屏幕的行为。参数“500 300 100 300”分别表示起始点 x 坐标、起始点 y 坐标、结束点 x 坐标和结束点 y 坐标。
模拟用户单击屏幕行为的具体命令如下:
adb shell input tap 100 300
这段代码模拟了用户单击屏幕的行为。参数“100 300”分别表示单击位置的 x 坐标和 y 坐标。
下面解释其他常用命令。
查看当前应用的Activity组件信息:
adb shell dumpsys activity top
查看指定包名应用的详细信息:
adb shell dumpsys [packagename]
查看指定进程名或者进程ID的内存信息:
adb shell dumpsys meminfo [packagename/pid]
查看指定包名应用的数据库存储信息:
adb shell dumpsys dbinfo [packagename]
重启进入bootloader状态,即刷机模式:
adb reboot bootloader
重启进入recovery状态,即恢复模式:
adb reboot recovery
readelf是用于查看ELF格式文件信息的工具,常见的ELF文件如在Android平台上的可执行文件、动态库或者静态库等。
在Linux系统中可以直接在命令行中使用该工具,虽然在macOS系统中无法直接使用该工具,但可以安装使用greadelf,两者功能是一样的。具体安装命令如下:
brew install binutils // x86架构的安装方法
arch -arm64 brew install binutils // ARM架构的安装方法
readelf工具的功能较多,可在命令行直接输入readelf --help命令获取readelf的功能介绍和所有参数的说明及用法,本节只对其中的几个常用参数及含义进行讲解,如表2-6所示。
表2-6 常用参数及含义
查看动态库文件形式的ELF文件头信息,具体命令及结果如下:
[root@localhost]# readelf -h libc.so
ELF 头:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
类别: ELF32
数据: 2 补码,小端序 (little endian)
版本: 1 (current)
OS/ABI: UNIX - System V
ABI版本: 0
类型: DYN (共享目标文件)
系统架构: ARM
版本: 0x1
入口点地址: 0x0
程序头起点: 52 (bytes into file)
Start of section headers: 772512 (bytes into file)
标志: 0x5000200, Version5 EABI, soft-float ABI
本头的大小: 52 (字节)
程序头大小: 32 (字节)
Number of program headers:9
节头大小: 40 (字节)
节头数量: 32
字符串表索引节头: 29
查看ELF文件程序头信息,具体命令及结果如下:
[root@localhost]# readelf -l libc.so
ELF 文件类型为 DYN (共享目标文件)
入口点 0x0
共有9个程序头,开始于偏移量52
程序头:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x00000034 0x00000034 0x00120 0x00120 R 0x4
LOAD 0x000000 0x00000000 0x00000000 0x8c910 0x8c910 R E 0x1000
LOAD 0x08cd20 0x0008dd20 0x0008dd20 0x04c08 0x0c680 RW 0x1000
DYNAMIC 0x08f2ac 0x000902ac 0x000902ac 0x00108 0x00108 RW 0x4
NOTE 0x000154 0x00000154 0x00000154 0x00038 0x00038 R 0x4
GNU_EH_FRAME 0x08c1e4 0x0008c1e4 0x0008c1e4 0x0072c 0x0072c R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0
EXIDX 0x07e514 0x0007e514 0x0007e514 0x02b38 0x02b38 R 0x4
GNU_RELRO 0x08cd20 0x0008dd20 0x0008dd20 0x032e0 0x032e0 RW 0x20
Section to Segment mapping:
段节...
00
01 .note.android.ident .note.gnu.build-id .dynsym .dynstr .gnu.hash .hash
02 .fini_array .data.rel.ro .init_array .dynamic .got .data .bss
03 .dynamic
04 .note.android.ident .note.gnu.build-id
05 .eh_frame_hdr
06
07 .ARM.exidx
08 .fini_array .data.rel.ro .init_array .dynamic .got
查看ELF文件节头信息,具体命令及结果如下:
[root@localhost]# readelf -S libc.so
共有32个节头,从偏移量0xbc9a0开始:
节头:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .note.android.ide NOTE 00000154 000154 000018 00 A 0 0 4
[ 2] .note.gnu.build-i NOTE 0000016c 00016c 000020 00 A 0 0 4
[ 3] .dynsym DYNSYM 0000018c 00018c 0060e0 10 A 4 1 4
[ 4] .dynstr STRTAB 0000626c 00626c 004680 00 A 0 0 1
[ 5] .gnu.hash GNU_HASH 0000a8ec 00a8ec 00303c 04 A 3 0 4
[ 6] .hash HASH 0000d928 00d928 00285c 04 A 3 0 4
[ 7] .gnu.version VERSYM 00010184 010184 000c1c 02 A 3 0 2
[ 8] .gnu.version_d VERDEF 00010da0 010da0 0000e4 00 A 4 7 4
[ 9] .gnu.version_r VERNEED 00010e84 010e84 000030 00 A 4 1 4
[10] .rel.dyn REL 00010eb4 010eb4 002e30 08 A 3 0 4
[11] .rel.plt REL 00013ce4 013ce4 001508 08 AI 3 12 4
[12] .plt PROGBITS 000151ec 0151ec 001fa0 00 AX 0 0 4
.......
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
y (noread), p (processor specific)
Android APK文件在编译打包时除了将源码编译为DEX文件外,还会将配置文件和部分资源文件编译为二进制文件。如果直接解包APK文件是无法反编译DEX文件和二进制资源文件的。Apktool是Connor Tumbleson专门为逆向分析Android APK文件而开发的工具。该工具不仅可以将DEX文件反编译为Smali代码,还会解码配置文件和资源文件。Apktool运行需要依赖Java 1.8及以上版本的环境,在正式开始使用前请确保计算机环境是否为Java 1.8或更高版本。通过官网https://apktool.org可以下载最新版Apktool。
下载完成后可在命令行中输入java -jar apktool.jar -h命令获取Apktool的功能介绍和所有参数的说明及用法,本节只对其中几个常用功能进行讲解。
将目标应用demo.apk反编译至目标目录output,具体命令如下:
apktool d [options] demo.apk -o output
其中options表示可选参数,具体可选参数及含义如表2-7所示。
表2-7 具体可选参数及含义
将反编译后的输出结果重新打包,具体命令如下:
apktool b [options] output -o repackage.apk
具体可选参数及含义如表2-8所示。
表2-8 具体可选参数及含义
在iOS系统中正常只能通过App Store下载安装应用,要想对应用进行分析只能从目标设备上导出目标应用的IPA包。苹果为了保护开发者的权益使用了数字版权加密技术对IPA包进行保护,因此直接导出的IPA包的内容是无法直接进行分析的。要想对IPA文件进行分析就需要对其进行解密,也就是通常所说的“砸壳”。
Clutch是一款便捷的工具解密工具,支持iPhone、iPad等设备以及所有iOS系统版本、架构类型和大多数二进制文件。不管应用如何加密,运行的时候都要解密,Clutch就是在应用运行时将其内存数据按照一定格式导出的。
Clutch的源码是在GitHub开源的,我们可以自己下载编译。下载源码后既可以将工程导入Xcode中编译,也可以通过命令行的方式进行编译。下面将展示如何通过命令行的方式编译Clutch。首先,安装编译所需环境和下载工具源码,具体如下:
xcode-select --install // 安装编译所需的Command line tools工具
git clone https://github.com/KJCracks/Clutch.git // 下载工具源码
开始正式编译,具体命令如下:
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../cmake/iphoneos.toolchain.cmake ..
make
通过scp命令将编译好的Clutch安装到目标设备,具体命令如下:
scp ./build/Clutch root@<your.device.ip>:/usr/bin/Clutch
通过SSH的方式连接目标设备,在命令行中输入Clutch即可查看该工具的所有功能,如图2-21所示。
图2-21 查看Clutch的功能
查看目标设备上安装的应用清单,具体命令如下:
iPhone:~ root# Clutch -i
Installed apps:
1: TextDemo <com.test.dump>
2: TextDemo2 <com.test2.dump>
3: TextDemo3 <com.test3.dump>
对选中的目标应用进行砸壳操作,具体命令如下:
iPhone:~ root# Clutch -d 2 // 数字2即上一步操作中应用对应的序号
至此已经完成砸壳操作,砸壳后的应用通常会存在/private/var/mobile/Documents/Dumped目录下。
Class-dump可以将砸壳后的IPA文件中的头文件导出,逆向分析iOS应用时结合头文件中声明的函数名或者变量名可极大地提高分析速度。Class-dump的官方版本因长期不维护而对由Objective-C 2.0和Swift开发的应用支持得不好,一些厉害的开发者于是对官方版本进行了修改以使其更好地支持Objective-C 2.0和Swift开发的应用。虽然Class-dump出现了很多修改版,但是这些版本的使用方法和功能与官方版本依然保持一致,因此本节将使用官方版本进行讲解。
在官网http://stevenygard.com下载class-dump-3.5.dmg文件,如图2-22所示。双击打开该文件,并将其中class-dump文件复制到/usr/local/bin/目录下,这样就可以直接在终端的命令行中使用class-dump命令。
图2-22 Class-dump工具
通过Class-dump工具将应用的Header信息输出在终端,具体命令如下:
$class-dump TestDemo.app
输出结果如图2-23所示。
图2-23 通过Class-dump将Header信息输出到终端
正常情况下目标应用中会存在大量函数,因此将结果输出在终端会不方便查看。对此,Class-dump提供了将结果输出到指定目录的功能,具体命令如下:
class-dump -H TestDemo.app -o Headers
输出结果如图2-24所示。
图2-24 通过Class-dump将Header信息输出到指定目录
下面就可以对目标应用中头文件的函数信息进行分析了。