安卓手游逆向

一、环境安装

1.1、安装Java环境 

1.2、安装SDK环境 

1.3、安装NDK环境 

二、APK

2.1、文件结构

  

2.2、打包流程 

2.3、安装流程

应用安装涉及目录:

system/app ----->系统自带的应用程序,获得adb root权限才能删除。

data/app ------->用户程序安装的目录,安装时把apk文件复制到此目录。

 

data/data -------> 存放应用程序的数据

 

data/dalvik-cache ------>将apk中dex文件安装到dalvik-cache目录下(dex文件是dalvik虚拟机的可执行文件,其大小约为原始apk文件大小的四分之一) 。

安装过程:

复制apk安装包到data/app目录下,解压并扫描安装包,把dex文件保存到dalvik-cache目录,并data/data目录下创建对应的应用数据目录。

三、虚拟机

1、Java虚拟机--->Java字节码 ---->基于栈架构。

2、dalvik虚拟机(jit机制)---->android5.0以下---->dalvik字节码---->基于寄存器架构。

3、art虚拟机(aot机制)---->android5.0以上

注意:

.dex ---->dexopt--->.odex dalvik加载执行的odex文件。

.dex --->dex2oat --->.oat art加载执行的是oat文件。

四、Java逆向知识

4.1、dex文件反汇编工具

.java ---> .class ---->.dex ---->smail。

在这个过程中会使用三种工具

使用dx.jar工具将.class文件打包成.dex文件 

使用baksmail.jar工具将.dex文件反编译成.smail文件

使用smail.jar工具将.smail文件打包成.dex文件。

4.2、dalvik字节码

数据类型对应

dalvik            Java

V ------------->void

Z ------------->boolean           

B ------------->byte          

C ------------->char           

S ------------->short        

I ------------->int

J ------------->long

F------------->float

D------------->double

L------------->java类类型

[------------->数组类型

字段

Lorg/cocos2dx/lua/AppActivity;->handler:Landroid/os/Handler;

   包名                      类名               变量名              类型

方法:                

Lpackage/name/ObjectName;->MethodName(III)Z

Lpackage/name/ObjectName:表示的是当前这个方法所在的类。

L是Java类类型,package/name/是包名,ObjectName是类名MethodName这部分表示的方法名

(III)Z:表示的是方法的签名信息,由方法参数列表(III)和返回值(Z)构成。

(III)表示三个int型参数;Z表示返回值类型为boolean。

4.3、dalvik指令集

基础字节码:名称后缀/字节码后缀 目的寄存器 源寄存“-”这个符号在有的指令里面没有的名称后缀是wide,表示数据宽度为64位,字节码后缀是from16,表示源寄存器为16位。

如move-wide/from16 vAA,VBBBB

move为基础字节码,即opcode、wide为名称后缀,标识指令操作的数据宽度为64位、from16为字节码后缀,标识源为一个16位的寄存器引用变量、vAA为目的寄存器,它始终在源的前面,取值范围为v0~v255 vBBBB为源寄存器,取值范围为v0~v65535。

dalvik指令集中大多数指令用到了寄存器作为目的的操作数或源操作数,其中A/B/C/D/E/F/G/H代表一个4位数值,AA/BB/CC...../GG代表一个8位的数值,AAAA/BBBB/...../GGGG代表一个16位的数值。

4.4、空操作指令

空操作指令的助记符为nop。它的值为00,通常nop指令被用来对齐代码之用,无实际操作。

4.5、数据操作指令

数据操作指令为move。 move 指令根据字节码大小与类型不同,后面会跟上不同的后缀。

move vA,vB:将v寄存器的值赋给vA寄存器,源寄存器与目的寄存器都为4位。

move/from16 vAA,vBBBB:将vBBBB寄存器的值赋给vAA寄存器,源寄存器为16位,目的寄存器为8位。

move/16 vAAAA,vBBBB:将vBBBB寄存器的值赋给vAAAA寄存器,源寄存器与目的寄存器都为16位。

move wide vA,vB:为4位的寄存器对赋值。源寄存器与目的寄存器都为4位。

move object vA,vB:object是对象的意思,那这里就是为对象赋值。源寄存器与目的寄存器都为4位。

move object/from16 vAA,vBBBB:为对象赋值。源寄存器为16位,目的寄存器为8位。

move-object/16 vAA,vBBBB:为对象赋值。源寄存器与目的寄存器都为16位。 

move result vAA:将上一个invoke类型指令操作的单字非对象结果赋给vAA寄存器。

move result wide vAA:将上一个invoke类型指令操作的双字非对象结果赋给vAA寄存器。

move result object vAA:将上一个invoke类型指令操作的对象结果赋给vAA寄存器。

move-exception vAA:保存运行时发生的异常到vAA寄存器,这条指令必须是异常发生时的异常处理器的一条指令。否则的话指令无效。

总结:move指令有三种作用:第一种作用:进行赋值操作、第二种作用:move-result 接收返回值操作、第三种作用:处理异常的操作 

4.6、返回指令

return就是返回的意思。

return-void:表示函数从一个void方法返回,返回值为空。

return vAA:表示函数返回一个32位非对象类型的值,返回值寄存器为8位的寄存器vAA。 

return-wide vAA:表示函数返回一个64位非对象类型的值,返回值为8位的寄存器对vAA。

return-object vAA:这里面出现了object,表示函数返回一个对象类型的值。返回值为8位的寄存器vAA。

4.7、数据定义指令

数据定义指令用来定义程序中用到的常量,字符串,类等数据。

const/4 vA,#+B:将数值符号扩展为32位后赋给寄存器vA。

const/16 vAA,#+BBBB”:将数据符号扩展为32位后赋给寄存器vAA

const vAA,#+BBBBBBBB:将数值赋给寄存器vAA。

const/bigh16 vAA,#+BBBB0000:将数值右边零扩展为32位后赋给寄存器vAA。

const-wide/16 vAA,#+BBBB:将数值符号扩展为64位后赋给寄存器对vAA。

const-wide/32 vAA,#+BBBBBBBB:将数值符号扩展为64位后赋给寄存器vAA

const-wide vAA,#HBBBBBBBBBBBBBBBB:将数值赋给寄存器vAA。

const-wide/high16 vAA,#+BBBB000000000000:将数值右边零扩展为64位后赋给寄存器vAA。

const-string vAA,string@BBBB:通过字符串索引构造一个字符串并赋给寄存器vAA。 

const-string/jumbo vAA,string@BBBBBBBB:通过字符串索引(较大)构造一个字符串并赋给寄存器vAA。

const-class vAA,type@BBBB:通过类型索引获取一个类引用并赋给寄存器vAA。

const-class/jumbo vAAAA,type@BBBBBBBB:通过给定的类型索引获取一个类引用并赋给寄存器vAAAA。这条指令占用两个字节,值为0xooff(Android4.0中新增的指令)。

4.8、实例操作指令

check-cast vAA,type@BBBB:将vAA寄存器中的对象引用转换成指定的类型。

如果失败会报出ClassCastException异常。
如果类型B指定的是基本类型,对于非基本类型的A来说,运行时始终会失败。 

instance-of vA,vB,type@CCCC:判断vB寄存器中的对象引用是否可以转换成指定的类型。

如果可以vA寄存器赋值为1,否则A寄存器赋值为0。

new-instance vAA,type@BBBB:构造一个指定类型对象的新实例,并将对象引用赋值给vAA寄存器。类型符type指定的类型不能是数组类。

4.9、数值操作指令

数组操作包括获取数组长度,新建数组,数组赋值,数组元素取值与赋值等操作。

array-length vA,vB:获取给定vB寄存器中数组的长度并将值赋给vA寄存器。数组长度指的是数组的条目个数。 

new-array vA,vB,type@CCCC:构造指定类型(type@CCCC)与大小(vB)的数组,并将值赋给vA寄存器。

filled-new-array {vc,vD,vE,vF,vG},type@BBBB:构造指定类型(type@BBBB)与大小(vA)的数组并填充数组内容。vA寄存器是隐含使用的,除了指定数组的大小外还指定了参数的个数,vC~vG是使用到的参数寄存序列。

4.10、异常指令

“throw vAA”抛出vAA寄存器中指定类型的异常。

4.11、跳出指令 

Dalvik指令集中有三种跳转指令: 

1、goto:无条件跳转。

2、switch:分支跳转

      packed-switch:有规律跳转、sparse-switch:无规律跳转。

3、if:条件跳转

      if-eq:等于/if-ne:不等于、if-lt:小于/if-le:小于等于
      if-gt:大于/if-ge:大于等于、if-eqz:等于0/if-nez:不等于0
      if-ltz:小于0/if-lez:小于等于0、if-gtz:大于0/if-gez:大于等于0

4.12、比较指令

比较指令用于对两个寄存器的值(浮点型或长整型)进行比较。

大于(1) /等于(0) /小于(-1)=>cmpg、cmp、大于(-1)/等于(0)/小于(1)=>cmpl 

4.13、字段操作指令

普通字段=>iget读/iput写

静态字段=>sget读/sput写

4.14、方法调用指令 

根据方法类型不同,共有5条方法调用指令。

invoke-virtual :调用实例的虚方法 ----->Java中的普通方法
invoke-super :调用实例的父类/基类方法 ----->Java中的父类
invoke direct :调用实例的直接方法----->Java中的构造方法
invoke-static :调用实例的静态方法----->Java中的静态方法
invoke-interface :调用实例的接口方法------>Java中的接口

4.15、数据转换指令

数据转换指令用于将一种类型的数值转换成另一种类型。

它的格式为“opcode vA,vB”,vB寄存器存放需要转换的数据,转换后的结果保存在vA寄存器中。

neg-数据类型=>求补

not-数据类型=>求反

数据类型1-to数据类型2=>将数据类型1转换为数据类型2。

4.16、数据运算指令

add/sub/mul/div/rem  加/减/乘/除/模

and/or/xor   与/或/异或

shl/shr/ushr 有符号左移/有符号右移/无符号右移。

五、smali文件分析

5.1、描述类的信息

在打开smali文件的时候,它的头三行描述了当前类的一些信息

.class<访问权限>[修饰关键字]<类名>

.super<父类名>

.source<源文件名>

.class指令表示当前的类名,类的访问权限是public,类名为LHelloWorld,类开头的L表示后面跟随的字符串是一个类。

.super指定了当前类所继承的父类,后面指的就是这个父类的类名,L表示后面跟字符串是一个类。

source行代码为空:因为经过混淆的dex文件,反编译出来的smali代码可能没有源文件信息。 

5.2、静态字段 

# static fields

. field<访问权限>static[修饰关键字]<字段名>:<字段类型>

baksmali在生成smali文件时,会在静态字段声明的起始处添加注释“static fields”,注释以#开头。

访问权限包括:private、protected、public修饰关键字为字段其他属性。

5.3、实例字段 

# instance fields

.field<访问权限>[修饰关键字]<字段名>:<字段类型>

5.4、直接方法 

# direct methods

.method<访问权限>[ 修饰关键字]<方法原型>、
<.registers>、<.locals> [.param] [.prologue][.line]<代码体>
.end method

#direct method 是注释,是baksmali添加的,访问权限和修饰关键字 跟字段是一样的。方法原型 描述了方法的名称、参数与返回值。 

.registers 指令指定了方法中寄存器的总数,这个数里是参数和本地变里总和。
.param 表明了方法的参数,每个.param指令表示一个参数,方法使用了几个参数就有几个.parameter指令。
.prologue 指定了代码的开始处,混淆过的代码可能去掉了该指令。

.line 指明了该处代码在源代码中的行号,同样,淆后的代码可能去掉了行号。
.local 使用这个指定表明方法中非参寄存器

5.5、虚方法

虚方法指的是从父类中继承的方法或者实现接口的方法,它的声明跟直接方法相同。

# virtual methods

.method<访问权限>[修饰关键字]<方法原型><.registers> <.locals>[.param][.prologue][.line]<代码体>.end method

5.6、接口 

 # interfaces

.implements<接口名>

 #interfaces是注释

.implements是接口关键字,后面的接口名是DexClassDef结构中interfacesOff字段指定的内容。

5.7、注解 

.annotation[注解属性]<注解类名>[注解字段 = 值].end annotation 

5.8、实例分析

使用程序代码中支付成功的逻辑代码替换掉支付取消的代码

保存并编译修改后的代码

编译后将会生成新的apk文件,安装重新运行即可。

5.9、RE文件管理器逆向 

 第一步附加模拟器

第二步执行命令:adb shell dumpsys activity top 

第三步使用代码查看器查看广告代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鸭鸭老板

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值