1. 准备工作
工具准备:
- Apktool:用于反编译和重新打包 APK
- 签名工具:jarsigner(JDK 自带)或 apksigner(Android SDK 提供)
- 调试工具:adb logcat 查看日志
操作流程:
反编译 APK -> 修改 Smali 代码 -> 重新打包 -> 签名 -> 安装测试
2. 反编译 APK
1 | apktool d target.apk -o output_dir |
反编译后,Smali 代码位于 output_dir/smali 目录中
3. 在 Smali 代码中插入日志
3.1. 定位目标代码
- 通过逆向工具(如 Jadx)分析目标代码的大致位置,找到对应的 Smali 文件
- 例如:目标代码在 com.example.MainActivity,则 Smali 文件为:
smali/com/example/MainActivity.smali
3.2. 插入日志的 Smali 指令
在 Smali 中调用Log.d()需要以下步骤:
- 定义 TAG(可选):在类中定义一个静态字符串作为 TAG
- 加载参数:将 TAG 和日志内容加载到寄存器
- 调用静态方法:执行
Log.d(TAG, message)
示例:在方法中插入日志代码
1 | # 原始代码(假设在方法 .method public onCreate()V 内) |
3.3. 注意事项
- 寄存器冲突:确保
v1、v2等寄存器未被占用(根据上下文调整寄存器编号) - 参数顺序:
Log.d()的第一个参数是TAG(String),第二个参数是message(String)
4. 重新打包 APK
1 | apktool b output_dir -o unsigned.apk |
生成的unsigned.apk是未签名的 APK
5. 签名 APK
5.1. 生成签名密钥(若无可跳过,使用已有密钥)
1 | keytool -genkey -v -keystore mykey.keystore -alias myalias -keyalg RSA -keysize 2048 -validity 10000 |
5.2. 使用 jarsigner 签名
1 | jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore mykey.keystore unsigned.apk myalias |
输出文件为signed.apk
5.3. 使用 apksigner 签名(推荐)
1 | apksigner sign --ks mykey.keystore --ks-key-alias myalias signed.apk unsigned.apk |
6. 安装并测试
1 | adb install signed.apk |
7. 常见问题与解决
7.1. 应用崩溃或无法启动
- 原因:Smali 代码修改错误(如寄存器冲突、指令格式错误)
- 解决:
- 检查插入的 Smali 指令语法
- 使用
adb logcat查看崩溃日志(过滤 AndroidRuntime)
7.2. 日志未输出
- 原因:
- 代码未被执行(断点位置错误)
- 日志 TAG 过滤错误
- 解决:
- 检查插入日志的代码路径是否触发
- 使用
adb logcat -s MyTag:*确保过滤正确
7.3. 签名后安装失败
- 原因:签名不兼容或 APK 未对齐
- 解决:
- 使用
zipalign对齐 APK:zipalign -v 4 unsigned.apk aligned.apk - 确保使用
apksigner而非旧版jarsigner,jarsigner仅支持 V1 签名,需改用apksigner生成 V2/V3 签名
- 使用
8. 完整操作流程示例
1 | # 1. 反编译 APK(使用 Apktool) |
如果无法安装 zip,可以通过以下方式手动删除 META-INF 文件夹:
- 使用解压工具(如 7-Zip、WinRAR)打开 aligned.apk
- 删除 META-INF 文件夹
- 保存并关闭