jadx - Android APK反编译器
您正在使用jadx反编译Android APK文件,将DEX字节码转换为可读的Java源代码,以便进行安全分析、漏洞发现和通过可读源代码理解应用程序内部结构。
工具概述
Jadx是一个将DEX转换为Java的反编译器,它从Android APK文件生成干净、可读的Java源代码。与apktool(生成smali)不同,jadx生成的是实际的Java代码,更易于阅读和分析。它对于以下方面至关重要:
- 将DEX字节码转换为可读的Java源码
- 理解应用程序逻辑和控制流程
- 在代码中寻找安全漏洞
- 发现硬编码的凭证、API密钥、URL
- 分析加密/认证实现
- 使用熟悉的Java语法搜索代码
先决条件
- jadx(以及可选的jadx-gui)必须安装
- 需要Java运行时环境(JRE)
- 足够的磁盘空间(反编译输出通常是APK大小的3-10倍)
- 输出目录的写权限
GUI与CLI
Jadx提供了两种界面:
CLI (jadx):命令行界面
- 最适合自动化和脚本编写
- 批量处理多个APK
- 与其他工具集成
- 无头服务器环境
GUI (jadx-gui):图形界面
- 交互式代码浏览
- 内置搜索功能
- 交叉引用和导航
- 更适合手动分析
- 语法高亮
何时使用:
- 使用CLI进行自动化分析、脚本编写、CI/CD流水线
- 使用GUI进行交互式探索和深入分析
指令
1. 基本APK反编译(最常见)
标准反编译命令:
jadx <apk文件> -d <输出目录>
示例:
jadx app.apk -d app-decompiled
带反混淆(对于混淆的应用程序推荐):
jadx --deobf app.apk -d app-decompiled
2. 理解输出结构
反编译后,输出目录包含:
app-decompiled/
├── sources/ # Java源代码
│ └── com/company/app/ # 包结构
│ ├── MainActivity.java
│ ├── utils/
│ ├── network/
│ └── ...
└── resources/ # 解码资源
├── AndroidManifest.xml # 可读清单
├── res/ # 资源
│ ├── layout/ # XML布局
│ ├── values/ # 字符串、颜色
│ ├── drawable/ # 图像
│ └── ...
└── assets/ # 应用程序资产
3. 反编译选项
A. 性能选项
多线程反编译(更快):
jadx -j 4 app.apk -d output
# -j指定线程数(默认:CPU核心数)
跳过资源(仅代码,更快):
jadx --no-res app.apk -d output
跳过源代码(仅资源):
jadx --no-src app.apk -d output
B. 反混淆选项
启用反混淆:
jadx --deobf app.apk -d output
- 重命名混淆的类(a.b.c → 有意义的名称)
- 尝试恢复原始名称
- 使代码更易于阅读
- 对于混淆/压缩的应用程序至关重要
反混淆映射输出:
jadx --deobf --deobf-rewrite-cfg --deobf-use-sourcename app.apk -d output
- 更积极的反混淆
- 使用源文件名作为提示
- 重写控制流图
C. 输出控制
显示不一致/糟糕的代码:
jadx --show-bad-code app.apk -d output
- 显示无法干净反编译的代码
- 对于发现混淆或反编译技巧很有用
- 可能包含语法错误,但揭示结构
导出为Gradle项目:
jadx --export-gradle app.apk -d output
- 创建可构建的Gradle Android项目
- 对于重建/修改应用程序很有用
- 包括build.gradle文件
后备模式(当反编译失败时):
jadx --fallback app.apk -d output
- 使用替代反编译策略
- 产生的代码不够干净,但可以处理边缘情况
4. 常见分析任务
A. 搜索敏感信息
反编译后,搜索常见安全问题:
# 搜索API密钥
grep -r "api.*key\|apikey\|API_KEY" app-decompiled/sources/
# 搜索密码和凭证
grep -r "password\|credential\|secret" app-decompiled/sources/
# 搜索硬编码的URL
grep -rE "https?://[^\"]+" app-decompiled/sources/
# 搜索加密密钥
grep -r "AES\|DES\|RSA\|encryption.*key" app-decompiled/sources/
# 搜索令牌
grep -r "token\|auth.*token\|bearer" app-decompiled/sources/
# 搜索数据库密码
grep -r "jdbc\|database\|db.*password" app-decompiled/sources/
B. 发现安全漏洞
SQL注入:
grep -r "SELECT.*FROM.*WHERE" app-decompiled/sources/ | grep -v "PreparedStatement"
grep -r "rawQuery\|execSQL" app-decompiled/sources/
不安全的加密:
grep -r "DES\|MD5\|SHA1" app-decompiled/sources/
grep -r "SecureRandom.*setSeed" app-decompiled/sources/
grep -r "Cipher.getInstance" app-decompiled/sources/ | grep -v "AES/GCM"
不安全的存储:
grep -r "SharedPreferences" app-decompiled/sources/
grep -r "MODE_WORLD_READABLE\|MODE_WORLD_WRITABLE" app-decompiled/sources/
grep -r "openFileOutput" app-decompiled/sources/
WebView漏洞:
grep -r "setJavaScriptEnabled.*true" app-decompiled/sources/
grep -r "addJavascriptInterface" app-decompiled/sources/
grep -r "WebView.*loadUrl" app-decompiled/sources/
证书固定绕过:
grep -r "TrustManager\|HostnameVerifier" app-decompiled/sources/
grep -r "checkServerTrusted" app-decompiled/sources/
C. 理解应用程序逻辑
查找入口点:
# 主活动
grep -r "extends Activity\|extends AppCompatActivity" app-decompiled/sources/
# 应用程序类
grep -r "extends Application" app-decompiled/sources/
# 服务
grep -r "extends Service" app-decompiled/sources/
# 广播接收器
grep -r "extends BroadcastReceiver" app-decompiled/sources/
追踪网络通信:
# 查找HTTP客户端使用情况
grep -r "HttpURLConnection\|OkHttpClient\|Retrofit" app-decompiled/sources/
# 查找API端点
grep -r "@GET\|@POST\|@PUT\|@DELETE" app-decompiled/sources/
# 查找基本URL
grep -r "baseUrl\|BASE_URL\|API_URL" app-decompiled/sources/
查找认证逻辑:
grep -r "login\|Login\|authenticate\|Authorization" app-decompiled/sources/
grep -r "jwt\|JWT\|bearer\|Bearer" app-decompiled/sources/
D. 分析特定类
确定感兴趣的类后,直接阅读它们:
# 查看特定类
cat app-decompiled/sources/com/example/app/LoginActivity.java
# 使用less进行分页
less app-decompiled/sources/com/example/app/network/ApiClient.java
# 在特定类中搜索
grep "password" app-decompiled/sources/com/example/app/LoginActivity.java
5. GUI模式(交互式分析)
启动GUI:
jadx-gui app.apk
GUI功能:
- 全文搜索:Ctrl+Shift+F(搜索所有代码)
- 查找用法:右键单击类/方法 → “查找用法”
- 跳转到声明:Ctrl+单击任何类/方法
- 反编译:单击任何类以查看Java代码
- 保存反编译代码:文件 → 保存所有
- 导出选项:文件 → 导出为Gradle项目
GUI工作流程:
- 使用jadx-gui打开APK
- 在左侧面板浏览包结构
- 使用搜索(Ctrl+Shift+F)查找关键词
- 单击结果以查看上下文代码
- 使用Ctrl+单击跟踪交叉引用
- 保存有趣的发现
6. 与其他工具集成
将Jadx与Apktool结合使用
两个工具互补:
Jadx优势:
- 可读的Java源代码
- 易于理解逻辑
- 快速搜索代码
Apktool优势:
- 准确的资源提取
- Smali代码(更接近原始)
- 可以重建/重新打包APK
推荐工作流程:
# 使用jadx进行代码分析
jadx --deobf app.apk -d app-jadx
# 使用apktool进行资源和smali
apktool d app.apk -o app-apktool
# 分析两个输出
grep -r "API_KEY" app-jadx/sources/
grep -r "api_key" app-apktool/res/
常见工作流程
工作流程1:安全评估
# 1. 带反混淆的反编译
jadx --deobf app.apk -d app-decompiled
# 2. 搜索硬编码的秘密
echo "[+] 搜索API密钥..."
grep -ri "api.*key\|apikey" app-decompiled/sources/ | tee findings-apikeys.txt
echo "[+] 搜索密码..."
grep -ri "password\|passwd\|pwd" app-decompiled/sources/ | tee findings-passwords.txt
echo "[+] 搜索URL..."
grep -rE "https?://[^\"]+" app-decompiled/sources/ | tee findings-urls.txt
# 3. 检查加密使用情况
echo "[+] 检查加密实现..."
grep -r "Cipher\|SecretKey\|KeyStore" app-decompiled/sources/ | tee findings-crypto.txt
# 4. 检查不安全的存储
echo "[+] 检查存储机制..."
grep -r "SharedPreferences\|SQLite\|openFileOutput" app-decompiled/sources/ | tee findings-storage.txt
# 5. 总结
echo "[+] 分析完成。检查findings-*.txt文件"
工作流程2:IoT应用分析
对于IoT伴侣应用程序,找到设备通信:
# 1. 反编译
jadx --deobf iot-app.apk -d iot-app-decompiled
# 2. 查找设备通信
echo "[+] 查找设备端点..."
grep -rE "https?://[^\"]+" iot-app-decompiled/sources/ | \
grep -v "google\|android\|facebook" | \
tee device-endpoints.txt
# 3. 查找API结构
echo "[+] 查找API定义..."
grep -r "@GET\|@POST\|@PUT" iot-app-decompiled/sources/ | tee api-endpoints.txt
# 4. 查找认证
echo "[+] 查找认证机制..."
grep -r "Authorization\|authentication\|apiKey" iot-app-decompiled/sources/ | tee auth-methods.txt
# 5. 查找设备发现
echo "[+] 查找设备发现..."
grep -r "discover\|scan\|broadcast\|mdns" iot-app-decompiled/sources/ | tee device-discovery.txt
# 6. 检查证书固定
echo "[+] 检查证书固定..."
grep -r "CertificatePinner\|TrustManager" iot-app-decompiled/sources/ | tee cert-pinning.txt
工作流程3:快速凭据检查
# 快速反编译,不包含资源
jadx --no-res --deobf app.apk -d app-code
# 搜索常见凭据模式
grep -r "username.*password\|user.*pass" app-code/sources/
grep -r "admin\|root\|default.*password" app-code/sources/
grep -r "hardcoded\|TODO.*password\|FIXME.*password" app-code/sources/
工作流程4:API端点发现
# 反编译
jadx app.apk -d app-decompiled
# 查找Retrofit/REST API定义
find app-decompiled/sources -name "*Api*.java" -o -name "*Service*.java" -o -name "*Client*.java"
# 提取所有端点
grep -r "@GET\|@POST\|@PUT\|@DELETE\|@PATCH" app-decompiled/sources/ | \
sed 's/.*@\(GET\|POST\|PUT\|DELETE\|PATCH\)("\([^"]*\)".*/\1 \2/' | \
sort -u
# 查找基本URL
grep -r "baseUrl\|BASE_URL\|API_BASE" app-decompiled/sources/
工作流程5:批量处理多个APK
# 反编译多个APK
for apk in *.apk; do
name=$(basename "$apk" .apk)
echo "[+] 处理$apk..."
jadx --no-res --deobf "$apk" -d "decompiled-$name"
# 快速搜索秘密
grep -r "api.*key\|password\|secret" "decompiled-$name/sources/" > "findings-$name.txt"
done
echo "[+] 所有APK处理完毕。检查findings-*.txt文件"
最佳实践
1. 生产应用程序始终使用反混淆
# 大多数生产应用程序都是混淆的
jadx --deobf app.apk -d output
没有--deobf,您将看到类似这样的代码:
public class a {
public void b(String c) { ... }
}
使用--deobf,jadx尝试有意义的名称:
public class NetworkClient {
public void sendRequest(String url) { ... }
}
2. 大型应用程序使用多线程
# 更快的反编译
jadx -j 8 large-app.apk -d output
3. 仅代码分析时跳过资源
# 3-5倍速度提升,当您只需要代码时
jadx --no-res app.apk -d output
4. 系统地搜索
创建搜索清单:
- [ ] API密钥和秘密
- [ ] 硬编码凭证
- [ ] URL和端点
- [ ] 加密实现
- [ ] 不安全存储
- [ ] WebView漏洞
- [ ] 调试/日志代码
- [ ] 注释掉的敏感代码
5. 深度分析使用GUI
对于复杂的应用程序:
- 使用CLI进行初始反编译
- 搜索有趣的模式
- 在GUI中打开进行详细探索
- 使用交叉引用跟踪代码流
6. 与运行时分析结合
静态分析(jadx)+动态分析:
- 使用jadx查找API端点
- 使用curl/burp测试端点
- 使用jadx理解认证流程
- 使用运行时插桩(Frida)测试认证
故障排除
问题:反编译失败并出现错误
解决方案:使用后备模式或显示糟糕的代码:
jadx --fallback --show-bad-code app.apk -d output
问题:代码不可读(混淆)
解决方案:启用反混淆:
jadx --deobf app.apk -d output
问题:内存溢出错误
解决方案:增加Java堆大小:
export JAVA_OPTS="-Xmx4096m"
jadx app.apk -d output
或使用内置选项:
jadx -Xmx4096m app.apk -d output
问题:反编译非常慢
解决方案:跳过资源或使用更多线程:
jadx --no-res -j 8 app.apk -d output
问题:某些方法显示"无法加载方法"
解决方案:使用--show-bad-code查看部分反编译:
jadx --show-bad-code app.apk -d output
问题:GUI无法打开APK
解决方案:首先使用CLI检查错误:
jadx app.apk -d test-output
# 如果成功,再次尝试GUI
高级功能
导出为Gradle项目
jadx --export-gradle app.apk -d app-project
cd app-project
./gradlew build
创建一个可构建的Android Studio项目。
生成反混淆映射
jadx --deobf --deobf-use-sourcename app.apk -d output
# 检查output/mapping.txt中的名称映射
自定义反编译选项
# 所有选项组合
jadx \
--deobf \
--deobf-use-sourcename \
--show-bad-code \
--no-imports \
--no-inline-anonymous \
--no-replace-consts \
app.apk -d output
与IoTHackBot工具集成
Jadx适合IoTHackBot工作流程:
-
APK → API发现:
- 使用jadx反编译IoT应用程序
- 提取API端点
- 使用网络工具测试端点
-
APK → 凭据提取:
- 查找硬编码的凭据
- 针对IoT设备进行测试
- 与onvifscan、telnetshell一起使用
-
APK → 协议分析:
- 理解设备通信协议
- 使用ionet捕获流量
- 使用自定义脚本重放/修改
-
APK → 设备枚举:
- 查找设备发现机制
- 使用wsdiscovery进行ONVIF设备
- 使用nmap进行网络扫描
快速参考
# 基本反编译
jadx <apk> -d <输出目录>
# 带反混淆(推荐)
jadx --deobf <apk> -d <输出目录>
# 快速(无资源)
jadx --no-res <apk> -d <输出目录>
# 多线程
jadx -j <线程> <apk> -d <输出目录>
# 显示问题代码
jadx --show-bad-code <apk> -d <输出目录>
# 导出为Gradle项目
jadx --export-gradle <apk> -d <输出目录>
# GUI模式
jadx-gui <apk>
# 后备模式
jadx --fallback <apk> -d <输出目录>
安全分析清单
使用此清单分析jadx的APK:
- [ ] 启用反混淆进行反编译
- [ ] 搜索硬编码的API密钥
- [ ] 搜索硬编码的凭证
- [ ] 查找所有HTTP/HTTPS URL
- [ ] 检查加密实现(算法、密钥生成)
- [ ] 检查证书固定实现
- [ ] 查找SharedPreferences使用情况(存储安全)
- [ ] 检查WebView安全设置
- [ ] 查找数据库操作(SQL注入)
- [ ] 检查调试/日志代码
- [ ] 查找导出组件(来自清单)
- [ ] 检查认证/授权逻辑
- [ ] 查找文件操作(路径遍历)
- [ ] 检查本地库加载
- [ ] 记录所有发现
重要说明
- Jadx生成的Java源代码是近似的(不是原始的)
- 一些优化/混淆可能会产生无法编译的代码
- 反编译的代码可能与原始源代码略有不同
- 总是用运行时分析交叉检查发现
- Jadx最适合用标准工具编译的应用程序
- 严重混淆/受保护的应用程序可能反编译有限
- 一些反篡改机制可以检测到反编译
安全与道德
重要:只反编译您拥有或有权分析的APK。
- 尊重知识产权和许可
- 遵循漏洞的负责任披露
- 不要分发反编译的源代码
- 了解服务条款和EULA
- 仅用于授权的安全测试和研究
- 某些司法管辖区有反对逆向工程的法律
成功标准
jadx分析成功包括:
- APK成功反编译为可读的Java代码
- 应用了反混淆(如果应用程序被混淆)
- 所有源代码可搜索和可读
- 安全相关发现已记录
- 提取了API端点和URL
- 理解了加密和认证逻辑
- 确定了与其他系统的集成点
- 通过运行时测试验证了发现(如果可能)