为什么要写这个, 因为看的太枯燥了,自己手打一遍 加深记忆。

1 dalvik 字节码

在说指令集前 先简单的回忆一下dalvik字节码的相关知识。

1.1 Dalvik 寄存器

Dalvik寄存器分为32位和64位,小于等于32位的使用一个寄存器标识,64位使用两个相邻寄存器标识,

1.2 寄存器的命名法

寄存器有两种命名方式:v命名法和p命名法

v命名法

局部变量寄存器 v0-vn 表示,参数寄存器从vn - v(n+m)

比如 在下图中,使用了v1,v2,v3,v4,v5,其中 v0,v1,v2 是局部变量,v3 和v4 是参数。

p命名法

变量寄存器 v0-vn 参数寄存器 p0-pn

p命名法比v命名法容易辨识,参数和变量采用不同的字母表示,但两者表示的含义都是一样的,没有什么区别。

1.3 了解dex反编译工具

java 文件到smali文件的过程

.java编译成.class在线编译成.dex,最后反编译成smali文件

class 文件打包成dex

dx –dex –output=Decrypt.dex com/xiaomutou/demo/Decrypt.class

dex文件反编译成samli文件

java -jar baksmali.jar -o smali_out/ classex.dex

smali 打包成dex

java -jar smali.jar smali_out/ -o classes.dex

1.4 Dalvik 字节码类型

在Dalvik中有一种描述类型的方式和Java对应,下面给出具体规则

Dalvik Java
B byte
C char
S short
I int
J long
F float
D double
Z boolean
V void
L Java类类型
[ 数组类型

1.5 字段

Lpackage/name/ObjectName;->FieldName:Ljava/lang/String;

字段格式:类型(包名+类名)->字段名称 :**字段类型**

举例:

1
2
3
4
5
6
7
8
9
10
Dalvik: 
Lcom/alipay/sdk/app/H5PayActivity;->b:Ljava/lang/String;
Java:
import com.alipay.sdk.app;

public class H5PayActivity {

String b;

}
1
2
3
4
5
6
7
Dalvik:
Lcom/auth/third/accountlink/ui/WebViewActivity;->a:Z
Java:
import com.auth.third.accoutlink.ui;
public class WebViewActivity{
boolean a;
}
1
2
3
4
5
6
7
8
Dalvik:
Lcom/alipay/sdk/authjs/a;->m:Lorg/json/JSONObject;
Java:
import com.alipay.sdk.authjs;
import org.json.JSONObject;
public class a{
JSONObject m;
}

例子解析不知道对不对, 如果有表哥看到了欢迎指正

1.6 方法

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

(III) Z:这部分表示的是方法的签名信息

举例:

1
2
3
4
5
6
7
8
9
10
Dalvik:
Landroid/app/Activity;-><init>()V
Java:
package andorid.app.Activity;

public class Activity{
public void <init>(){

}
}
1
2
3
4
5
6
7
8
9
Dalvik:
Lcom/alipay/sdk/j/h;->b()Z
Java:
import com.alipay.sdk.j;
public class h{
public boolean b(){

}
}
1
2
3
4
5
6
7
8
9
Dalvik:
Landroid/content/Intent;->getExtras()Landroid/os/Bundle;
Java:
import andorid.content
public class Intent{
public Bundle getExtras(){

}
}
1
2
3
4
5
6
7
8
9
Dalvik:
Lorg/cocos2dx/lua/LoadingAct;->setContentView(I)V
Java:
import org.cocos2dx.lua;
public class LoadingAct{
public void setContentView(int p1){

}
}

例子解析不知道对不对, 如果有表哥看到了欢迎指正

2 Dalvik 指令集

2.1 Dalvik 指令格式

推荐一篇文章:Android 逆向笔记

基础字节码 - 名称后缀/字节码后缀 目的寄存器 源寄存

move-wide/from16 vAA,vBBBB

move 为基础字节码,即opcode

wide 为名称后缀,标识指令操作的数据宽度为64位

from16 为字节码后缀 ,标识源为一个16位的寄存器引用变量

vAA 为目的寄存器,它始终在源寄存器的前面 一个A代表4位 两个A为8位 取值范围为V0-V(2^8)

vBBBB 为源寄存器, 取值 v0 - v 65535

常见Dalvik 指令的使用

  1. 空操作指令

    nop 值为00 通常被用来做代码对齐,无实际操作

  2. 数据操作指令

    move 作用:将源寄存器的值赋值给目的寄存器

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

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

    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作用:

    1. 赋值操作
    2. move-result 接收方法返回值操作
    3. 处理异常的操作
  3. 返回指令

    return就是返回的意思,大家根据这个英文就可以理解啦。

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

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

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

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

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

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

“const/16 vAA, #+BBBB:将数据符号扩展为32位后赋给寄存器vAA。这里的#+BBBB表示 0x12344等

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

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

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

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

const-wide vAA, #+BBBBBBBBBBBBBBBB:将数值赋给寄存器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中新增的指令)。

  1. 实例操作指令

    “check-cast vAA, type@BBBB”:check-cast v0 ,

    将vAA寄存器中的对象引用转换成指定的类型。如果失败会报出ClassCastException异常。

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

“instance-of vA, vB, ”:

判断vB寄存器中的对象引用是否可以转换成指定的类型。如果可以vA寄存器赋值为1,否则vA寄存器赋值为0。

“new-instance vAA, type@BBBB”:

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

  1. 数组操作指令

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

“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字节码后缀指定了取值范围 ,vC是第一个参数寄存器,N = A +C -1。

fill-array-data vAA, +BBBBBBBB:

用指定的数据来填充数组,vAA寄存器为数组引用,引用必须为基础类型的数组,在指令后面会紧跟一个数据表。

  1. 异常指令

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

  2. 跳转指令(重点)

    跳转指令用于从当前地址跳转到指定的偏移处。

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

    1. goto:无条件跳转

    2. switch:分支跳转

      ​ packed-switch:有规律跳转

      ​ sparse-switch: 无规律跳转

      1. 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

  3. 比较指令(cmp)

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

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

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

例如:cmp-long vAA, vBB, vCC

​ 比较两个长整型数。如果vBB寄存器大于vCC寄存器,则结果为1,相等则结果为0,小则结果为-1。

例如:cmpl-float vAA, vBB, vCC

​ 比较两个单精度浮点数。如果vBB寄存器大于vCC寄存器,结果为-1,相等则结果为0,小于的话结果为1。

例如:cmpl-double vAA, vBB, vCC

​ 比较两个单精度浮点数。如果vBB寄存器大于vCC寄存器,结果为-1,相等则结果为0,小于的话结果为1。

例如:cmpg-float vAA, vBB, vCC

  比较两个单精度浮点数。如果vBB寄存器大于vCC寄存器,结果为-1,相等则结果为0,小于的话结果为1。

例如:cmpg-double vAA, vBB, vCC

​ 比较两个单精度浮点数。如果vBB寄存器大于vCC寄存器,结果为-1,相等则结果为0,小于的话结果为1。

  1. 字段操作指令

    普通字段 => iget读 / iput 写

    静态字段 => sget读 / sput 写

  2. 方法调用指令(重点)

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

invoke-virtual :调用实例的虚方法

invoke-super :调用实例的父类/基类方法

invoke-direct :调用实例的直接方法

invoke-static :调用实例的静态方法

invoke-interface :调用实例的接口方法
  1. 数据转换指令

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

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

neg-数据类型 **=>** 求补

not-数据类型 **=>** 求反

数据类型1-to-数据类型2 **=>** 将数据类型1转换为数据类型2
  1. 数据运算指令

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

    and/or/xor 与/或/异或

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

参考文献

深入理解Dalvik字节码指令及Smali文件

相关文章
评论
分享
  • scrapy 框架学习

    入坑scrapy在自己学习了一段时间爬虫之后(其实也就是了解了下爬虫),我就迫不及待的想学习心得东西了。 今天就入手scrapy框架 官方文档 安装安装上基本没啥大问题,缺啥补啥就行 这里我选择使用Python虚拟环境virtuale...

    scrapy 框架学习
  • 某app加密算法分析

    Hey, password is required here. a7fbab8565cf6bbb84f5578e356b215e1a835de7a145bd926381e35cc45256f4...

    某app加密算法分析
  • jni函数hook

    jni函数hook(计算 地址方式)12345678910111213141516171819202122232425262728293031323334353637function hookTest9() { Jav...

    jni函数hook
  • Hook jni 主动调用

    Hook jni 主动调用要对hellofromc 进行主动调用,修改返回值,但是这里不能直接通过replace去修改返回值,而是要通过newstringutf 去修改返回值。 1234567891011121314151617181...

    Hook jni 主动调用
  • Hook 计算非导出函数地址

    hook 读写内存数据对string字符串,可能是加密的,可以通过直接hook 加载的内存数据来读取解密状态的字符串 123456789读取内存字符串数据function hookTest7() { var soAdd...

    Hook 计算非导出函数地址
  • Hook 获取指针参数的返回值

    Hook 获取指针参数的返回值在c语言中,一般都会以指针传递返回的值 ,没有return 或者return为true hook sub_750 打印参数和输出 12345678910111213141516171819functio...

    Hook 获取指针参数的返回值
  • Hook dlopen

    hook dlopen在刚开始hook 我们必须使得app加载so 才能hook, 我们可以hookdlopen 获取到so在那加载,在高版本中有一些so会走android_dlopen_ext 1234567891011121314...

    Hook dlopen
  • Hook 导出函数和修改函数参数返回值

    Hook 导出函数123456789101112131415161718192021222324252627282930// hook 导出函数function hookTest1() { var addAddr =...

    Hook 导出函数和修改函数参数返回值
  • Hook so 导入导出表

    hook so 导入导出表启动frida打开两个cmd 窗口 12345第一个cmd窗口adb shellsucd /data/local/tmp./fx // 这个是frida-server-12.8.14-android-x86...

    Hook so 导入导出表
  • Hook Java层通杀

    Hook 通杀Hook 普通方法和修改函数参数返回值fradaserver 是手机端的, android低版本 frida 尽量低版本 fridaserver版本要与frida库版本一致 不同平台用不同fridaserver 不要和...

    Hook Java层通杀
Please check the comment setting in config.yml of hexo-theme-Annie!