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参数ii2,string也进入记牌器

然后判断2==i7==i30==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?