android内部dex解析,Android学习心得(16) --- Dex文件结构范例解析(2)

我在博客上发表一些我的Android学习心得,希望对大家能有帮助。

这一篇我们讲述一下通过一个实例来分析dex文件结构和组成。

参考Leb128数据类型 Android学习心得(5) --- dex数据类型LEB128

参考实例分析学习理解dex文件结构Android学习心得(15) --- Dex文件结构解析(1)

参考baksmali工具使用Android学习心得(4) --- MAC下smali文件编写与运行

1、编译

我们通过一个例子来分析dex文件的构成

创建一个Hello.java文件,输入下面的值,这个是我们学习的样本

public class Hello {

public static void main(String[] argc) {

System.out.println("Hello world");

}

}

通过编译成.class文件之后再编译成.dex文件

083059164.jpg

083059165.jpg

使用0xED打开进行查看

083059166.jpg

2、Header

我们通过前一张中Dex Header解析

通过dex文件中前0x70的header数据查询并填入表格

前0x70数据

083059167.jpg

083059168.jpg

083059169.jpg

3、MapList

在Header中MapOff指向的是MapList结构

MapList结构第四节中已经定义,我们查询并填写表格

map_off中偏移地址为0x0240,查询相应地址

第一个16位是MapItem的数目:0x000D(14个)

083059170.jpg

083059171.jpg

4、string_id_item

首先我们查看MapList中string_id_item,size是14个,从0x70开始

083059172.jpg

我们分别从0x176、0x17E等读取出14个字符串,并填入表格

083059173.jpg

5、type_id_item

我们查看MapList中type_id_item,个数是7个,从0xA8开始

083059174.jpg

由于这个是表示stringids的索引,查string_id_item表得出

083059175.jpg

6、proto_id_item

查看proto_id_item,个数是3个,从0xC4开始

083059176.jpg

通过查看proto_id_item结构,填入表格

083059177.jpg

7、field_id_item

我们查看MapList中field_id_item,个数是1个,从0xE8开始

083059178.jpg

通过查看field_id_item结构,填入表格

083059179.jpg

8、method_id_item

我们查看MapList中method_id_item,个数是4个,从0xF0开始

083059180.jpg

通过查看上一节中对method_id_item描述,填入表格

083059181.jpg

9、class_def_item

我们查看MapList中class_def_item,个数是1个,从0x110开始

083059182.jpg

通过上一节中DexClassDef结构,我们填写表格

083059183.jpg

我们查看MapList中class_def_item,的确偏移地址和个数都相同。

083059184.jpg

由于DexClass.h定义的u4是属于Leb128

083059185.jpg

下面紧跟的是两个直接方法

083059186.jpg

第一个是00 81 80 04 B0 02

083059187.jpg

从0x130开始分析code_item结构

083059188.jpg

083059189.jpg

分析思路整理如下

(1) 《Dalvik VM Instruction Format》 里操作符 op 都是位于首个 16bit 数据的低 8 bit

起始的是 op = 0x70

(2) 在 《Bytecode for Dalvik VM》 里找到对应的 Syntax 和 format 。

syntax = invoke-direct

format = 0x35c

(3) 在《Dalvik VM Instruction Format》里查找 35c , 得知 op = 0x70 的指令占据 2 个 16 bit 数据 ,

格式是 B|A|op CCCC G|F|E|D ,其中,B=1,A=0。

我们查询到: [B=1] op {vD}, kind@CCCC

有上述得出CCCC = 3,D = 0;

0E操作码是对应的是return-void

得到指令是:

invoke-direct {v0}, Ljava/lang/Object;.:()V

return-void

第二个是01 09 C8 02

083059190.jpg

从0x148开始分析code_item结构

083059191.jpg

083059192.jpg

分析思路整理如下

(1) 《Dalvik VM Instruction Format》 里操作符 op 都是位于首个 16bit 数据的低 8 bit

起始的是 op = 0x62

(2) 在 《Bytecode for Dalvik VM》 里找到对应的 Syntax 和 format 。

syntax = sget-object

format = 0x21c

(3) 在《Dalvik VM Instruction Format》里查找 21c , 得知 op = 0x62 的指令占据 2 个 16 bit 数据 ,

格式是 AA|op BBBB ,其中,AA=00,BBBB=0。

得到指令是:

sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;

继续进行

(1) 《Dalvik VM Instruction Format》 里操作符 op 都是位于首个 16bit 数据的低 8 bit

起始的是 op = 0x1A

(2) 在 《Bytecode for Dalvik VM》 里找到对应的 Syntax 和 format 。

syntax = const-string vAA, string@BBBB

format = 0x21c

(3) 在《Dalvik VM Instruction Format》里查找 21c , 得知 op = 0x1A 的指令占据 2 个 16 bit 数据 ,

格式是 onst-string vAA, string@BBBB ,其中,AA=01,BBBB=1。

得到指令是:

const-string v1, "Hello World!"

继续进行

(1) 《Dalvik VM Instruction Format》 里操作符 op 都是位于首个 16bit 数据的低 8 bit

起始的是 op = 0x6E

(2) 在 《Bytecode for Dalvik VM》 里找到对应的 Syntax 和 format 。

syntax = invoke-virtual

format = 0x35c

(3) 在《Dalvik VM Instruction Format》里查找 21c , 得知 op = 0x6E 的指令占据 2 个 16 bit 数据 ,

格式是 B|A|op CCCC G|F|E|D,其中,B=2, CCCC=2, E=1, D=0。

其格式为:[B=2] op {vD, vE}, kind@CCCC

得到指令是:

invoke-virtual {v0, v1}, Ljava/io/PrintStream; -> println(Ljava/lang/String;)V

return-void

最终分析核心代码

invoke-direct {v0}, Ljava/lang/Object;.:()V

sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;

const-string v1, "Hello World!"

invoke-virtual {v0, v1}, Ljava/io/PrintStream; ->println(Ljava/lang/String;)V

return-void

对比baksmali文件生成smali文件

.class public LHello;

.super Ljava/lang/Object;

.source "Hello.java"

# direct methods

.method public constructor ()V

.registers 1

.prologue

.line 1

invoke-direct {p0}, Ljava/lang/Object;->()V

return-void

.end method

.method public static main([Ljava/lang/String;)V

.registers 3

.prologue

.line 3

sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;

const-string v1, "Hello world!"

invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V

.line 4

return-void

.end method

核心代码相同,分析正确。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值