网络安全Kali学习系列 · 第54篇

APK 逆向:jadx 与 apktool

Android 应用结构 · 反编译 · 代码审计 · 重打包
📋 本篇导读
  • APK 文件结构与 AndroidManifest.xml 解析
  • jadx 图形化反编译与代码审计
  • apktool 解包、修改与重打包签名
  • 常见加固方案与脱壳思路
  • 实战:从 APK 中提取硬编码密钥与 API

一、APK 文件结构

APK 本质上是一个 ZIP 压缩包。理解其内部结构是逆向分析的第一步。

1.1 APK 内部结构

Text · APK 目录结构
1
2
3
4
5
6
7
8
9
10
12
12
# APK 内部结构(本质上是一个 ZIP)
app.apk
├── AndroidManifest.xml # 应用清单(二进制XML)
├── classes.dex # Dalvik 字节码(主程序)
├── classes2.dex # 多 dex 分包(大型 App)
├── resources.arsc # 编译后的资源索引
├── res/ # 资源文件(图片/布局等)
├── assets/ # 原始资源(不编译)
├── lib/ # native 库(.so 文件)
│ ├── arm64-v8a/ # 64 位 ARM
│ ├── armeabi-v7a/ # 32 位 ARM
│ └── x86_64/ # x86 64 位

1.2 核心文件说明

文件 格式 说明
AndroidManifest.xml 二进制 XML 应用清单:包名、权限、组件声明
classes.dex Dalvik 字节码 Java 代码编译后的可执行文件
resources.arsc 二进制资源表 资源 ID 到值的映射
res/ 编译后 XML 布局、字符串、图片等
lib/*.so ELF 共享库 C/C++ 编译的 native 代码
META-INF/ 签名文件 CERT.RSA/CERT.SF/MANIFEST.MF

二、工具概览

工具 功能 优势
jadx DEX → Java 反编译 GUI 界面,代码搜索,交叉引用
apktool APK 解包/重打包 资源解码、smali 编辑、回编译
dex2jar DEX → JAR 转换 配合 JD-GUI 查看代码
frida 动态 Hook 运行时修改(下篇详解)
objection frida 封装 一键绕过 SSL Pinning 等

三、jadx 实战

jadx 是最好的 DEX 反编译工具之一,能将 Dalvik 字节码还原为可读的 Java 代码。

3.1 安装与启动

Bash · jadx 安装
1
2
3
4
5
6
7
8
9
# 方式一:Kali apt 安装
sudo apt install jadx
# 方式二:从 GitHub 下载最新版
wget https://github.com/skylot/jadx/releases/download/v1.5.0/jadx-1.5.0.zip
unzip jadx-1.5.0.zip -d ~/jadx
# GUI 启动
~/jadx/bin/jadx-gui target.apk

3.2 命令行模式

Bash · jadx CLI 用法
1
2
3
4
5
6
7
8
9
10
11
# 反编译为 Java 源码(输出到目录)
jadx -d output/ target.apk
# 显示反编译进度
jadx -d output/ target.apk --show-bad-code
# 导出 Gradle 工程(可直接用 Android Studio 打开)
jadx -d output/ target.apk -e
# 仅提取资源
jadx -d output/ target.apk -r

3.3 GUI 审计技巧

jadx-gui 常用快捷键与功能:
快捷键 功能
Ctrl+Shift+F 全局搜索(搜索字符串/类名/方法名)
Ctrl+左键 跳转到定义(类/方法/变量)
Ctrl+右键 查找使用(交叉引用,谁调用了这个方法)
Alt+H 调用层级分析
F4 搜索结果导航

3.4 审计搜索关键词

Text · jadx 全局搜索关键词
1
2
3
4
5
6
7
8
9
10
# 在 jadx-gui 中 Ctrl+Shift+F 搜索以下关键词:
# API 密钥与 Token
"api_key" "apikey" "API_KEY" "secret" "token" "Bearer"
# URL 与端点
"http://" "https://" "http://10." "http://192.168."
# 加密相关
"Cipher" "AES" "RSA" "MD5" "SHA" "encrypt" "decrypt"

四、apktool 实战

apktool 用于解包 APK、修改资源与 smali 代码、重打包并签名。是修改 APK 的核心工具。

4.1 基本用法

Bash · apktool 命令
1
2
3
4
5
6
7
8
9
10
11
# 1. 解包 APK(反编译资源和 smali)
apktool d target.apk -o output_dir
# 2. 仅解码资源(不解码 dex)
apktool d target.apk -r -o output_dir
6
# 3. 仅解码 dex(不解码资源)
apktool d target.apk -s -o output_dir
# 4. 重打包
apktool b output_dir -o modified.apk

4.2 解包后的目录结构

Text · apktool 解包结构
1
2
3
4
5
6
7
8
output_dir/
├── AndroidManifest.xml # 可读 XML 格式
├── apktool.yml # apktool 元数据
├── res/ # 解码后的资源
├── smali/ # 反编译的 Dalvik 汇编
├── smali_classes2/ # 第二个 dex 的 smali
├── assets/ # 原始资源
└── lib/ # native 库

4.3 重打包与签名

Bash · 重打包与签名流程
1
2
3
4
5
6
7
8
9
10
11
12
# Step 1: 重打包
apktool b output_dir -o modified.apk
# Step 2: 生成签名密钥(首次需要)
keytool -genkey -alias mykey -keyalg RSA
-keysize 2048 -validity 10000 -keystore my.keystore
# Step 3: 对齐(可选,Android 12+ 要求)
zipalign -v 4 modified.apk aligned.apk
# Step 4: 签名
apksigner sign --ks my.keystore --out signed.apk aligned.apk

五、AndroidManifest.xml 审计

AndroidManifest.xml 是 APK 最核心的配置文件,包含权限声明、组件定义、导出配置等关键安全信息。

5.1 审计要点

审计项 风险 检查方法
android:debuggable true 时可被调试附加 检查 application 标签
android:exported Activity/Service/Receiver 无需权限可被调用 检查组件 exported=true
android:allowBackup true 时数据可被 adb backup 导出 检查 application 标签
android:networkSecurityConfig 未配置时默认不信任用户证书 检查是否存在网络安全配置
过度权限 申请了超出功能需要的权限 审查 uses-permission 列表
明文流量 usesCleartextTraffic=true 检查 application 标签

5.2 Manifest 示例

XML · AndroidManifest.xml 审计示例
1
2
3
4
5
6
7
8
9
10
android:allowBackup="true"
android:usesCleartextTraffic="true">
android:exported="true"/>
⚠️ 风险清单
debuggable=true 可被调试 | allowBackup=true 数据可导出 | usesCleartextTraffic=true 允许明文 HTTP | READ_SMS 权限过度申请 | exported=true 组件可被外部调用

六、加固与脱壳

商业 App 通常使用加固保护代码,使直接反编译无法获取真实逻辑。

6.1 常见加固方案

加固厂商 特征 识别方法
360 加固 Dex 加密 + SO 壳 libjiagu.so
腾讯乐固 Dex 加密 + VMP libshell.so / libshellaide.so
梆梆安全 Dex 加密 + 反调试 libsecmain.so
爱加密 Dex 加密 + SO 壳 libexec.so
Google Play Play App Signing 非加固,签名保护

6.2 脱壳思路

Frida DEX Dump:运行时从内存中 dump 解密后的 DEX 文件。工具:frida-dexdump
FART:Frida Active Response Tool,主动调用 dexClass 加载并 dump
BlackDex:黑名单脱壳工具,支持多种加固方案
Youpk:基于 ART 运行时的脱壳方案
核心原理:加固壳在运行时必须将真实 DEX 解密到内存中才能执行。在合适的时机 dump 内存即可获得原始 DEX。

6.3 frida-dexdump 实操

Bash · frida-dexdump 使用
1
2
3
4
5
6
# 安装
pip install frida-dexdump
# 使用(需要 frida-server 已在设备上运行)
frida-dexdump -U -f com.example.app
# dump 的 DEX 文件会保存到当前目录

七、实战:提取硬编码密钥

以下演示从 APK 中提取硬编码的 API 密钥和加密密钥的完整流程。

Bash · 完整提取流程
1
2
3
4
5
6
7
8
9
10
12
13
14
15
15
# Step 1: 用 jadx 反编译
jadx -d output/ target.apk
# Step 2: 全局搜索硬编码密钥
grep -rn "api_key\|apikey\|API_KEY" output/sources/
grep -rn "secret\|token\|Bearer" output/sources/
# Step 3: 搜索硬编码 URL
grep -rn "http://\|https://" output/sources/ | grep -v "schemas.android"
# Step 4: 搜索加密密钥
grep -rn "AES\|DES\|RSA\|encrypt\|decrypt" output/sources/
# Step 5: 检查 assets 目录
find output/assets -type f | head -20

八、smali 修改示例

apktool 解包后生成 smali 代码,修改 smali 可以改变应用逻辑。以下是一个绕过登录检查的示例。

Smali · 绕过登录检查示例
1
2
3
4
5
6
7
8
9
10
12
12
# 原始 smali(检查登录状态)
.method public checkLogin()Z
.locals 1
iget-boolean v0, p0, Lcom/example/LoginActivity;->isLoggedIn:Z
return v0
.end method
# 修改后(始终返回 true)
.method public checkLogin()Z
.locals 1
const/4 v0, 0x1 # 直接返回 true
return v0
💡 smali 语法速记
const/4 v0, 0x1 = 将 1 赋给寄存器 v0(true) | const/4 v0, 0x0 = 0(false) | return v0 = 返回 v0 的值

九、小结

🔑 本篇要点
  • APK 本质是 ZIP,核心文件:AndroidManifest.xml / classes.dex / resources.arsc / lib/*.so
  • jadx 用于反编译 DEX → Java,GUI 支持搜索、交叉引用、调用层级分析
  • apktool 用于解包/修改/重打包,生成可读 AndroidManifest.xml 和 smali 代码
  • 重打包流程:apktool b → zipalign → apksigner sign
  • AndroidManifest.xml 审计:debuggable / exported / allowBackup / usesCleartextTraffic / 过度权限
  • 常见加固方案:360 加固、腾讯乐固、梆梆安全,通过 SO 库特征识别
  • 脱壳原理:运行时 dump 内存中解密的 DEX,工具:frida-dexdump / FART / BlackDex
下一篇预告
第 55 篇:Frida 动态调试与 SSL Pinning 绕过
运行时 Hook、绕过证书绑定、抓包 HTTPS
网络安全Kali学习系列 · 第54篇 · APK逆向:jadx与apktool