01. 安卓逆向基础、环境搭建与授权
边界说明:本文只面向自研 Demo、开源靶场或已获得书面授权的 App。所有操作目标都是理解 Android 应用结构、验证安全风险、建设防护能力,不用于未授权破解、盗号、绕过付费或攻击第三方服务。
1. 本章目标
学完本章后,应能完成四件事:
| 能力 | 说明 | 验收方式 |
|---|---|---|
| 理解 APK 构成 | 知道 Manifest、DEX、资源、Native 库、签名各自负责什么 | 能解压 APK 并标注每类文件用途 |
| 搭建工具链 | 准备 Android Studio、adb、jadx、apktool、apksigner、Frida、Burp/mitmproxy | 每个工具能输出版本或完成一次最小操作 |
| 创建授权 Demo | 自己写一个包含登录、会员判断、HTTPS 请求、Native 方法的测试 App | 能安装运行 debug 和 release APK |
| 建立实验记录 | 每次分析都有命令、截图、日志、结论和限制 | 输出case-notes.md |
安卓逆向学习最常见的问题是直接上工具,但不知道工具结果说明什么。本章先把 Android 应用的运行模型、工程产物和实验环境讲清楚,后续静态、动态、Native、防护章节都围绕同一个 Demo 进行。
2. Android 逆向必须先懂的基础
2.1 APK 是什么
APK 本质上是一个带签名的 ZIP 包。它不是单个可执行文件,而是由多个层次组成:
| 文件或目录 | 作用 | 逆向关注点 |
|---|---|---|
AndroidManifest.xml | 声明包名、权限、组件、入口、导出状态 | 组件暴露、调试开关、备份开关、Deep Link |
classes.dex | Java/Kotlin 编译后的 Dalvik 字节码 | 业务逻辑、加密逻辑、风控判断、接口调用 |
resources.arsc | 编译后的资源索引 | 字符串、布局、资源 ID 映射 |
res/ | 布局、图片、字符串等资源 | 页面结构、隐藏入口、硬编码文案 |
assets/ | 原样打包的资源文件 | 配置、证书、模型文件、脚本 |
lib/<abi>/*.so | Native 动态库 | JNI、加密、反调试、完整性校验 |
META-INF/或签名块 | APK 签名信息 | 是否被重签名、签名方案版本 |
逆向时不要只看 Java 反编译结果。很多关键逻辑会拆散在 Manifest、资源、Java/Kotlin、Native、网络请求和服务端校验之间。
2.2 Android 安全边界
Android 的基础安全模型包括:
- 应用沙箱:每个 App 默认拥有独立 UID,私有目录通常在
/data/data/<package>。 - 权限模型:危险权限需要运行时申请,组件导出需要额外权限或身份校验。
- 签名模型:同签名 App 可共享能力,升级安装依赖签名一致。
- 进程模型:Java 层、Native 层、系统服务通过 Binder、JNI、系统 API 协作。
- 网络模型:App 通过 OkHttp、Retrofit、HttpURLConnection、WebView 等发起请求。
逆向分析就是在这些边界上找证据:哪里把秘密放在客户端,哪里只做本地判断,哪里能被抓包重放,哪里缺少签名或完整性验证。
3. 工具链安装与验证
3.1 基础工具清单
| 工具 | 用途 | 验证命令或方法 |
|---|---|---|
| Android Studio | 创建 Demo、编译 APK、调试源码 | 能打开项目并运行模拟器 |
| Android SDK / adb | 安装、启动、日志、shell、文件操作 | adb devices |
| jadx / jadx-gui | APK 转近似 Java/Kotlin 源码 | jadx --version或打开 GUI |
| apktool | 反编译资源和 Smali,重打包 APK | apktool --version |
| apksigner | APK 签名、签名验证 | apksigner verify --verbose app.apk |
| keytool | 生成测试证书 | keytool -help |
| Frida / frida-tools | Java/Native Hook | frida --version、frida-ps -Uai |
| Burp Suite / mitmproxy | 抓包、改包、重放请求 | 能抓到 Demo 的 HTTP/HTTPS 请求 |
| Ghidra / IDA Free | Native 反编译 | 能打开.so并查看函数 |
3.2 adb 基础命令
adb devices adbinstallapp-debug.apk adb shell pm list packages|grepreverse adb shell dumpsys package com.example.reversedemo adb shell am start-ncom.example.reversedemo/.MainActivity adb logcat|grepReverseDemo adb shell run-as com.example.reversedemolsfiles关键理解:
adb install用于安装未上架测试包。dumpsys package能看到 Activity、Service、Receiver、Provider、权限和签名摘要。logcat是动态分析的第一手证据,但正式包不应输出敏感日志。run-as只对 debuggable 应用可用,正式包不能依赖这个能力。
3.3 Frida 设备验证
Frida 需要电脑端版本和设备端frida-server主版本一致。
frida--versionadb shell getprop ro.product.cpu.abi adb push frida-server /data/local/tmp/frida-server adb shellchmod755/data/local/tmp/frida-server adb shell /data/local/tmp/frida-server frida-ps-Uai验证标准:
| 检查项 | 通过标准 |
|---|---|
| USB 连接 | adb devices显示 device |
| Frida 服务 | 设备端frida-server正常运行 |
| 进程枚举 | frida-ps -Uai能列出 App |
| 版本一致 | 无 protocol mismatch 报错 |
4. 授权 Demo 工程设计
建议创建一个ReverseDemo,故意包含学习用的风险点和后续修复点。不要直接拿第三方商业 App 当练习目标。
4.1 Demo 功能清单
| 功能 | 初始实现 | 用于练习 |
|---|---|---|
| 登录页 | 用户名密码写死为demo/123456 | 静态字符串定位、日志检查 |
| 会员判断 | isVip()本地返回布尔值 | Smali 修改、Frida Hook |
| 接口请求 | 请求本地测试服务/api/profile | 抓包、参数篡改、重放 |
| 请求签名 | 客户端生成timestamp + nonce + hmac | 静态定位签名函数、动态打印明文 |
| Native 方法 | nativeCheck()返回环境检测结果 | JNI 定位、Native Hook |
| Root/代理检测 | 简单检测su、代理端口 | 绕过检测与防护复测 |
| 防护开关 | release 开启混淆、签名校验 | 对比加固前后分析成本 |
4.2 Kotlin 示例:本地会员判断
packagecom.example.reversedemoobjectUserCenter{privateconstvalLOCAL_USER="demo"privateconstvalLOCAL_PASSWORD="123456"funlogin(user:String,password:String):Boolean{returnuser==LOCAL_USER&&password==LOCAL_PASSWORD}funisVip(userId:String):Boolean{returnuserId=="10001"}funfeatureName():String{returnif(isVip("10002"))"vip-video"else"free-video"}}这个 Demo 故意把账号、密码和会员判断放在客户端。后续章节会证明:只要关键权益依赖客户端判断,就可以被静态修改或动态 Hook 影响。
4.3 Kotlin 示例:网络签名函数
objectSigner{privateconstvalCLIENT_SECRET="demo-client-secret-change-me"funsign(path:String,timestamp:String,nonce:String,body:String):String{valraw="$path|$timestamp|$nonce|$body|$CLIENT_SECRET"returnsha256(raw)}privatefunsha256(value:String):String{valdigest=java.security.MessageDigest.getInstance("SHA-256")returndigest.digest(value.toByteArray()).joinToString(""){"%02x".format(it)}}}这个写法也故意不安全:只要密钥在客户端,就可能被静态搜索、动态打印或从内存里定位。真正的核心鉴权应由服务端掌握,客户端只能持有短期凭证。
4.4 Native 示例:JNI 检测
#include<jni.h>#include<unistd.h>extern"C"JNIEXPORT jboolean JNICALLJava_com_example_reversedemo_NativeGuard_nativeCheck(JNIEnv*,jobject){returnaccess("/system/bin/su",F_OK)!=0;}这个 Native 方法用于练习:
- 用 jadx 找到
System.loadLibrary。 - 用
readelf、nm或 Ghidra 找 JNI 函数。 - 用 Frida Hook Java 层或 Native 层返回值。
- 把检测结果从“可绕过”改造成“只作为风险信号,不作为唯一安全判断”。
5. Demo 构建与运行
5.1 Debug 包
./gradlew assembleDebug adbinstall-rapp/build/outputs/apk/debug/app-debug.apk adb shell am start-ncom.example.reversedemo/.MainActivity adb logcat|grepReverseDemoDebug 包适合学习调试,但不代表真实防护状态。它通常包含调试符号、日志、未混淆类名,攻击成本很低。
5.2 Release 包
./gradlew assembleRelease apksigner verify--verboseapp/build/outputs/apk/release/app-release.apk adbinstall-rapp/build/outputs/apk/release/app-release.apkRelease 包要重点检查:
- 是否关闭
debuggable。 - 是否启用 R8/ProGuard 混淆。
- 是否删除敏感日志。
- 是否启用签名校验和完整性校验。
- 是否启用 Network Security Config。
6. 本章 Demo:环境验收实验
6.1 实验任务
- 编译并安装
ReverseDemodebug 包。 - 用
adb shell dumpsys package记录包名、版本、Activity 和签名摘要。 - 用 jadx 打开 APK,找到
UserCenter.isVip()。 - 用 apktool 反编译 APK,找到 Manifest 和 Smali 目录。
- 用 Burp/mitmproxy 抓到 Demo 的一次接口请求。
- 用
frida-ps -Uai确认能看到 Demo 进程。
6.2 验证表
| 步骤 | 命令或工具 | 通过标准 | 证据文件 |
|---|---|---|---|
| 安装 APK | adb install -r app-debug.apk | 显示Success | 01-install.txt |
| 查看包信息 | adb shell dumpsys package | 能看到 Activity 和签名 | 02-package.txt |
| 静态查看 | jadx-gui | 能定位isVip() | 03-jadx-screenshot.png |
| 资源反编译 | apktool | 生成AndroidManifest.xml和smali/ | 04-apktool-log.txt |
| 抓包 | Burp/mitmproxy | 能看到 Demo 请求 | 05-http-sample.txt |
| Frida 枚举 | frida-ps -Uai | 能看到进程 | 06-frida-list.txt |
6.3 常见问题
| 问题 | 原因 | 处理 |
|---|---|---|
adb devices显示 unauthorized | 设备未授权电脑 | 手机弹窗允许 USB 调试 |
INSTALL_FAILED_UPDATE_INCOMPATIBLE | 已安装不同签名包 | 卸载旧包后重装测试包 |
| jadx 打不开 APK | APK 损坏或路径含特殊字符 | 换短路径,先用unzip -t检查 |
| apktool 重打包失败 | 资源解码异常或版本旧 | 升级 apktool,保留错误日志 |
| Frida 连接失败 | server 架构或版本不一致 | 按 ABI 下载同版本 server |
| HTTPS 看不到明文 | App 启用证书绑定或未信任用户证书 | 本章只记录现象,后续章节专门处理 |
7. 本章交付物
完成本章后,建议产出:
case-reversedemo/ 01-env/ 01-install.txt 02-package.txt 03-jadx-screenshot.png 04-apktool-log.txt 05-http-sample.txt 06-frida-list.txt case-notes.mdcase-notes.md至少包含:实验环境、工具版本、APK 信息、已完成步骤、未完成原因、下一步计划。
8. Android 运行模型
8.1 从源码到 APK 的完整链路
Android 逆向要先理解“源码不是 APK 的最终形态”。一个普通 Kotlin/Java 项目从源码到安装包大致经历:
| 阶段 | 输入 | 输出 | 逆向关注点 |
|---|---|---|---|
| Kotlin/Java 编译 | .kt、.java | .class | 语法糖会被展开,例如 Kotlinobject、默认参数、协程状态机 |
| DEX 转换 | .class | classes.dex | 方法数、字符串池、类结构、调用引用 |
| 资源编译 | res/、AndroidManifest.xml | resources.arsc、二进制 XML | 资源 ID、组件声明、字符串 |
| Native 编译 | C/C++ | .so | JNI、符号、导入函数、架构 ABI |
| 打包 | DEX、资源、so、assets | 未签名 APK | 目录结构、压缩内容 |
| 签名 | 未签名 APK、证书 | 可安装 APK | V1/V2/V3/V4 签名、证书摘要 |
| 安装 | APK | /data/app/...、应用沙箱 | 包名、UID、私有目录、权限 |
学习时要把 jadx、apktool、adb、Frida 分别放在这条链路里理解。jadx 更接近 DEX 反编译,apktool 更接近资源和 Smali,adb 更接近运行环境,Frida 更接近运行时行为。
8.2 Android 进程和沙箱
每个 Android App 默认运行在自己的 Linux UID 下。这个 UID 决定了它能访问哪些文件、能否读写其他应用目录、能否通过 Binder 调用系统服务。
| 概念 | 解释 | 实操观察 |
|---|---|---|
| UID | 应用安装后分配的 Linux 用户 ID | `adb shell dumpsys package |
| 私有目录 | /data/data/<pkg>或/data/user/0/<pkg> | debug 包可尝试run-as <pkg> |
| 进程名 | 默认是包名,也可为组件单独配置进程 | `adb shell ps -A |
| 权限 | Manifest 申请,运行时授权 | adb shell dumpsys package <pkg> |
| SELinux | 限制系统资源访问 | adb shell getenforce |
逆向时常见误判是:在 root 设备上能看到的文件,不代表普通设备也能看到;debug 包能run-as,不代表 release 包也能。
8.3 Activity、Service、Receiver、Provider 的逆向意义
| 组件 | 正常用途 | 逆向分析点 | Demo 设计 |
|---|---|---|---|
| Activity | 页面展示和交互 | 是否可被外部启动、是否绕过登录态 | DebugPanelActivity |
| Service | 后台任务、长连接、播放、同步 | 是否导出、是否接受外部 Intent | SyncService |
| BroadcastReceiver | 接收系统或应用广播 | 是否可被伪造广播触发 | DebugReceiver |
| ContentProvider | 跨进程数据访问 | 是否暴露敏感数据 | DemoProvider |
Demo 中可以故意放一个导出 Activity,再在后续章节验证:外部命令能否直接启动,页面是否校验登录态。
adb shell am start-ncom.example.reversedemo/.DebugPanelActivity adb shell am broadcast-acom.example.reversedemo.DEBUG_ACTION adb shell content query--uricontent://com.example.reversedemo.provider/user8.4 Intent 与 Deep Link
Deep Link 风险不是“能打开页面”本身,而是打开后是否能执行敏感操作。
<activityandroid:name=".DeepLinkActivity"android:exported="true"><intent-filter><actionandroid:name="android.intent.action.VIEW"/><categoryandroid:name="android.intent.category.DEFAULT"/><categoryandroid:name="android.intent.category.BROWSABLE"/><dataandroid:scheme="reversedemo"android:host="open"/></intent-filter></activity>验证命令:
adb shell am start-aandroid.intent.action.VIEW-d"reversedemo://open/vip?userId=10002"检查点:
- 页面是否要求登录。
- 参数是否做白名单校验。
- 是否允许跳转到任意 URL。
- 是否触发支付、提现、绑定账号等敏感动作。
- 错误参数是否导致崩溃或信息泄露。
9. Demo 工程细化
9.1 推荐 Demo 模块划分
ReverseDemo/ app/ src/main/java/com/example/reversedemo/ MainActivity.kt LoginActivity.kt DebugPanelActivity.kt UserCenter.kt Signer.kt ApiClient.kt NativeGuard.kt RiskDetector.kt StorageLab.kt src/main/cpp/ native_guard.cpp src/main/res/xml/ network_security_config.xml每个类负责一个学习主题:
| 文件 | 学习主题 | 后续章节对应 |
|---|---|---|
UserCenter.kt | 登录和会员判断 | 静态分析、Smali、Frida |
Signer.kt | 请求签名和硬编码密钥 | jadx 搜索、Hook 参数 |
ApiClient.kt | OkHttp/Retrofit 请求 | 抓包、重放、篡改 |
NativeGuard.kt | JNI 声明 | Native 分析 |
RiskDetector.kt | root、debug、proxy 检测 | Hook 和防护复测 |
StorageLab.kt | SharedPreferences、SQLite、文件 | 本地数据风险 |
9.2 Demo 风险开关设计
为了方便对比,可以把风险点做成可切换模式:
objectLabSwitch{constvalUSE_LOCAL_VIP_CHECK=trueconstvalUSE_CLIENT_SIDE_SECRET=trueconstvalPRINT_SENSITIVE_LOG=trueconstvalENABLE_EXPORTED_DEBUG_PAGE=trueconstvalENABLE_NATIVE_ROOT_CHECK=true}实验方式:
| 开关 | 打开时验证 | 关闭或修复后复测 |
|---|---|---|
USE_LOCAL_VIP_CHECK | Hook/Smali 可影响会员页 | 服务端接口拒绝核心权益 |
USE_CLIENT_SIDE_SECRET | jadx/Frida 能定位签名材料 | 服务端不再依赖客户端长期密钥 |
PRINT_SENSITIVE_LOG | logcat 可看到敏感字段 | release 无敏感日志 |
ENABLE_EXPORTED_DEBUG_PAGE | adb 可直接启动 | 导出关闭或入口鉴权 |
ENABLE_NATIVE_ROOT_CHECK | Native 方法可被 Hook | 检测仅作为风险信号 |
9.3 Demo 后端最小设计
即使是 Android 逆向学习,也建议准备一个最小后端。否则只能验证客户端现象,不能证明服务端是否安全。
接口建议:
| 接口 | 用途 | 风险验证 |
|---|---|---|
POST /login | 返回测试 token | token 存储、日志泄露 |
GET /profile | 查询用户资料 | 越权访问 |
POST /vip/resource | 访问会员资源 | 本地会员判断是否影响服务端 |
POST /order/pay | 模拟下单支付 | 金额篡改、订单归属 |
POST /risk/report | 上报环境检测结果 | 风险信号设计 |
服务端最小校验:
- token 必须有效。
userId由 token 推导,不能信任客户端传入。- 签名必须覆盖 path、method、timestamp、nonce、body hash。
- nonce 只能使用一次。
- 高风险操作需要服务端二次校验。
10. 工具验证深水区
10.1 adb 深入命令
| 任务 | 命令 | 用途 |
|---|---|---|
| 查看安装路径 | adb shell pm path com.example.reversedemo | 定位 base.apk |
| 拉取 APK | adb pull /data/app/.../base.apk | 分析已安装包 |
| 查看应用 UID | `adb shell dumpsys package | grep userId` |
| 查看权限 | `adb shell dumpsys package | grep permission -n` |
| 启动 Activity | adb shell am start -n <pkg>/<activity> | 验证导出页面 |
| 发送广播 | adb shell am broadcast -a <action> | 验证 Receiver |
| 查看崩溃 | adb logcat -b crash | 定位异常 |
| 查看网络代理 | adb shell settings get global http_proxy | 抓包排错 |
| 清除数据 | adb shell pm clear <pkg> | 复现实验初始状态 |
| 卸载应用 | adb uninstall <pkg> | 解决签名冲突 |
10.2 jadx 使用细节
| 操作 | 目的 | 注意 |
|---|---|---|
| 全局搜索字符串 | 找 URL、密钥、错误文案 | 混淆后字符串仍常保留 |
| 搜索方法名 | 找业务入口 | 混淆后方法名可能不可用 |
| 查看调用者 | 建立调用链 | 反射和动态加载可能断链 |
| 导出 Gradle 项目 | 方便全文搜索 | 不能当源码直接运行 |
| 对比 debug/release | 看混淆和日志差异 | release 更接近真实环境 |
10.3 apktool 使用细节
apktool d-fapp-debug.apk-odecoded-debug apktool b decoded-debug-orebuilt.apk常见参数:
| 参数 | 用途 |
|---|---|
-f | 覆盖输出目录 |
-o | 指定输出目录或文件 |
--use-aapt2 | 使用 aapt2 构建资源 |
--no-res | 不反编译资源,适合资源异常时 |
--no-src | 不反编译 Smali,只看资源 |
apktool 成功反编译不代表能成功重打包。资源异常、签名差异、版本差异都可能影响安装。
10.4 Frida 环境排错清单
| 现象 | 排查方向 | 处理 |
|---|---|---|
unable to connect | USB、frida-server 未运行 | 检查adb devices和 server |
protocol error | 电脑端和设备端版本不一致 | 下载同版本 frida-server |
permission denied | server 无执行权限 | chmod 755 |
| 只看到系统进程 | 权限或设备连接异常 | 用 root 环境或调试设备 |
| spawn 后黑屏 | Hook 脚本异常阻塞 | 先注释修改逻辑,只打印 |
| 类找不到 | 类未加载或包名错误 | 先触发页面或枚举 ClassLoader |
11. 实验记录规范
11.1 每次实验必须记录的字段
# 实验记录 ## 基本信息 - 实验名称: - 实验日期: - 操作人: - App 包名: - App 版本: - APK 哈希: - 设备型号: - Android 版本: - 是否 root: ## 工具版本 | 工具 | 版本 | 用途 | ## 操作步骤 1. 2. 3. ## 证据 | 证据 | 文件 | 说明 | ## 结论 - 已验证: - 未验证: - 限制: - 下一步:11.2 APK 哈希记录
shasum-a256app-debug.apk shasum-a256app-release.apk为什么要记录哈希:
- 保证报告和样本对应。
- 避免 debug/release 混用。
- 复测时确认是否同一版本。
- 多人协作时减少证据争议。
11.3 证据命名规范
| 类型 | 命名示例 |
|---|---|
| 命令输出 | 01-adb-devices.txt |
| 截图 | 02-jadx-isvip.png |
| Hook 脚本 | 03-hook-isvip.js |
| Hook 日志 | 04-hook-isvip.log |
| 抓包样本 | 05-profile-request.http |
| 修改前代码 | 06-before.smali |
| 修改后代码 | 07-after.smali |
| 复测矩阵 | 08-retest-matrix.md |
12. 阶段练习
12.1 入门练习
| 练习 | 操作 | 通过标准 |
|---|---|---|
| APK 解压 | unzip -l app.apk | 能解释主要目录 |
| 包名识别 | apkanalyzer或 Manifest | 能写出包名和版本 |
| 设备安装 | adb install | App 可启动 |
| 日志查看 | adb logcat | 能过滤 Demo 日志 |
| jadx 查看 | 打开 APK | 能定位MainActivity |
12.2 进阶练习
| 练习 | 操作 | 通过标准 |
|---|---|---|
| 导出组件验证 | adb shell am start | 能证明是否可外部启动 |
| 本地存储查看 | debug 包run-as | 能找到测试数据 |
| 网络代理配置 | Burp/mitmproxy | 能抓到 Demo 请求 |
| Frida 枚举 | frida-ps -Uai | 能看到 Demo 进程 |
| Native 提取 | unzip -p | 能提取目标 ABI so |
12.3 专项练习
| 主题 | 任务 | 输出 |
|---|---|---|
| Manifest | 列出所有组件和导出状态 | manifest-audit.md |
| DEX | 找登录、会员、签名方法 | dex-map.md |
| 网络 | 抓 3 个关键接口 | api-flow.md |
| Native | 找nativeCheck | jni-map.md |
| 防护 | 对比 debug 和 release | build-compare.md |
13. 验收考试
最终验收要求:
- 在本机完成 Demo 编译和安装。
- 用不少于 8 条 adb 命令完成设备、包、组件、日志、代理检查。
- 用 jadx 定位 3 个关键类:登录、签名、Native 声明。
- 用 apktool 反编译并找到 Manifest 和 Smali。
- 用 Frida 完成进程枚举。
- 用 Burp/mitmproxy 完成至少一次授权 Demo 抓包。
- 输出完整
case-notes.md。
评分表:
| 项目 | 分值 | 扣分点 |
|---|---|---|
| 环境可用 | 20 | 工具版本未记录、设备不可连接 |
| Demo 可运行 | 20 | debug/release 混淆、包名不清 |
| 工具验证 | 20 | jadx/apktool/Frida/Burp 任一缺证据 |
| 记录规范 | 20 | 没有命令输出和截图 |
| 安全边界 | 20 | 未写授权范围或使用真实敏感数据 |
14. 基础、环境与 Demo 工程
本节补充真正的知识点说明。每个知识点都包含需要理解的核心、Demo 中的验证方式和常见误区。
Android 应用基础
| 知识点 | 核心理解 | Demo/验证 | 常见误区 |
|---|---|---|---|
| APK 文件结构 | APK 是带签名的压缩包,核心由 Manifest、DEX、资源、Native 库、assets 和签名信息组成。 | 解压ReverseDemo,标注AndroidManifest.xml、classes.dex、lib/arm64-v8a/libreversedemo.so。 | 只看 jadx 代码,忽略 Manifest、资源和 so。 |
| DEX 字节码 | Java/Kotlin 最终会进入 DEX,ART 执行的是 DEX 而不是源码。 | 在 jadx 中对比 Kotlinobject和反编译后的类结构。 | 把反编译代码当作原始源码逐行理解。 |
| Kotlin 编译痕迹 | 空安全、伴生对象、默认参数、协程会生成额外类和辅助方法。 | 搜索Intrinsics、Companion、DefaultImpls。 | 看到代码复杂就误以为有安全防护。 |
| 应用 UID | Android 用 Linux UID 隔离应用,私有目录权限由 UID 控制。 | 用dumpsys package查看userId,debug 包尝试run-as。 | 把 root 设备能读到的数据当作普通设备也可读。 |
| 四大组件 | Activity、Service、Receiver、Provider 是外部入口和业务承载点。 | 分别用am start、am broadcast、content query验证 Demo 入口。 | 只测试页面,不测试后台组件和 Provider。 |
| Intent 参数 | Intent 的 extras、data、action 都可能由外部构造,不能默认可信。 | 构造 Deep Link 参数打开会员页。 | 把客户端传入的userId当作服务端可信身份。 |
| 签名机制 | 签名证明 APK 来源和升级一致性,不加密代码。 | 用apksigner verify --print-certs查看证书摘要。 | 认为 APK 签名能阻止反编译。 |
| Debug 与 Release | debug 包偏调试,release 包才接近真实上线状态。 | 分别构建两个包并用 jadx 对比混淆、日志和 Manifest。 | 只分析 debug 包后直接给出正式安全结论。 |
工具与环境
| 知识点 | 核心理解 | Demo/验证 | 常见误区 |
|---|---|---|---|
| adb 设备通道 | adb 提供安装、shell、日志、组件触发和数据清理能力。 | 完成adb devices、install、logcat、am start。 | 把 adb 能触发当作漏洞结论,不看触发后的业务影响。 |
| jadx 角色 | jadx 适合读 DEX 近似源码和调用关系。 | 定位UserCenter.isVip()、Signer.sign()。 | 认为 jadx 看不到就代表不存在。 |
| apktool 角色 | apktool 适合资源、Manifest、Smali 和重打包验证。 | 反编译 Demo 并找到 Smali 目录。 | 用 apktool 输出的资源名直接推断业务风险。 |
| apksigner 角色 | apksigner 验证签名方案、证书和重签名结果。 | 对原包和重签名包分别验证。 | 只要能重签名就认为完整性防护失效,还需结合服务端。 |
| Frida 前置条件 | Frida 需要设备连接、server 版本、目标进程和注入时机匹配。 | 用frida-ps -Uai枚举 Demo。 | Hook 成功就直接判业务高危。 |
| Burp/mitmproxy | 抓包工具用于观察和篡改授权测试流量。 | 抓 Demo 的/api/profile请求。 | 抓不到包就认为接口一定安全。 |
| Ghidra 角色 | Ghidra 用于 so 反汇编、字符串引用、函数重命名和控制流理解。 | 导入libreversedemo.so并搜索nativeCheck。 | 只看 Java external 方法,不分析 so。 |
| 工具版本记录 | 逆向结果和工具版本强相关,报告必须记录版本。 | 输出tool-version.md。 | 不记录版本导致复现困难。 |
Demo 工程设计
| 知识点 | 核心理解 | Demo/验证 | 常见误区 |
|---|---|---|---|
| 可控授权样本 | 学习逆向必须使用自建 Demo、开源靶场或授权测试包。 | 在ReverseDemo中内置测试账号和测试接口。 | 用第三方未授权 App 练习。 |
| 本地会员判断 | 客户端布尔值可被 Smali 或 Hook 影响。 | 设计UserCenter.isVip()。 | 把本地判断当作核心权益保护。 |
| 请求签名函数 | 签名函数用于学习参数覆盖范围和密钥边界。 | 设计Signer.sign(path,timestamp,nonce,body)。 | 认为客户端签名必然安全。 |
| 测试后端 | 没有后端就无法验证核心业务是否真的越权。 | 提供/login、/profile、/vip/resource。 | 只看客户端 UI 变化,不测接口结果。 |
| Native 检测点 | Native 适合学习 JNI 和环境检测,但不是绝对安全。 | 设计NativeGuard.nativeCheck()。 | 把逻辑放进 so 就认为不可分析。 |
| 证据目录 | 证据必须按阶段归档,便于复现和交付。 | 建立01-env、02-static、03-dynamic。 | 截图和命令输出散落,最后无法写报告。 |
使用方式
每个知识点都要落到三件事:能解释原理,能在ReverseDemo或授权样本里找到证据,能写出验证结果和修复边界。
