
做安卓应用安全分析和手机取证的人肯定都经历过这种场面一台旧安卓机摆在面前要搞清楚上面装了哪些第三方应用每个 APK 申请了什么权限反编译后能看到哪些值得留意的字符串应用数据里又剩下什么“痕迹”。说起来不算复杂真动手却很磨人。光是把设备上所有第三方 APK 逐个提取、反编译、查特征就要大半天要是再算上后续的数据采集、哈希校验和报告整理时间直接翻倍。我最近把这条链路整理成了一键式的自动化工作流代号 OpenClawWeComzh。它不做颠覆性的技术革新只是把安卓 APK 分析和手机取证这些零散操作串成一条可重复执行、可追溯的流水线自动识别设备、批量提取 APK、解析权限与元数据、通过反编译定位风险特征、收集设备与应用数据、计算完整性校验值最后输出带时间线的报告。这篇文章适合三类人来读正在做移动安全研究、需要快速给一批 APK 建索引分析的同学做手机取证、要留下清晰证据目录的从业者以及刚接触 APK 分析、希望少踩坑的安卓开发。接下来从环境搭建讲到实战排错尽量让不同基础的读者都能把流程跑起来。进阶玩法我也会聊但主线始终是“先把基础自动化做扎实”。1. 为什么要把 APK 分析与手机取证做成一条自动化流水线1.1 单点工具多串不起来才是真痛点安卓分析生态里其实不缺好工具。抓包有 mitmproxy反编译有 jadx、apktool设备交互有 adbSQLite 查看有各种 GUI哈希校验更是随便一个脚本都能做。问题在于这些工具默认情况下都是独立的“孤岛”。我早期做基础分析时流程一般是这样手动adb shell pm list packages -3拉出第三方包列表再逐个pm path找 APK 位置adb pull到本机然后用 jadx 反编译用 aapt dump badging 看权限再凭直觉搜索一段关键词。听起来只有五六步实际做下来非常痛苦——每台机器安装的应用不一样拉下来的 APK 路径参差不齐反编译产物多到 grep 都不知道从哪里下手最后写报告时还要重新打开每个目录手动汇总。真正要解决的痛点不是某一个环节跑得慢而是环节之间的衔接太脆弱。只要中间任何一个操作漏掉比如拉错 APK、漏看一个权限、忘记记录取证时间整个结论的可信度都会打折扣。自动化解决的就是这种“衔接问题”。把每一步的输入输出固定下来让脚本替人记住哪些文件拉过了、哪些目录已经哈希校验这样人只需要把精力放在判断结果上而不是纠结有没有漏流程。1.2 OpenClawWeComzh 的定位与核心能力OpenClawWeComzh 这个名字可以理解成“一只在安卓系统里扒拉证据的爪子”。它不是我重新写的逆向引擎而是一个编排层把 adb、aapt、apktool、jadx、哈希工具这些基础组件包在一个统一的工作流里。所有模块按顺序执行每个模块的产物都落到固定的目录结构中最后生成汇总报告。这套工作流的基础能力包括自动检测 adb 连接的设备并读取设备信息从设备上批量提取第三方 APK解析每个 APK 的包名、版本、SDK 版本与权限声明反编译 Java/Kotlin 代码并搜索风险特征收集系统运行状态与目标应用的逻辑数据对所有证据文件计算 SHA-256 并留存校验清单最后输出 JSON 和 HTML 两种格式的报告。它解决的核心问题就是在一台“已知来源”的设备上把从 APK 静态分析到手机取证的常规动作压缩成一条命令就能完成的任务。能做到这一步其实不需要太高深的技术关键是把流程想清楚再动手写脚本。这也是这篇文章想带给大家的东西——不是让你背我的代码而是理解一条流水线应该怎么设计。1.3 自动化的边界哪些环节让机器做哪些必须人来扛把话说在前面自动化不是万能的。我见过一些人拿到脚本就无脑跑最后把结果当圣旨这是很危险的取向。自动化真正擅长的是那些“可验证、可重复”的环节提取文件、解析格式、搜索特征、计算哈希、整理时间戳。这些操作不需要太多现场判断交给脚本反而更可靠还能避免人为手误。但判断“这个 APK 里的可疑字符串到底意味着什么”或者“这份证据在案件里有多大价值”这些工作必须人来完成。比如 jadx 反编译后看到一段 Base64 硬编码脚本只能告诉你“这里有一串疑似密钥的字符串”至于它是不是真正起作用的密钥、关联到哪个接口需要结合上下文阅读代码才能确认。所以我在设计 OpenClawWeComzh 时刻意把流程分成了“自动采集”和“人工复核”两个阶段。脚本负责把所有原始材料摆到桌面上并生成一份提示清单分析人员则对着清单逐项确认必要时打开反编译代码细看。这样既省时间又不丢分析深度。2. 环境搭建从一根 USB 线到能跑通的脚本2.1 主机侧工具清单与安装这部分没什么捷径先把工具链装齐。我一般会在独立的虚拟机或隔离环境里跑这类分析避免把待分析样本直接放到日常工作机上。工具清单如下adbAndroid Debug Bridge负责与设备通信提取 APK、拉取数据都靠它。aapt / aapt2解析 APK 元数据、权限列表的“读卡器”一般在 Android SDK build-tools 里。apktool反编译资源文件、查看 smali 码、回编译测试用。jadx把 dex 还原成可读性更好的 Java 源码日常搜索特征的主力工具。Python 3用来写批量调度脚本、解析 badging 输出、生成 JSON/HTML 报告。sha256sumLinux/macOS或 Get-FileHashWindows做完整性校验。安装方式按平台走就行。macOS 用 Homebrew 最省事brew install android-platform-tools brew install jadx brew install apktool # aapt 需要安装 Android SDK build-tools或用 android-sdk 相关 caskDebian/Ubuntu 系的机器可以用系统包管理器装一部分但版本可能偏旧。推荐直接下载 Android command-line tools再用 sdkmanager 装 build-toolsjadx 和 apktool 直接从 GitHub release 下载解压后加入 PATH。sudo apt update sudo apt install -y android-tools-adb default-jdk unzip wget2.2 手机侧准备与连接检测测试机上要做的准备很少但每一条都可能卡住整个流程。打开“开发者选项”和“USB 调试”这个大家都知道容易忽略的是“屏幕常亮”和“锁屏方式”。如果分析过程中屏幕灭了某些操作的权限弹窗出不来adb 会话也可能受影响。我习惯在设置里把锁屏改成“无”或者至少保证屏幕常亮。设备通过 USB 连接后第一件事永远是确认 adb 能看到设备adb start-server adb devices -l正常输出里应该有一行设备的序列号状态为device。如果看到unauthorized说明手机上的调试授权弹窗没有被确认需要点亮屏幕手动点“允许”。如果看到offline大概率是 USB 线质量问题或者 adb 服务状态异常换一根线或者执行adb kill-server再adb start-server通常能解决。这里补一个判断 Android 版本的小命令后面很多兼容性判断会用到adb shell getprop ro.build.version.release adb shell getprop ro.product.model先把这些基础信息记录下来因为报告里也需要。2.3 最小可用脚本自动识别接入设备环境准备好以后我会先写一个很短的探测脚本。它的作用不是分析而是快速返回“当前有几台设备、分别是什么型号、Android 版本是多少”为后续批量操作做准备。#!/usr/bin/env bash # device_probe.sh adb start-server /dev/null 21 echo 设备列表 adb devices -l echo echo 设备详情 for serial in $(adb devices | awk NR1 $2device {print $1}); do echo 序列号: $serial echo 型号: $(adb -s $serial shell getprop ro.product.model | tr -d \r) echo 品牌: $(adb -s $serial shell getprop ro.product.brand | tr -d \r) echo 系统: Android $(adb -s $serial shell getprop ro.build.version.release | tr -d \r) echo SDK: $(adb -s $serial shell getprop ro.build.version.sdk | tr -d \r) done这个脚本看起来简单却是我所有自动化的起点。后面所有批量任务都会基于“遍历设备列表”这个思想展开只是把内容换成 APK 拉取、数据采集等具体操作。我建议你先把这一步跑通设备识别稳了后续流程才有保障。3. APK 提取与静态分析自动化3.1 批量拉取第三方 APK 的正确姿势拿到一台测试机第一步是列出所有第三方应用。为什么只列第三方因为系统内置应用数量庞大而且其中大多数不是我们要分析的对象。在受控分析场景下用户后来安装的应用才是关注重点。adb shell pm list packages -3输出格式是package:com.example.something。我们需要把包名前缀去掉然后逐个查询 APK 路径并拉取。这里有一个容易被忽视的坑一个包名可能对应多个 APK 路径尤其是使用 split APK 机制的应用例如某些大型游戏路径不止一条。如果只拉第一行会漏掉部分代码模块。所以脚本里要处理所有路径#!/usr/bin/env bash # pull_apks.sh serial$1 out_dirapks if [ -z $serial ]; then echo 用法: ./pull_apks.sh 设备序列号 exit 1 fi mkdir -p $out_dir for pkg in $(adb -s $serial shell pm list packages -3 | sed s/^package:// | tr -d \r); do echo [*] 处理包名: $pkg paths$(adb -s $serial shell pm path $pkg | sed s/^package:// | tr -d \r) for apk_path in $paths; do apk_name$(basename $apk_path) mkdir -p $out_dir/$pkg adb -s $serial pull $apk_path $out_dir/$pkg/$apk_name done done echo [*] 拉取完成这里tr -d \r是用来去掉 Windows 环境下多出来的回车符很多从 Windows 下跑脚本的同学会栽在这个小细节上。输出目录按包名/文件名组织后续反编译和哈希校验都会方便很多。3.2 元数据与权限解析从 badging 里挖线索APK 拉下来之后静态分析的第一个动作是看“门面”。这里的门面指的是 AndroidManifest 里的包名、版本号、SDK 版本、权限声明等元数据。aapt 可以一次性把这些信息 dump 出来aapt dump badging apks/com.example.test/base.apk badging.txtbadging 输出里有几类关键字段值得写脚本解析。package:行能同时看到包名和版本号sdkVersion:与targetSdkVersion:决定应用在哪个安卓版本区间运行uses-permission:则列出了所有申请的权限。我用一个简单的组合命令快速提取grep -E ^package:|^sdkVersion:|^targetSdkVersion:|^uses-permission: badging.txt拿到权限列表后不要只看数量要看“质量”。我习惯拿出一个重点权限集合做标注包括但不限于权限说明为什么值得关注READ_SMS读取短信涉及敏感通信内容READ_CONTACTS读取通讯录常见于通讯录同步类应用ACCESS_FINE_LOCATION精确定位可能持续跟踪位置RECORD_AUDIO录音需要明确用户授权场景SYSTEM_ALERT_WINDOW悬浮窗可能干扰其他应用REQUEST_INSTALL_PACKAGES安装其他应用高风险敏感能力如果在某个工具类应用里看到高风险权限组合比如既读通讯录又录音还带悬浮窗那就要提高警惕继续往代码层面挖。3.3 反编译与关键词匹配定位风险证据静态分析只靠看权限是不够的还得进代码里找证据。jadx 是这步的主力工具。一条命令就能把 APK 批量反编译到目录mkdir -p src for apk in apks/*/*.apk; do outsrc/$(basename $(dirname $apk)) jadx -d $out $apk /dev/null 21 done反编译完成以后搜索就成了重头戏。我会在代码目录里跑一批关键词覆盖几类常见风险特征敏感权限相关的 API 调用SmsManager、getDeviceId、getSimSerialNumber、LocationManager等。网络行为特征http://、https://、Socket、WebSocket、baseUrl。隐藏逻辑特征RootBeer、Magisk、isRooted、AccessibilityService。加密与密钥线索AES、RSA、SecretKeySpec、Base64、MD5。实际操作中我用的是一条比较宽的 grepgrep -rE READ_SMS|READ_CONTACTS|ACCESS_FINE_LOCATION|RECORD_AUDIO|getDeviceId|http://|https:// \ src/ | head -100不过要提醒一下这类搜索是“广撒网”命中结果里一定会有大量误报。比如一个正常的新闻客户端也会请求定位权限也会调LocationManager这不能一锤定音。搜索的价值是帮你把高嫌疑区域筛出来然后再去读上下文判断行为是否合理。自动化在这里做的事情是把“搜索范围”和“命中的候选列表”固化下来避免每次手工重复。3.4 混合应用Unity/Cocos的 APK 分析差异现在很多应用不是纯 Java/Kotlin 写的尤其游戏类应用常见的是 Unity 或 Cocos 引擎。这类 APK 里大量业务代码并不在 dex 里而是编译进了libil2cpp.so或libcocos.so这样的原生库中。直接用 jadx 搜 Java 层能看到的逻辑非常有限。遇到 Unity 引擎的 APK我会把lib/arm64-v8a/libil2cpp.so提取出来先用strings命令扫一遍strings lib/arm64-v8a/libil2cpp.so | grep -E http|https|key|base64|Alipay|WeChat | head -100Cocos 引擎的包也是类似思路关键逻辑在libcocos.so和脚本资源里。定位到疑似关键函数后再用 Ghidra 或 IDA 进一步看反汇编。这个玩法已经不是基础流水线能覆盖的了但在章节末尾提出来很重要——避免大家拿着全套自动化脚本碰上游游戏包就误以为“分析完了”。4. 手机取证全流程自动化实操4.1 设备信息与运行状态采集APK 静态分析之外手机取证还需要采集设备和运行时信息。这些信息能还原“设备在某个时间点发生了什么事”跟 APK 分析互为补充。我在流程里固定采集以下几类设备属性型号、Android 版本、序列号、内核版本用getprop获取。包管理信息dumpsys package 包名包含权限授予状态、安装时间等关键信息。运行状态dumpsys activity activities看当前 Activity 栈dumpsys appops看应用对权限的实际使用情况这是静态权限声明之外很重要的一层。使用统计dumpsys usagestats能给出应用的前后台使用时间窗口。把这些命令的原始输出保存下来比只看汇总结论更有价值。取证讲究原始记录一条一条带有时间戳的 dump 文件本身就是证据链的一部分。我会把它们统一放进evidence/序列号/时间戳/目录。mkdir -p evidence/$serial/$(date %Y%m%d%H%M%S) adb -s $serial shell dumpsys package evidence/$serial/dumpsys_package.txt adb -s $serial shell dumpsys activity activities evidence/$serial/activity_stack.txt adb -s $serial shell dumpsys appops evidence/$serial/appops.txt adb -s $serial shell dumpsys usagestats evidence/$serial/usagestats.txt4.2 目标应用数据提取有 root 与无 root 两条路APK 文件本身只是一部分应用运行时留在设备里的数据往往信息量更大。提取路径跟设备有没有 root 权限直接相关要分两种方案来写。没有 root 的设备能够做的通常是“逻辑提取”。比如应用在外部存储或 DCIM 目录留下的文件、数据库副本、以及通过系统备份接口导出的数据。adb backup是曾经很常用的方式但安卓 12 及更高版本对非 root 应用的备份限制越来越严很多应用的备份数据会变成加密状态甚至直接拒绝备份。所以我在无 root 场景下一般优先提取应用主动暴露出来的文件或者用户目录下可访问的数据库。有 root 权限的测试设备提取方式直接很多。目标应用的数据目录通常位于/data/data/包名其中可能包含数据库、SharedPreferences 缓存等。在授权分析环境中我习惯先打包再拉取adb -s $serial shell su -c tar -czf /sdcard/evidence_${pkg}.tgz /data/data/${pkg} adb -s $serial pull /sdcard/evidence_${pkg}.tgz evidence/$serial/ adb -s $serial shell rm -f /sdcard/evidence_${pkg}.tgz这里有几个细节。第一先把数据打包到/sdcard再 pull是因为直接对/data/data目录做多次小文件拷贝容易触发 I/O 限制而且包成单文件不容易漏。第二拿到压缩包后最好保留原始压缩包和原始 dump 文件不要因为方便就删掉一份。第三所有提取操作都必须保证设备连接稳定充电状态优先防止中途断电导致证据文件损坏。4.3 完整性校验与证据目录归档取证报告里如果没有哈希校验基本等于白做。校验的目的很简单证明你提交的证据文件和分析时看到的文件是同一个中间没有被篡改或误操作。自动化流程里我会在分析结束后对两类文件做哈希。一类是 APK 源文件另一类是取证采集到的 dump 文件。脚本里直接串起来find apks evidence -type f -exec sha256sum {} \; hashes.sha256生成hashes.sha256之后再额外生成一个带时间戳的副本cp hashes.sha256 hashes_$(date %Y%m%d%H%M%S).sha256注意哈希校验一定要在“原始文件还能被独立验证”的时候做。如果先压缩再校验校验的对象应该是压缩包本身如果直接校验散装文件那就要保留散装目录。归档原则就一句话每一步操作的输入和输出都要能对上账。4.4 自动生成取证报告自动化跑完以后所有材料都在。但一堆原始 dump 和哈希清单对阅读者并不友好需要汇总成报告。我用 Python 做简单聚合遍历apks/目录下每个 APK 的 badging 信息提取包名、版本、权限列表读取hashes.sha256把哈希值挂到对应文件上再读取设备属性文件拼出设备概览。报告分成两页即可。一页是 JSON方便程序化读取和二次分析一页是 HTML方便人工浏览。HTML 模板里我会固定输出几个区块案件与设备信息、APK 清单、权限风险提示、取证文件清单与哈希值、操作时间线。时间来自脚本执行时的系统时钟注意与设备时间做基础比对至少要记录两种时间不能只依赖其中一种。这里的关键经验是报告的价值不在于华丽而在于完整记录“何时、何地、何人、对什么设备、做了什么操作、产出什么文件”。每一份报告都该能让人原地复原整个分析流程。5. 常见踩坑与问题排查实录5.1 adb 连接与会话权限问题最常碰到的就是这个。设备第一次连接时必须在屏幕上点掉 USB 调试授权弹窗脚本里做不到自动处理。如果忘了点adb devices会显示unauthorized所有后续脚本都会卡在提取阶段。解决方式很简单但不一定都很顺利。第一点亮屏幕手动确认授权第二把设备上的“记住此电脑”选项打开避免每次重连都要授权第三如果设备显示offline优先执行adb kill-server adb start-server重启 adb 服务再不行就拔掉 USB 线重插或者换一个接口。另外批量跑多台设备时每条 adb 命令都要带上-s 序列号否则 adb 会报“more than one device/emulator”直接退出。这是个特别容易忽略的坑脚本写了循环却忘了每个子命令都要指定设备结果跑一半就断了。5.2 APK 安装降级错误与多用户目录在逆向分析过程中有时候需要把修改过的 APK 装回设备做验证。如果设备上已经安装过更高版本的应用会看到INSTALL_FAILED_VERSION_DOWNGRADE之类的报错。这时候可以加参数强制降级安装adb install -r -d app.apk其中-r是覆盖安装-d是允许版本降级。不过我这里要提醒一句给测试设备做验证性安装没问题但不要随便拿用户的主力机去测误装一个被改动过的 APK 可能带来不必要的麻烦。多用户目录的问题更隐蔽。有些设备开了分身或多用户空间pm path可能返回多个路径。对应不同的 user 或 profile拉 APK 时要留意路径前缀里的user/0或者user/999。如果不区分最终分析结果可能搞混来源用户取证报告的准确性就受损了。5.3 拆包 APKsplit APK导致的丢包问题前面提到过部分大型应用会拆分成 base.apk 和多个 split 包。如果只关注了第一个路径拉回来的 APK 往往只能反映壳子核心功能模块缺失反编译出来自然什么有用的代码都看不到。排查方法很简单看pm path返回了几行。一旦多于一行就要全部拉取并且把 APK 目录保留完整不要强行合并到同一个文件。签名一致性也值得顺手查一下即使它们都属于同一个应用签名不一致依然是不正常的现象可以用apksigner verify --print-certs逐个确认。5.4 备份数据解密与格式不兼容如果走了adb backup路线生成的.ab文件不是直接能读的普通压缩包。无密码备份是明文但带着自定义头有密码备份则是加密的解密需要类似android-backup-extractor的工具。安卓 12 以后这条路越来越窄很多应用直接禁止备份所以我对这套方案的优先级是降低的。更实用的替代思路是直接从应用在外部存储或可导出目录中留下的数据库入手。很多应用的数据库并没有被清理干净拉回来以后用 sqlite3 打开就能看到关键表结构。记住取证追求的是可行方案不是理论上的完整镜像。设备没有 root 权限时拿到一份可读的逻辑数据比纠结拿不到完整镜像要有用得多。6. 自动化进阶玩法与个人经验6.1 从单设备到多设备批量调度把单设备的流程跑通以后多设备批量并不复杂核心是“把设备序列号作为变量传下去”。前面提到的最小探测脚本已经实现了设备遍历。扩展到全流程时只需要在最外层对每个序列号开一个独立目录然后并行执行同一套流水线即可。并行跑的时候要注意几个点每台设备的 adb 命令都加-s避免设备冲突输出目录用序列号隔离防止数据串台在脚本里加入超时控制防止某台设备卡住整条队列。如果设备数量多到几十台我会考虑用 adb 的无线调试模式统一管理前提是测试环境网络可控。6.2 集成动态检测工具静态分析再细致也只能覆盖到代码声明层。对于加壳应用、动态加载代码、混淆严重的样本静态搜出来的线索可能只是冰山一角。进阶玩法是把动态检测工具也接进流水线。我现在常搭配三样东西。第一Frida用来 Hook 关键函数观察应用运行时的真实调用链。第二UI 自动化工具类似 maestro 那种把用户操作流程脚本化自动触发登录、点击等行为配合抓包看网络请求。第三本地流量代理把所有 HTTPS 流量解密记录。这三样的接入会让整套流程从“APK 静态分析 数据提取”升级成“动静态结合的行为分析”。但代价是复杂度明显上升建议等基础自动化稳定了再扩展。6.3 我在实践中的几条经验最后分享几条从实际项目里攒下的经验不按重要性排序只是想到哪写到哪。第一文件名和目录名一定要规范。看似无聊其实是救命神器。我见过太多人提取证据后随手扔在桌面几天后就分不清哪个文件对应哪次采集。我的习惯是设备序列号/采集时间/证据类型/文件名这条规则从第一天就定死。第二别迷信设备时间。手机系统时间可能被人为改动过或者长时间未同步导致偏差。取证记录里应该同时保存“设备时间”和“主机时间”并在报告里注明两者的来源。这听起来很基础却是最容易出事的地方。第三宁可多存一份不要少存一份。原始 dump 文件占了空间就占了分析过程中生成的所有中间文件我都建议保留到项目归档阶段再清理。硬盘很便宜但丢失原始证据后想补救代价极高。第四自动化脚本要经常回归测试。装上新的工具版本、换了设备型号、安卓系统升级都可能让旧脚本悄悄失效。我现在每次调整环境后都会拿一台固定的测试机跑一遍完整流程确保输出结构没有变异。这套 OpenClawWeComzh 基础流水线算不上有多惊艳但正是这些“固执”的基础工作让我在后续的分析里省下了大量时间。如果你刚开始搭自己的 APK 分析与手机取证自动化不妨先把流程跑通再慢慢加复杂度——稳住的流水线永远比花哨的半成品有用。