001
JDK Android 集成开发环境搭建 NDK AndroidKiller Jeb IDA WinHex
虚拟机
java 虚拟机 dalvik 虚拟机(5.0以下) art 虚拟机(5.0及以上)
.dex => dexopt => .odex dalvik 加载执行的 odex 文件
.dex => dex2oat => .oat art 加载执行的 oat 文件
APK 文件结构
class.dex 应用程序的可执行文件,方法数超过 65535 ,进行分包处理会有多个 dex 文件。通过反编译工具 dex2jar 转换为 jar 包,在通过 jd-gui 查看代码 resources.arsc 资源索引表
dalvik 寄存器
v: 局部变量寄存器 v0-vn 参数寄存器 vn-vn + m p: 参数寄存器 p0-pn 变量寄存器:v0-vn
Dalvik | java |
---|---|
B | byte |
C | char |
S | short |
I | int |
J | long |
F | float |
D | double |
Z | boolean |
V | void |
L | java 类类型 |
[ | 数组类型 |
Lpackage/name/ObjectName;->FieldName:Ljava/lang/String;
字段格式:类型(包名+类名)-> 字段名称:字段类型
dalvik 指令
基础字节码 - 名称后缀/字节码后缀 目的寄存器 源寄存器
nop
空操作指令,值为00
,对其代码,无实际操作move
数据操作指令move
作用:1、赋值
2、接受方法返回值操作
3、处理异常操作
move vA, vB
将vB
寄存器的值赋给vA
寄存器,源寄存器和目的寄存器都为 4 位move-wide vA, vB
为 4 位的寄存器赋值,源和目的寄存器都为 4 位move/form16 vAA, vBBBB
将vBBBB
寄存器的值赋给vAA
寄存器,源寄存器为 16 位, 目的寄存器 8 位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 寄存器return
返回指令return-void
一个 void 方法返回,返回值为空return vAA
函数返回一个 32 位非对象类型的值,返回值寄存器为 8 位的 vAAreturn-wide vAA
函数返回一个 64 位非对象类型的值,返回值为8位的寄存器 vAAreturn-object vAA
函数返回一个对象类型的值,返回值为8 位的寄存器 vAAconst
数据定义指令(定义常量,字符串,类等数据)const/4 vA, #+B
将数值符号扩展为 32 位后赋给寄存器 vAconst/16 vAA, #+BBBB
将数据符号扩展为 32 位 后赋给寄存器 vAAconst vAA, #+BBBBBBBB
将数值赋给寄存器 vAAconst/high16 vAA, #+BBBB0000
将数值右边零扩展为 32 位后赋给寄存器 vAAconst-wide/16 vAA, #++BBBB
将数值符号扩展为 64 位后赋值给寄存器 vAAconst-wide/32 vAA, #+BBBBBBBB
将数值符号扩展为 64 位后赋值给寄存器 vAAconst-wide vAA, #+BBBBBBBBBBBBBBBB
将数值赋给寄存器 vAAconst-string vAA, string@BBBB
通过字符串索引构造一个字符串并赋给寄存器 vAAconst-string vAA, string@BBBBBBBB
通过字符串索引 (较大) 构造一个字符串并赋给寄存器 vAAconst-class vAA, type@BBBB
通过类型索引获取一个类引用并赋给寄存器 vAAconst-class/jumbo vAAAA, type@BBBBBBBB
通过给定的类型索引获取一个类引用并赋给 vAAAA。这条指令占用两个字节,值为 0xooff (Android4.0新增)实例操作指令
check-cast vAA, type@BBBB
将 vAA 寄存器中的对象引用转换为指定类型instance-of vA, vB
判断 vB 的对象引用是否可以转换为指定类型。如果可以 vA 赋值 1,否则 vA 赋值 0new-instance vAA, type@BBBB
构造一个指定类型对象的实例,并将对象引用赋值给 vAA 寄存器数组操作指令
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 是使用到的参数寄存序列。filled-new-array/range {vCCCC ..vNNNN}, type@BBBB
指令功能与filled-new-array {vC, vD, vE, vF, vG}, type@BBBB
相同,只是参数寄存器使用range
字节码指定了取值范围fill-array-data vAA, +BBBBBBBB
用指定的数据填充数组, vAA 寄存器为数组引用,引用必须为基础类型的数组,在指令后面会紧跟一个数据表异常指令
throw vAA
抛出 vAA 寄存器中指定类型的异常跳转指令
if-eq
等于if-ne
不等于if-lt
小于if-le
小于等于if-gt
大于if-ge
大于等于if-eqz
等于0if-nez
不等于0if-ltz
小于0if-lez
小于等于0if-gtz
大于0if-gez
大于等于0packed-switch
有规律跳转sparse-switch
无规律跳转goto
无条件跳转switch
分支跳转if
条件跳转cmp
比较指令(浮点型或长整型)大于(1)/等于(0)/小于(-1)
=> cmpg、cmp大于(-1)/等于(0)/小于(1)
=> cmplcmp-long vAA, vBB, vCC
比较两个长整型数,如果 vBB 大于 vCC, 则 vAA 等于 1,相等则结果为 0, 小于则结果为 -1cmpl-float vAA, vBB, vCC
比较两个单精度浮点数. 大于 为 -1, 等于 0 ,小于为 1cmpl-double vAA, vBB, vCC
比较双精度浮点数字段操作指令
普通字段 => iget
读 /iput
写静态字段 => sget
读 /sput
写方法调用指令
invoke-virtual
调用实例的虚方法(普通方法)invoke-super
调用实例的父类/基类方法invoke-direct
调用实例的直接方法(构造方法)invoke-static
调用实例的静态方法invoke-interface
调用实例的接口方法数据转换指令
opcode vA, vB
vB 存放需要转换的数据,转换后的结果保存在 vAneg-数据类型 => 求补
not-数据类型 => 求反
数据类型1-to-数据类型2 => 将数据类型1转换为数据类型2
数据运算指令
add/sub/mul/div/rem
加、减、乘、除、模and/or/xor
与、或、异或shl/shr/ushr
有符号左移、有符号右移、无符号右移
评论