Untitled
这是系列文章的第三篇
我们继续
前言
基础字节码---名称后缀/字节码后缀
目的寄存器 源寄存
1、名称后缀是wide,表示数据宽度为64位
2、字节码后缀是from16,表示源寄存器为16位
3、move-wide/from16 vAA,vBBBB
分析一下:这里AA是目的寄存器没表示出来
BBBB,因为一个字母是4位,4个B就表示源寄存器为16位
整体分析:
move为基础字节码,即 opcode。
wide为名称后缀标识指令操作的数据宽度为64位。
from16为字节码后缀,标识源为一个16位的寄存器引用变量
vAA为目的寄存器,它始终在源的前面,取值范围为v~V255。
VBBBB为源寄存器,取值范围为v0~v65535
Dalvik指令集中大多数指令用到了寄存器作为目的操作数或源操作数
其中A/B/C/D/E/F/G/H
代表一个4位的数值,
AA/BB/CC/DD/EE/FF/GG/HH
代表8位的数值
AAAA/BBBB/…HHH
则代表一个16位的数值
Dalvik指令使用
空操作指令
空操作指令的助记符为nop
它的值为00,通常nop指令被用来作对齐代码之用,无实际操作!
返回指令
1、"return-void":表示函数从一个vod方法返回,返回值为空。
2、"return vAA":表示函数返回一个32位非对象类型的值返回值寄存器为8位的寄存器vAA
3、"return-wide vAA":表示函数返回一个64位非对象类型的值,返回值为8位的寄存器对vAA
4、"return-object vAA":这里面出现了 object,表示函数返回一个对象类型的值。返回值为8位的寄存器vAA
数据定义指令
可以参考这里:
https://blog.csdn.net/u010164190/article/details/52089794

数据定义指令用来定义程序中用到的常量,字符串,类等数据。
1)"const/4 vA,#+B":将数值符号扩展为32位后赋给寄存器vA。
2)"const/16 vAA,#+BBBB":将数据符号扩展为32位后赋给寄存器
3)"const vAA,#+ BBBBBBBE":将数值赋给寄存器vAA。
4)"const/high16 vAA,#+BBBB0O000":将数值右边零扩展为32位后赋给寄存器vAA。
5)"const-string vAA,string@BBBB":通过字符串索引构造一个字符串并赋给寄存器vAA。
6)"const-string/jumbo vAA,string@BBBBBBBB":通过字符串索引
(较大)构造一个字符串并赋给寄存器vAA。
7)"const-class vAA,type@BBBB":通过类型索引获取一个类引用并赋给寄存器vAA。
8)"const-class/jumbo vAAAA,type@BBBBBBBB":通过给定的类型索引获取一个类引用并赋给寄存器 VAAAA
(这条指令占用两个字节值为0xoof(Android4.0中新增的指令))。

跳转指令
跳转指令用于从当前地址跳转到指定的偏移处。
跳转指令
(1)、goto:无条件跳转
(2)、switch:分支跳转
(3)、packed-switch:有规律跳转
(4)、sparse-switch:无规律跳转
(5)、if:条件跳转
if-eq:等于/if-ne:不等于
if-lt:小于/if-le:小于等于
if-gt:大于/if-ge:大于等于
if-eqz:等于0/if-nez:不等于0
if-1tz:小于0/if-1ez:小于等于0
if-gtz:大于0/if-gez:大于等于0
实例操作指令
1、"check-cast vAA,type@BBBB"
check-cast vO将vAA寄存器中的对象引用转换成指定的类型。如果失败会报出 Class CastException异常。 如果类型B指定的是基本类型,对于非基本类型的A来说,运行时始终会失败
2、"instance-of vA,vB"
判断vB寄存器中的对象引用是否可以转换成指定的类型。
如果可以vA寄存器赋值为1,否则vA寄存器赋值为0
3、"new-instance vAA,type@BBBB"
构造一个指定类型对象的新实例,并将对象引用赋值给vAA寄存器。
类型符type指定的类型不能是数组类。
数组操作类型
数组操作包括获取数组长度,新建数组,数组赋值,数组元素取值与赋值等操作。
1、array-length vA,vB"
获取给定vB寄存器中数组的长度并将值赋给A寄存器。 数组长度指的是数组的条目个数。
2、"new-array vA,vB,type@CCCC":
构造指定类型(type@CCCC)与大小(vB)的数组,并将值赋给vA寄存器
异常指令
"throw vAA":抛出vAA寄存器中指定类型的异常
比较指令(cmp)
比较指令用于对两个寄存器的值(浮点型或长整型)进行比较
大于(1)/等于(0)/小于(-1)-->cmpg、cmp
大于(-1)/等于(0)/小于(1)--->cmpl
字段操作指令
字段是成员变量
普通字段
iget读 iput写
iget读是从后往前走 iput写是从前往后走
静态字段
sget读 sput写
方法调用指令
根据方法类型不同,共有5条方法调用指令
1、invoke-virtua|:调用实例的虚方法(普通方法) 2、invoke-super:调用实例的父类/基类方法 3、invoke-direct:调用实例的直接方法 4、invoke-static:调用实例的静态方法 5、invoke-interface:调用实例的接口方法
数据转换指令
数据转换指令用于将一种类型的数值转换成另一种类型。
它的格式为opcode VA,vB
vB寄存器存放需要转换的数据,转换后的结果保存在vA寄存器中
neg---数据类型--->求补
not---数据类型--->求反 数据类型1-to-数据类型2--->将数据类型1转换为数据类型2
APK快速上手小技巧
1、快速定位关键代码
搜索特征字符串
比如购买、VIP、支付取消、余额不足等
搜索关键api
支付宝、微信......关键字
通过方法名来判断方法的功能
比如方法的名称,每个程序都有自己的规范等!
反编译APK程序
AndroidMainfest.xml
-->包名/系统版本/组件
程序的主 activity(程序入口界面)
每个 Android程序有且只有一个主 Activity分析程序的执行流程
需重点关注的 application
1.application执行时间 2.授权验证
2、定位关键代码的技巧
1)信息反馈法(资源id/字符串)
比如支付成功,支付失败等!
2)特征函数法
比如api函数
3)顺序查看法
进行分析程序执行流程/病毒分析
4)代码注入法
动态调式/插入log查看 logcat/分析加解密
5)栈跟踪法
动态调式/函数调用流程
使用IDA进行分析
6)Method Profiling
方法剖析-->动态调式/热点分析/函数调用流程
3、关键词
方法名和游戏方法名
onResult,onchinabilling,resulton,Paycenter,Callback
爱游戏方法名
paySuccess(成功)payFailed(失败)payCancel(成功)
沃游戏方法名
OnPayResult,PyaResulton,Activity,result,callback
4399游戏方法名
notifydelivergoods
支付宝和银行卡方法名
handle,message
移动MM方法名
onBillingFinish,Billing,CallBack
360支付
onfnished on Activityresult
支付宝搜索字符串:9000
咪咕游戏搜索常量:onresult
发送短信权
android.permission.SEND_SMS
锁定支付模式关键字符串:CHINA TELECOM
支付上限
carrier_pay_out limit,no_propriate_pay_method
谷歌广告
Missing internet permission in AndroidManifest.xml
运营商网络特征码备注
中国移动46000、46002、46007、46020return 0 getMobile Type
中国联通46001、46006、46010return 2 getOperatorType
中国电信46003、46005、46011return 1 getSimType
实操一:单地斗*主
用单机斗*主来学习
前言

也是有多人对战的





我们的目标是:跳过这个支付宝支付,购买该程序软件内容呢
采用Android Killer和jadx-gui两个软件的混合使用
jadx-gui查看Java代码
把APK丢到jadx-gui中
我们要点击这个搜索类

APK才算反编译完成
我们知道的在支付宝中搜索的字符串:9000(支付成功)
进行搜索
"9000"

双击搜索内容 进来之后看到了 Java代码

public void a(String str) {
String a2 = new e(str).a();
理解一下:public void方法里传入了一个 String,String a2 new了一个string
我们再去看看方法a里面写了什么

public String a() {
return this.f554a;
}
这个方法最终会返回一个方法:f554a
继续向下分析

几个if语句进行判断
成功的话进入UMGameAgent.pay这个 商品选择阶段
前面是天数 后面是金额

那么这里的思路:
思路一:如果把30天20块钱的代码放入2天2块钱的代码替换后,是不是可以买30天的记牌器只用花2块钱 思路二:8000是支付成功和9000是支付失败,那么调换位置呢
我们继续往上看

看看w
方法的调用
选中w之后 右键查找用例

进行查看

同样是if判断,这里是采用了赋值操作
可以看到传入两个int参数i
和i2
,string也进入记牌器
然后判断2==i
、7==i
、30==i
然后赋值d2
那么思路三:可以将此处20改为0吗
Android Killer进行查看smali代码
把APK丢到Android Killer中

然后去搜索字符串:9000(支付成功)

进行逻辑分析

很好理解的
const-string v1:把v1定义为9000(支付成功)
equals:v0和v1进行了个比较,返回结果放到v1里面
if-eqz:如果v1等于0跳到cond_4
那么去看看cond_4

继续进行逻辑分析
const-string v1:把v1定义为8000(支付失败)
invoke-static:是方法调用指令中的:调用实例的静态方法 建议回头去看一下
equals:v0和v1进行了个比较,返回结果放到v0里面
if-eqz:如果v0等于0跳到cond_1
那么我们继续 去看看cond_1

goto是跳转指令中的:无条件跳转
return-void:就是结束了
那么最简单的一个方法:
if-eqz v1, :cond_4
改为if-nez v1, :cond_4
支付失败 执行支付成功

保存之后 编译输出

进行查看

可以看到我们其实 是支付失败的 但是因为执行的是支付成功
所以依然可以使用
是不是蛮简单的?但是其实并不是 我感觉要多加练习,你要抓住那个点,多加练习才可以
继续加油
再来一个实操
实操二:卧龙影视
以卧龙影视进行演示
前言

当我们点击之后 它会加载广告

那么我们使用之前的方法安卓(一)是不是可以删掉第一个跳转的界面 进行去广告操作呢 是可以的
小伙伴们可以去尝试一波

今天破解的就是它的Vip功能
如上操作
jadx-gui查看Java代码
要破解Vip,这里大部分所有APK的环境下都是搜索getVip
这里要注意:
1、搜索勾选代码
2、我们要破解的是用户的Vip


往上翻 针对UserVip

右键查找用例


这是一个实体类
分析一下
is vip(是否是Vip)、
End(vip结束时间)、Start(vip开始时间)
那么继续针对getIsVip进行查找用例


那么我们这里:让 getVip返回值不为空
Android Killer进行查看smali代码
根据包package 在Android Killer中找对应目录

注意这里是:smali_classes2


我们要改的smali代码就是UserVip.smali
然后找到public getVip()

进行分析
这个方法使用到locals 1
—个寄存器
iget读取字段,v0是我们的寄存器,p0是从之前用户判断过来的值,这里就是用户去读取v0
如果p0是Vip那么v0就是Vip,如果p0不是Vip那么v0肯定不是Vip
最后return v0
寄存器
我们的目标是:让getvip返回值不为空就行
const v0,0x1

回编译成功

关于回编译失败问题:
1、APKTOOL版本问题

2、Java环境问题


然后我们继续 去查看一下
当我们注册登录之后 成功拿到Vip

安卓学习思路方法总结(三)https://www.freebuf.com/articles/mobile/282950.html
安卓学习思路方法总结(四)https://www.freebuf.com/articles/mobile/284486.html
安卓学习思路方法总结(五)https://www.freebuf.com/articles/mobile/284778.html
安卓学习思路方法总结(六)https://www.freebuf.com/articles/mobile/286838.html
Last updated
Was this helpful?