如何解释dalvik字节码
文档:
在Android系统源码目录dalvikdocs有相关指令文档
dalvik-bytecode.html
实战:
来直接实战模拟来理解枯燥的理论
用IDA打开一个dex文件, 设置显示指令
随便找一段代码
注意:
206E 28DE 0050是IDA的显示问题 在文件中的存储顺序是
6E 20 DE 28 50 00
在WinHex搜索一下就知道了
上面截图的指令在文件中的排列顺序如下:
14 05 09 00 09 01
6E 20 DE 28 50 00
6E 20 81 29 04 00
6E 30 83 29 34 07
.....
我们分别对如上3个条指令做解释
1. 14 05 09 00 09 01
14 为操作码 (opcode) 去文档查询
3li表示
第1个数字3表示指令由3个16位字组成
第2个数字1表示该条指令使用到1个寄存器
第3个字母i表示后面有一个32位立即数
所以我们可以知道,这条指令一共有6个字节 其中4个字节是立即数
此时你肯定有疑问i哪里来的?
助记符 | 位大小 | 说 明 |
b | 8 | 8位有符号立即数 |
c | 16,32 | 常量池索引 |
f | 16 | 接口常量(仅对静态链接格式有效) |
h | 16 | 有符号立即数(32位或64位数的高值位,低值位为0) |
i | 32 | 立即数,有符号整数或32位浮点数 |
l | 64 | 立即数,有符号整数或64位双精度浮点数 |
m | 16 | 方法常量(仅对静态链接格式有效) |
n | 4 | 4位的立即数 |
s | 16 | 短整型立即数 |
t | 8, 16, 32 | 跳转,分支 |
x | 0 | 无额外数据 |
没错文档中后面的字母就可以查询上表的助记符
指令格式为: const VAA, #+BBBBBBBB
那么现在, 嗯! 又有一些很操蛋的约定了
● 每16位的字采用空格分隔开来。
● 每个字母表示4位,每个字母按顺序从高字节开始,排列到低字节。每4位之间可能使用竖线 “|” 来表示不同的内容。
● 顺序采用 A ~ Z 的单个大写字幕作为一个4位的操作码,op表示一个8位的操作码。
● “Φ” 来表示这字段所有位为0值
● 每条指令从操作码开始,后面紧跟参数,参数个数不定,每个参数之间采用逗号分开。
● 每条指令的参数从指令第一部分开始,op位于低8位,高8位可以是一个8位的参数,
也可以是两个4位的参数,还可以为空,如果指令超过16位,则后面部 分一次作为参数
● 如果参数采用 “vX” 的方式表示,表示它是一个寄存器,如v0、v1等。
这里采用v而不用r是为了避免与基于该虚拟机架构本身的寄存器名字产生冲突,如ARM架构寄存器命名采用r开头。
● 如果参数采用 “#+X” 的方式表示,表明它是一个常量数字。
● 如果参数采用 “+X” 的方式表示,表明它是一个相对指令的地址偏移。
● 如果参数采用 “kind@X” 的方式表示,表明它是一个常量池的索引值。其中kind表示常量池类型,它可以是
“string” 字符串常量池索引
“type” 类型常量池索引
“field 字段常量池索引
“meth” 方法常量池索引
那么对于上面的指令 const VAA, #+BBBBBBBB
const op操作码
VAA 8位来描述这个寄存器
#+BBBBBBBB 常量数值
于是有
14 | 05 | 09 00 09 01 |
op | 寄存器下标 | 立即数 |
const | V5 | 0x01090009 |
最后翻译出指令 const V5, 0x01090009
2 .6E 30 83 29 34 07
同样的方法:
拿着6E查询dalvik-bytecode.html得到如下信息
指令格式下标为35c,拿着指令下表查询instruction-formats.html得到
对于6E 30 83 29 34 07
op = 6E
A = 3
B = 0
CCCC = 83 29
D = 4
E = 3
F = 7
G = 0
于是翻译成指令有
invoke-virtual {v4, v3, v7} kind@8329