安卓学习思路方法总结(三)
字数 3160 2025-08-09 18:44:12
Android逆向工程学习指南(三):Dalvik指令集与APK破解实战
一、Dalvik指令集详解
1. 基础字节码分析
- 名称后缀:如
wide表示数据宽度为64位 - 字节码后缀:如
from16表示源寄存器为16位 - 寄存器表示:
A/B/C/D/E/F/G/H:4位数值AA/BB/CC/DD/EE/FF/GG/HH:8位数值AAAA/BBBB/...HHH:16位数值
2. 常用指令类型
空操作指令
- 助记符:
nop - 值:
00 - 用途:对齐代码,无实际操作
返回指令
return-void:从void方法返回,返回值为空return vAA:返回32位非对象类型值return-wide vAA:返回64位非对象类型值return-object vAA:返回对象类型值
数据定义指令
const/4 vA,#+B:将数值符号扩展为32位后赋给vAconst/16 vAA,#+BBBB:将数据符号扩展为32位后赋给vAAconst-string vAA,string@BBBB:通过字符串索引构造字符串const-class vAA,type@BBBB:通过类型索引获取类引用
跳转指令
goto:无条件跳转switch:分支跳转packed-switch:有规律跳转sparse-switch:无规律跳转if条件跳转:if-eq/if-ne:等于/不等于if-lt/if-le:小于/小于等于if-gt/if-ge:大于/大于等于if-eqz/if-nez:等于0/不等于0
实例操作指令
check-cast vAA,type@BBBB:将对象引用转换成指定类型instance-of vA,vB:判断vB对象引用是否可以转换new-instance vAA,type@BBBB:构造指定类型新实例
数组操作指令
array-length vA,vB:获取数组长度new-array vA,vB,type@CCCC:构造指定类型与大小的数组
方法调用指令
invoke-virtual:调用实例虚方法invoke-super:调用父类方法invoke-direct:调用直接方法invoke-static:调用静态方法invoke-interface:调用接口方法
二、APK破解实战技巧
1. 快速定位关键代码方法
- 搜索特征字符串:如"支付"、"VIP"、"余额不足"等
- 搜索关键API:如支付宝、微信相关API
- 通过方法名判断功能:分析程序命名规范
- 反编译APK:
- 分析
AndroidManifest.xml:包名、系统版本、组件 - 定位主Activity(程序入口界面)
- 关注
application执行时间和授权验证
- 分析
2. 定位关键代码技巧
- 信息反馈法:通过资源ID或字符串定位
- 特征函数法:通过API函数定位
- 顺序查看法:分析程序执行流程
- 代码注入法:动态调试,插入log查看
- 栈跟踪法:动态调试,分析函数调用流程
- Method Profiling:方法剖析,热点分析
3. 常见支付关键词
- 支付宝:搜索字符串"9000"(支付成功)
- 咪咕游戏:搜索常量"onresult"
- 中国移动:特征码46000、46002、46007、46020
- 中国联通:特征码46001、46006、46010
- 中国电信:特征码46003、46005、46011
三、实战案例解析
案例1:单机斗地主破解
目标:跳过支付宝支付购买记牌器
-
jadx-gui分析:
- 搜索字符串"9000"定位支付成功代码
- 分析
if判断逻辑,发现支付成功(9000)和失败(8000)的判断
-
Android Killer修改:
- 找到
if-eqz v1, :cond_4判断 - 修改为
if-nez v1, :cond_4使支付失败时执行成功逻辑
- 找到
-
效果:支付失败但程序认为成功,可使用记牌器功能
案例2:卧龙影视VIP破解
目标:绕过VIP验证
-
jadx-gui分析:
- 搜索"getVip"定位VIP验证方法
- 分析
UserVip实体类中的isVip、End、Start字段
-
Android Killer修改:
- 找到
public getVip()方法 - 修改为
const v0,0x1强制返回VIP状态
- 找到
-
效果:登录后显示VIP状态,解锁全部功能
案例3:起名软件VIP破解
目标:绕过五行选择限制
-
jadx-gui分析:
- 搜索"getVip"定位验证代码
- 分析
switch判断逻辑
-
Android Killer修改:
- 找到两处
if-eqz v1, :cond_0 - 修改为
if-nez v1, :cond_0 - 或直接注释
getVip方法
- 找到两处
-
效果:可无限制使用五行选择功能
案例4:RE文件管理器广告去除
目标:去除退出时的广告
-
adb抓包:
- 使用
adb shell dumpsys activity top获取当前界面进程 - 定位广告Activity
com.AddDouDouWall2.WebPageDownLoadMainActivity
- 使用
-
jadx-gui分析:
- 找到广告URL和
DownLoadManagerService - 分析
onDestroy方法中的网络检查和启动逻辑
- 找到广告URL和
-
Android Killer修改:
- 修改
if-eqz v0, :cond_0为if-nez v0, :cond_0 - 或替换广告URL为自定义页面
- 修改
-
效果:退出时不再显示广告
案例5:车来了广告去除
目标:去除中间广告
-
DDMS分析:
- 使用DDMS监控应用行为
- 过滤
com.ygkj.chelaile.standard包名 - 定位广告域名
atrace.chelaile.net.cn
-
Android Killer修改:
- 搜索并替换广告域名为
127.0.0.1
- 搜索并替换广告域名为
-
效果:中间广告消失
案例6:好搜小说大全插桩分析
目标:学习代码插桩技术
-
Log信息输出插桩:
- 在
onCreate()方法中插入Log输出 - 使用Unicode编码特殊字符
- 注意寄存器数量调整(
locals)
- 在
-
StackTrace栈跟踪:
- 在关键方法如
loadData()中插入栈跟踪代码 - 使用
Exception.printStackTrace()输出调用链
- 在关键方法如
-
DDMS分析:
- 观察入口点和入口界面的执行顺序
- 分析栈跟踪信息,理解调用关系
四、常见问题解决
-
回编译失败:
- APKTOOL版本问题:尝试不同版本
- Java环境问题:检查Java版本和环境变量
-
程序崩溃:
- 插桩导致寄存器不足:增加
locals数量 - 方法调用错误:检查指令使用是否正确
- 插桩导致寄存器不足:增加
-
init()方法插桩:
- init方法在初始化时不会调用寄存器
- 是安全的插桩位置
五、高级技巧
-
栈跟踪分析:
- 使用DDMS暂停分析栈
- 理解Parents(父节点)和Children(子节点)关系
- 分析调用链和循环体
-
动态调试:
- 结合jadx-gui静态分析和动态调试
- 使用logcat监控程序行为
-
代码注入:
- 修改关键判断逻辑(如if条件)
- 替换关键字符串和URL
- 强制返回值绕过验证
六、注意事项
- 法律风险:所述技术仅用于学习目的
- 道德考量:尊重开发者劳动成果
- 技术边界:不得用于非法用途
通过系统学习Dalvik指令集和实战案例,可以逐步掌握Android逆向工程的核心技术。建议从简单案例入手,逐步深入理解Android应用的运行机制和破解方法。