如果想看下安卓 APP 发出的请求内容,有什么办法吗?这个看似简单的问题却并不好实现,只是因为一个叫 https 的家伙从中捣鬼。如果说应用使用的是 http 协议,那非常简单,在电脑上开个代理软件,然后手机网络设置下代理即可。但是至今还在使用 http 协议的 APP 不能说已经完全灭绝,但肯定是凤毛麟角,大概率不在你想研究的范围之内。
如果尝试 Google 下如何解决这个问题,这些文章中大多会给一些差不多的解决方案。比如使用 Charles 的话,可以通过下载 Charles 的证书,导入到手机的安全证书中让手机信任 Charles 证书。但是这个仅限于 Android 7.0 以下的版本,因为 Android 7.0 之后升级了安全策略,默认不信任用户添加到系统的 CA 证书。那么你可以尝试找个 Android 7.0 的设备,来使用这种办法(我是没有去尝试),但是在 2024 年的今天,很多应用已经不再支持如此老版本的系统。
所以这里我们讨论一种使用 Android 高版本(Android 13)来抓取 APP 请求的方法。由于这种方法需要将手机 root,而我又不忍爱机受此酷刑,所以使用 AVD 来代替真机。后来发现 AVD 在测试方面其实比真机要好用不少,比如文件传输、输入等。整体使用软件版本如下。
- System: MacOS Sonoma 14.6.1
- Charles: v4.6.7
- Android Studio: 2024.1.1 Patch 2
- Android: Tiramisu,Api 33,arm64-v8a,Android 13.0(Google APIs)
- Magisk: V27.0
Android 系统 root
使用这种方法的基础是需要手机已经 root 过,因为后面的一些操作需要 root 权限才行。在 root 的时候就卡了我挺久,最核心的原因就是使用的 Android API 版本不对。这里一定要使用 Google APIs 的版本,其他的版本据说编译时候没有 adb root 功能。
那么我们来实际 root 一个 AVD 试试。首先我们需要创建一个 AVD。
这里我们选择了 Pixel 8 Pro,然后选择 image 的时候注意一定选择这个,在初次选择的时候应该是灰色的,需要先下载。然后一路 Next,一个崭新的 AVD 就创建完成。接着我们启动一下。
完美!
完美个毛线,万里长征的第一步而已。想要 root 需要一定的软件支持。这个在互联网上,或者 github 上随便搜索下一大把教程。
这里我们找到了 rootAVD,然后照着 Use Case 操作就行。这里需要注意的两点是:
- 如果使用的 Magisk Versions >= 26.x 只能使用 FAKEBOOTIMG 参数的方式来安装
- Android 14 需要使用 Magisk Version >= 26.x 才能 root
- API 28 (Pie) is not supported at all -> because
- Magisk Versions >= 26.x can only be proper installed with the FAKEBOOTIMG argument. due to the New sepolicy.rule Implementation
- Android 14 needs Magisk Version >= 26.x to be rooted
我们这里需要 root 的 Android 版本是 13 其实可以不用 care,但是为了后面玩下更高版本的,所以我决定还是使用高版本的 Magisk,Magisk 可以从这里进行下载。
rootAVD 的代码我已经拉到本地了,rootAVD 里面的 Magisk 版本好像是 25.0 的,我们需要把上一步中下载的 Magisk-v27.0.apk 重命名为 Magisk.zip 并替换 rootAVD 目录下的同名文件。
然后我们按照 rootAVD 中的指引操作。
yuman@U-N9CQ49WD-2247: ~/workspace/android/rootAVD-master
$ ./rootAVD.sh [17:46:18]
rootAVD A Script to root AVD by NewBit XDA
Usage: rootAVD [DIR/ramdisk.img] [OPTIONS] | [EXTRA ARGUMENTS]
or: rootAVD [ARGUMENTS]
Arguments:
ListAllAVDs Lists Command Examples for ALL installed AVDs
InstallApps Just install all APKs placed in the Apps folder
Main operation mode:
DIR a path to an AVD system-image
- must always be the 1st Argument after rootAVD
ADB Path | Ramdisk DIR | ANDROID_HOME:
[M]ac/Darwin: export PATH=~/Library/Android/sdk/platform-tools:$PATH
export PATH=$ANDROID_HOME/platform-tools:$PATH
system-images/android-$API/google_apis_playstore/x86_64/
[L]inux: export PATH=~/Android/Sdk/platform-tools:$PATH
export PATH=$ANDROID_HOME/platform-tools:$PATH
system-images/android-$API/google_apis_playstore/x86_64/
[W]indows: set PATH=%LOCALAPPDATA%\Android\Sdk\platform-tools;%PATH%
set PATH=%ANDROID_HOME%\platform-tools;%PATH%
system-images\android-$API\google_apis_playstore\x86_64\
ANDROID_HOME: By default, the script uses ~/Library/Android/sdk, to set its Android Home
directory, search for AVD system-images and ADB binarys. This behaviour
can be overwritten by setting the ANDROID_HOME variable.
e.g. export ANDROID_HOME=~/Downloads/sdk
$API: 25,29,30,31,32,33,34,UpsideDownCake,etc.
Options:
restore restore all existing .backup files, but doesn't delete them
- the AVD doesn't need to be running
- no other Argument after will be processed
InstallKernelModules install custom build kernel and its modules into ramdisk.img
- kernel (bzImage) and its modules (initramfs.img) are inside rootAVD
- both files will be deleted after installation
InstallPrebuiltKernelModules download and install an AOSP prebuilt kernel and its modules into ramdisk.img
- similar to InstallKernelModules, but the AVD needs to be online
AddRCscripts install all custom *.rc scripts, placed in the rootAVD folder, into ramdisk.img/overlay.d/sbin
Options are exclusive, only one at the time will be processed.
Extra Arguments:
DEBUG Debugging Mode, prevents rootAVD to pull back any patched file
PATCHFSTAB fstab.ranchu will get patched to automount Block Devices like /dev/block/sda1
- other entries can be added in the script as well
- a custom build Kernel might be necessary
GetUSBHPmodZ The USB HOST Permissions Module Zip will be downloaded into /sdcard/Download
FAKEBOOTIMG Creates a fake Boot.img file that can directly be patched from the Magisk APP
- Magisk will be launched to patch the fake Boot.img within 60s
- the fake Boot.img will be placed under /sdcard/Download/fakeboot.img
Extra Commands can be combined, there is no particular order.
Notes: rootAVD will
- always create .backup files of ramdisk.img and kernel-ranchu
- replace both when done patching
- show a Menu, to choose the Magisk Version (Stable || Canary || Alpha), if the AVD is online
- make the choosen Magisk Version to its local
- install all APKs placed in the Apps folder
- use ~/Library/Android/sdk to search for AVD system images
Command Examples:
./rootAVD.sh
./rootAVD.sh ListAllAVDs
./rootAVD.sh InstallApps
./rootAVD.sh system-images/android-34/google_apis/arm64-v8a/ramdisk.img
./rootAVD.sh system-images/android-34/google_apis/arm64-v8a/ramdisk.img FAKEBOOTIMG
./rootAVD.sh system-images/android-34/google_apis/arm64-v8a/ramdisk.img DEBUG PATCHFSTAB GetUSBHPmodZ
./rootAVD.sh system-images/android-34/google_apis/arm64-v8a/ramdisk.img restore
./rootAVD.sh system-images/android-34/google_apis/arm64-v8a/ramdisk.img InstallKernelModules
./rootAVD.sh system-images/android-34/google_apis/arm64-v8a/ramdisk.img InstallPrebuiltKernelModules
./rootAVD.sh system-images/android-34/google_apis/arm64-v8a/ramdisk.img InstallPrebuiltKernelModules GetUSBHPmodZ PATCHFSTAB DEBUG
./rootAVD.sh system-images/android-34/google_apis/arm64-v8a/ramdisk.img AddRCscripts
可以看到 Command Examples 中已经给出了一些示例,并且列出了一个 android-34 image 的操作示例,由于 android-34 不是我们的目标 API,所以我们需要找下我们的目标 API
yuman@U-N9CQ49WD-2247: ~/workspace/android/rootAVD-master
$ ./rootAVD.sh ListAllAVDs [17:51:48]
rootAVD A Script to root AVD by NewBit XDA
... ...
Command Examples:
./rootAVD.sh
./rootAVD.sh ListAllAVDs
./rootAVD.sh InstallApps
./rootAVD.sh system-images/android-35/google_apis_playstore/arm64-v8a/ramdisk.img
./rootAVD.sh system-images/android-35/google_apis_playstore/arm64-v8a/ramdisk.img FAKEBOOTIMG
./rootAVD.sh system-images/android-35/google_apis_playstore/arm64-v8a/ramdisk.img DEBUG PATCHFSTAB GetUSBHPmodZ
./rootAVD.sh system-images/android-35/google_apis_playstore/arm64-v8a/ramdisk.img restore
./rootAVD.sh system-images/android-35/google_apis_playstore/arm64-v8a/ramdisk.img InstallKernelModules
./rootAVD.sh system-images/android-35/google_apis_playstore/arm64-v8a/ramdisk.img InstallPrebuiltKernelModules
./rootAVD.sh system-images/android-35/google_apis_playstore/arm64-v8a/ramdisk.img InstallPrebuiltKernelModules GetUSBHPmodZ PATCHFSTAB DEBUG
./rootAVD.sh system-images/android-35/google_apis_playstore/arm64-v8a/ramdisk.img AddRCscripts
./rootAVD.sh system-images/android-33/google_apis/arm64-v8a/ramdisk.img
./rootAVD.sh system-images/android-33/google_apis/arm64-v8a/ramdisk.img FAKEBOOTIMG
./rootAVD.sh system-images/android-33/google_apis/arm64-v8a/ramdisk.img DEBUG PATCHFSTAB GetUSBHPmodZ
./rootAVD.sh system-images/android-33/google_apis/arm64-v8a/ramdisk.img restore
./rootAVD.sh system-images/android-33/google_apis/arm64-v8a/ramdisk.img InstallKernelModules
./rootAVD.sh system-images/android-33/google_apis/arm64-v8a/ramdisk.img InstallPrebuiltKernelModules
./rootAVD.sh system-images/android-33/google_apis/arm64-v8a/ramdisk.img InstallPrebuiltKernelModules GetUSBHPmodZ PATCHFSTAB DEBUG
./rootAVD.sh system-images/android-33/google_apis/arm64-v8a/ramdisk.img AddRCscripts
./rootAVD.sh system-images/android-33/google_apis_playstore/arm64-v8a/ramdisk.img
./rootAVD.sh system-images/android-33/google_apis_playstore/arm64-v8a/ramdisk.img FAKEBOOTIMG
./rootAVD.sh system-images/android-33/google_apis_playstore/arm64-v8a/ramdisk.img DEBUG PATCHFSTAB GetUSBHPmodZ
./rootAVD.sh system-images/android-33/google_apis_playstore/arm64-v8a/ramdisk.img restore
./rootAVD.sh system-images/android-33/google_apis_playstore/arm64-v8a/ramdisk.img InstallKernelModules
./rootAVD.sh system-images/android-33/google_apis_playstore/arm64-v8a/ramdisk.img InstallPrebuiltKernelModules
./rootAVD.sh system-images/android-33/google_apis_playstore/arm64-v8a/ramdisk.img InstallPrebuiltKernelModules GetUSBHPmodZ PATCHFSTAB DEBUG
./rootAVD.sh system-images/android-33/google_apis_playstore/arm64-v8a/ramdisk.img AddRCscripts
./rootAVD.sh system-images/android-34/google_apis/arm64-v8a/ramdisk.img
./rootAVD.sh system-images/android-34/google_apis/arm64-v8a/ramdisk.img FAKEBOOTIMG
./rootAVD.sh system-images/android-34/google_apis/arm64-v8a/ramdisk.img DEBUG PATCHFSTAB GetUSBHPmodZ
./rootAVD.sh system-images/android-34/google_apis/arm64-v8a/ramdisk.img restore
./rootAVD.sh system-images/android-34/google_apis/arm64-v8a/ramdisk.img InstallKernelModules
./rootAVD.sh system-images/android-34/google_apis/arm64-v8a/ramdisk.img InstallPrebuiltKernelModules
./rootAVD.sh system-images/android-34/google_apis/arm64-v8a/ramdisk.img InstallPrebuiltKernelModules GetUSBHPmodZ PATCHFSTAB DEBUG
./rootAVD.sh system-images/android-34/google_apis/arm64-v8a/ramdisk.img AddRCscripts
我这因为来回踩坑,装的镜像有点多,找到我们的目标 API -> system-images/android-33/google_apis/arm64-v8a/ramdisk.img。
yuman@U-N9CQ49WD-2247: ~/workspace/android/rootAVD-master
$ ./rootAVD.sh system-images/android-33/google_apis/arm64-v8a/ramdisk.img FAKEBOOTIMG [17:55:09]
[!] and we are NOT in an emulator shell
[*] Set Directorys
[-] source.properties file exist
[*] AVD system-image Pkg.Revision=16
[-] Test if ADB SHELL is working
[*] ADB connection possible
[-] In any AVD via ADB, you can execute code without root in /data/data/com.android.shell
[*] Cleaning up the ADB working space
[*] Creating the ADB working space
[-] Magisk installer Zip exists already
[*] Push Magisk.zip into /data/data/com.android.shell/Magisk
[-]
[-] ramdisk.img Backup exists already
[*] Push ramdisk.img into /data/data/com.android.shell/Magisk/ramdisk.img
[-]
[*] Push rootAVD.sh into /data/data/com.android.shell/Magisk
[-]
[-] run the actually Boot/Ramdisk/Kernel Image Patch Script
[*] from Magisk by topjohnwu and modded by NewBit XDA
[!] We are in a ranchu emulator shell
[-] Api Level Arch Detect
[-] Device Platform is arm64 only
[-] Device SDK API: 33
[-] First API Level: 33
[-] The AVD runs on Android 13
[-] Switch to the location of the script file
[*] Looking for an unzip binary
[-] unzip binary found
[*] Extracting busybox and Magisk.zip via unzip ...
[*] Finding a working Busybox Version
[*] Testing Busybox /data/data/com.android.shell/Magisk/lib/arm64-v8a/libbusybox.so
[!] Found a working Busybox Version
[!] BusyBox v1.36.1-Magisk (2023-09-02 05:30:11 PDT) multi-call binary.
[*] Move busybox from lib to workdir
[-] Checking AVDs Internet connection...
[-] Checking AVDs Internet connection another way...
[!] AVD is offline
[*] Re-Run rootAVD in Magisk Busybox STANDALONE (D)ASH
[-] We are now in Magisk Busybox STANDALONE (D)ASH
[*] rootAVD with Magisk '27.0' Installer
[-] Get Flags
[*] System-as-root, keep dm/avb-verity
[-] Encrypted data, keep forceencrypt
[*] RECOVERYMODE=false
[-] KEEPVERITY=true
[*] KEEPFORCEENCRYPT=true
[-] copy all arm64-v8a files from /data/data/com.android.shell/Magisk/lib/arm64-v8a to /data/data/com.android.shell/Magisk
[-] copy 'stub.apk' from /data/data/com.android.shell/Magisk/assets to /data/data/com.android.shell/Magisk
[*] Detecting ramdisk.img compression
[!] Ramdisk.img uses lz4_legacy compression
[-] taken from shakalaca's MagiskOnEmulator/process.sh
[*] executing ramdisk splitting / extraction / repacking
[-] API level greater then 30
[*] Check if we need to repack ramdisk before patching ..
[*] After decompressing ramdisk.img, magiskboot will work
Detected format: [lz4_legacy]
[!] allowing MANAGE_EXTERNAL_STORAGE permissions to...
[*] Processing fake Boot.img
[*] Creating a fake Boot.img
[-] removing old /sdcard/Download/fakeboot.img
[!] Only a minimal header is required for Magisk to repack the ramdisk
[*] repacking ramdisk.img into /sdcard/Download/fakeboot.img
[*] /sdcard/Download/fakeboot.img could not be created
[-] Magisk expects a more complete boot.img header as source
[*] Adding /data/data/com.android.shell/Magisk/ramdisk.cpio to fakeboot.img header
[*] Checking filesize Padding for Pagesize 2048
[*] Padding filesize to match Pagesize of 2048 Bytes
[-] repacking ramdisk.img into /sdcard/Download/fakeboot.img with the more complete header
[!] /sdcard/Download/fakeboot.img created
[*] Searching for pre installed Magisk Apps
[!] Temporarily installing Magisk
[*] Detecting current user
[-] Current user 0
[-] Starting Magisk
[*] Install/Patch /sdcard/Download/fakeboot.img and hit Enter when done(max. 60s)
最后的一行“Install/Patch /sdcard/Download/fakeboot.img”意思是让你装下“fakeboot.img”,但是好像不装也没关系。
运行完之后系统会自动重启,可以看到 Magisk 已经成功安装了。如果没有成功,可以重启多试几次。
然后我们看下 adb root 是否已经可用,正常的话系统已经成功 root。
yuman@U-N9CQ49WD-2247: ~/workspace/android/rootAVD-master
$ adb root [17:55:32]
restarting adbd as root
yuman@U-N9CQ49WD-2247: ~/workspace/android/rootAVD-master
$ adb shell [17:59:02]
emu64a:/ #
请求抓取
使用系统代理
现在我们来配置下 Charles,其实很简单,只需要打开正常的代理配置即可。
同时在 AVD 中配置上网络代理。
这里需要注意的 hostname 需要填 10.0.2.2,10.0.2.2 是安卓模拟器主机的特殊别名,这里也踩过坑,填电脑 IP 的话偶尔好使,大部分时间不好使。
打开某著名XX APP
系统代理的问题
查看 Charles 中拦截的请求,发现好像只有图片,视频之类的请求。难道数据的请求都走的 TCP 或者其他方式吗?搜索后发现应该是 Proxy.NO_PROXY 在作怪,Android 一般都使用 OkHttp 包作为 Http 请求工具类,在使用时候可以设置 Proxy.NO_PROXY 属性,来防止通过网络代理方式抓包。类似如下的代码。
OkHttpClient client = new OkHttpClient.Builder().proxy(Proxy.NO_PROXY).build();
FormBody form = new FormBody.Builder()
.add("user", dataMap.get("username"))
.add("pwd", dataMap.get("password"))
.add("sign", dataMap.get("sign")).build();
Request req = new Request.Builder().url("http://192.168.0.6:9999/login").post(form).build();
NO_PROXY 问题解决
这时候就需要借助一些流量转发软件如 SocksDroid,将客户端的流量转发到代理服务器上,而不是通过使用系统网络代理的方式。
首先,我们需要将 Charles 的 SOCKS 代理打开,因为 SocksDroid 是基于 SOCKS5 协议做流量转发。
然后我们回到 AVD,需要将系统网络代理关掉。最后配置下 SocksDroid。基本照下图片做配置即可。
再次打开 APP,刷新一下页面,我们再看下 Charles。
https 问题解决
可以发现,多出来 api 域名请求的记录,看这域名名字基本就是常用的服务接口没跑了。但是由于服务协议是 https ,因此请求都是 unknow,请求及返回的内容都是乱码。下面就是解决终极问题 - https 的时候了。说实话 https 这个问题折腾了蛮久,尝试了各种方法都不行,即使设备已经 root 了,但是依然无法将证书写到系统目录下(也可能是因为使用的是 AVD,好像还要解 bl 锁)。直到搜到一个帖子试了下,竟然成功了。这种方法仅在 Android 13 上有效,Android 14 又又又升级了安全策略,这种方式已失效。
首先我们需要下载 Charles 的证书。可以通过访问 chls.pro/ssl 进行下载,或者直接在 Charles 中保存下来。
由于安卓上存储的证书都是以文件的 hash 码命名,所以我们也要按照这个规则来,先计算出文件的 hash 码,再将文件重命名。
yuman@U-N9CQ49WD-2247: ~/data
$ openssl x509 -subject_hash_old -in ~/Downloads/charles-ssl-proxying-certificate.pem [17:36:37]
c855b6dd
-----BEGIN CERTIFICATE-----
MIIFUDCCBDigAwIBAgIGAZHU1oy1MA0GCSqGSIb3DQEBCwUAMIGsMT0wOwYDVQQD
DDRDaGFybGVzIFByb3h5IENBICg5IFNlcCAyMDI0LCBVLU45Q1E0OVdELTIyNDcu
bG9jYWwpMSUwIwYDVQQLDBxodHRwczovL2NoYXJsZXNwcm94eS5jb20vc3NsMREw
DwYDVQQKDAhYSzcyIEx0ZDERMA8GA1UEBwwIQXVja2xhbmQxETAPBgNVBAgMCEF1
Y2tsYW5kMQswCQYDVQQGEwJOWjAeFw0yNDA5MDgwMzMxNTZaFw0yNTA5MDgwMzMx
NTZaMIGsMT0wOwYDVQQDDDRDaGFybGVzIFByb3h5IENBICg5IFNlcCAyMDI0LCBV
LU45Q1E0OVdELTIyNDcubG9jYWwpMSUwIwYDVQQLDBxodHRwczovL2NoYXJsZXNw
cm94eS5jb20vc3NsMREwDwYDVQQKDAhYSzcyIEx0ZDERMA8GA1UEBwwIQXVja2xh
bmQxETAPBgNVBAgMCEF1Y2tsYW5kMQswCQYDVQQGEwJOWjCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAIq0SC7f2+nyzZtqp0mBdAWF3goHdIS1Ab0x7g+4
rvbg8Mp6AdrxmnBAAYgt7DVo2OBv7XXotaJ+FTpZWCvtxorQt+z9QCnV+sQ4hWSR
RJuRpOPA2+sILN+uMjwv2hhfa95JqV9REpsylZpiOSUYDXtGlqh+FmphG1cnvC2H
cJmUk2kcXGd3MmirhfkL63JlSy0SOMUlxEK0UUSBbsfqiC/VBjuM4swXR8iBhUiJ
zmDjswJ9cEzqo5A54nIKZKnz9gnVIZol7oj46LVtvg5yDHYJihPshZAgH0g3hsuJ
4r0O4LQopw+hP3Z4H7UdQmW22D9vQIIwzxoqOgzA38Zk3X0CAwEAAaOCAXQwggFw
MA8GA1UdEwEB/wQFMAMBAf8wggEsBglghkgBhvhCAQ0EggEdE4IBGVRoaXMgUm9v
dCBjZXJ0aWZpY2F0ZSB3YXMgZ2VuZXJhdGVkIGJ5IENoYXJsZXMgUHJveHkgZm9y
IFNTTCBQcm94eWluZy4gSWYgdGhpcyBjZXJ0aWZpY2F0ZSBpcyBwYXJ0IG9mIGEg
Y2VydGlmaWNhdGUgY2hhaW4sIHRoaXMgbWVhbnMgdGhhdCB5b3UncmUgYnJvd3Np
bmcgdGhyb3VnaCBDaGFybGVzIFByb3h5IHdpdGggU1NMIFByb3h5aW5nIGVuYWJs
ZWQgZm9yIHRoaXMgd2Vic2l0ZS4gUGxlYXNlIHNlZSBodHRwOi8vY2hhcmxlc3By
b3h5LmNvbS9zc2wgZm9yIG1vcmUgaW5mb3JtYXRpb24uMA4GA1UdDwEB/wQEAwIC
BDAdBgNVHQ4EFgQULVxwSQ0VmWEEJ4eD19lgWaiUO2IwDQYJKoZIhvcNAQELBQAD
ggEBAFpxIHjcNYNUIinWn+maGAHTahdtHqIgSh+NIRSdnQVMzl1glYAUAcjvhdSr
hqiM/3wNhm4S28HE+khwVVKJrM+XnAQ8G0qUlK8MkTuLhJ+9bcXjlPic7LGY4zO7
c8CIrZEmdBYjqzjYJIReoFwiU2H2OLBRSx1eNfp2mOnxddIL3dFkiAKXl6+nsf9l
tswO6rURH6DNA6cmmC0/6elZ0RtgoaGItXkhQfYhtm9rEG3cLNJOas6blCsf4cgA
ktL/wcOI/E07GP25fSa1eSxhuE+KvL35pXbs41+nLTN8IGHiwoDE/gEGtdECrG90
/0G6Evsqw1cVdjcbdRxEEAnrnyc=
-----END CERTIFICATE-----
yuman@U-N9CQ49WD-2247: ~/data
$ mv ~/Downloads/charles-ssl-proxying-certificate.pem c855b6dd.0
然后使用 adb push 到 AVD 中,并执行 adb shell 进入 AVD shell,检查下文件是否被正常 push。
yuman@U-N9CQ49WD-2247: ~/data
$ adb push c855b6dd.0 /sdcard/Download/ [20:30:39]
c855b6dd.0: 1 file pushed, 0 skipped. 2.3 MB/s (1921 bytes in 0.001s)
yuman@U-N9CQ49WD-2247: ~/data
$ adb shell [20:32:55]
emu64a:/ # ls -lh /sdcard/Download/
total 130M
-rw-rw---- 1 u0_a165 media_rw 1.8K 2024-10-15 20:22 c855b6dd.0
-rw-rw---- 1 u0_a165 media_rw 2.0M 2024-10-15 17:55 fakeboot.img
接着就是见证奇迹的时刻,执行下面一堆命令
emu64a:/ # mkdir -m 700 /data/local/tmp/htk-ca-copy
emu64a:/ # cp /system/etc/security/cacerts/* /data/local/tmp/htk-ca-copy/
emu64a:/ # mount -t tmpfs tmpfs /system/etc/security/cacerts
emu64a:/ # mv /data/local/tmp/htk-ca-copy/* /system/etc/security/cacerts/
emu64a:/ # cp /sdcard/Download/c855b6dd.0 /system/etc/security/cacerts/
emu64a:/ # chown root:root /system/etc/security/cacerts/*
emu64a:/ # chmod 644 /system/etc/security/cacerts/*
emu64a:/ # chcon u:object_r:system_file:s0 /system/etc/security/cacerts/*
emu64a:/ # rm -r /data/local/tmp/htk-ca-copy
emu64a:/ # ls /system/etc/security/cacerts/|grep c855b6dd
c855b6dd.0
最后的 ls 只是为了验证下文件是否被正常写入而已。
翻一下上面的一堆命令,大概是这么个意思
- 从 /system/etc/security/cacerts/ 中复制所有系统证书到临时目录。
- 在 /system/etc/security/cacerts/ 上面挂载一个 tmpfs 内存文件系统。这实际上将一个可写的全新空文件系统放在了 /system 的一小部分上面。
- 将复制的系统证书移回到该挂载点。
- 将 Charles CA 证书也移动到该挂载点。
- 更新临时挂载点中所有文件的权限为 644,并将系统文件的 SELinux 标签设置为 system_file,以使其看起来像是合法的 Android 系统文件。
- Pushes the HTTP Toolkit CA certificate to the device over ADB.
- Copies all system certificates out of
/system/etc/security/cacerts/to a temporary directory.- Mounts a tmpfsopens in a new tab in-memory filesystem on top of
/system/etc/security/cacerts/. This effectively places a fresh empty filesystem that is writable over the top of a small part of/system.- Moves the copied system certificates back into that mount.
- Moves the HTTP Toolkit CA certificate into that mount too.
- Updates the permissions to
644& sets thesystem_fileSELinux label on everything in the temporary mount, so it all looks like legitimate Android system files.- Checks if
/apex/com.android.conscrypt/cacertsis present, and if so it enters the mount namespace (withnsenter) of all Zygote processes (which launch apps) and every running app, to bind mount the system certificate path over that APEX path (if you're interested, I've written a more detailed article about the full Android 14 CA certificate injection processopens in a new tab).
核心就是挂载一个内存文件系统,由于是内存文件系统,所以重启手机后就会失效。
然后我们需要将 Charles 的 SSL Proxying Setting 打开,让 Charles 来代理 SSL 请求,这样才能真正的拦截 SSL 相关的请求。
最后,让我们来刷新下 APP 中的页面,完美!
本文的目的只有一个就是学习更多的逆向技巧和思路,如果有人利用本文技术去进行非法商业获取利益带来的法律责任都是操作者自己承担,和本文以及作者无关