用python一步步解剖dex文件(一)

请勿转载,谢谢!!! 



目标

这里的dex文件,就是android中dalvik虚拟机运行的程序格式文件;art虚拟机,也是基于dex格式再创作的。

我们的目标,就是直观的了解下,这个dex到底是什么东东。


知识点

在开始之前,先熟悉python的两个知识点:

1. mmap

2. struct

这两个是python中的内置模块,分别是映射文件和结构化操作。

mmap

了解linux的是不是感觉很亲切?是的,功能是类似的,把一个文件映射到一段内存,然后操作内存就像直接读写文件一样。

创建的格式:

mmap函数原型

例如:

mmap调用示例

使用更简单,可以直接操作数组:

直接读写

更详细介绍参考:

http://blog.csdn.net/zdy0_2004/article/details/53200250

对linux的mmap感兴趣的可以参考:

http://ju.outofmemory.cn/entry/224106

struct

struct是对二进制流进行操作的一个模块,直译就是数据结构,很像c语言中的结构体struct声明。它提供了从二进制流读取数据(unpack),和把数据写入二进制流的方法(pack)。

使用示例:


静态方法调用

其中'<L',指定了要从数据流中读取的格式,第二个参数则是数据流的对应位置。

格式对应表如下:

struct格式对应表

还可以指定字节顺序:

struct字节序

除此外,还可以指定缓冲区,这里不介绍,参考:

https://www.cnblogs.com/coser/archive/2011/12/17/2291160.html


DEX文件格式

言归正传,我们的目标是dex文件。

文件结构:

dex文件结构

文件头结构

文件头固定0x70长度,也就是112个字节。

其中signature计算的范围是整个文件除去magic, checksum和signature三部分的其余所有部分。

checksum计算的范围是除去magic和checksum两部分的其余所有部分。

magic是dex文件标识,固定为'dex\n035'

其余大部分字段,都是在划分区域,通过(size, off)的方式,就是圈定文件的[off, off+size]部分为相关段的数据;后续的索引,也是建立在这个基础上的。

dex文件头

索引区结构

索引区有五大区域,分别是字符串区域,类名区域,函数原型区域,类属性区域,方法区域。其中每个区域的范围,可以通过头部的信息获取到,[off, size]。

这五个区域,是有相互关系的,一个区域记录的往往是另一个区域的索引。

字符串区域

从下图看,就是每四个字节是一项,这四个字节代表的是真实字符串的偏移值。

字符串区域结构

如果把这个数值作为文件的偏移值,相关的内存是这样的:

其中size是字符串的长度,str是size大小的一串字符。

字符串真实值

类名区域

这个区域存储的是所有的类名索引,结构如下,每一项用4个字节存储,表示字符串区域的索引;这里就已经有两重索引了,一重似乎类索引包含的字符串索引,一重是字符串本身的索引。

类名索引结构

函数原型区域

这个区域存储的是所有函数的原型汇总,每个原型由三部分组成,(名称,返回类型,参数类型),当然它们存储的都是索引数值。

其中名称的索引是字符串区域的索引,返回类型是类名区域的索引,而参数类型则导向另一个地方,它存储的是一个偏移数值。

函数原型结构

这个偏移数值最终导向的结构,是一个数组列表结构,由[size, itemlist]格式组成,其中size是参数的总个数,itemlist就是size大小的参数列表,列表的每一项又是一个索引数,指向类名区域的索引。

也就是说,这个结构其实就是size大小的一个类名数组,也就是我们要找寻的参数类型。

函数原型导向结构

方法区域

方法结构相比原型要简单很多,也是三部分组成,(类名,函数原型,方法名),当然也都是存的索引数值。

其中类名是指向类名区域的索引,函数原型是指向函数原型区域的索引,方法名是指向字符串区域的索引。

方法结构

类属性区域

类的属性和类的方法是相似的,由三部分组成(类名,字段类型,名称),也都是存储的索引数值;

其中类名是指向类名区域的索引,字段类型是指向类名区域的索引,名称则是指向字符串区域的索引。

类属性结构

结构先分析到这里为止,接下来我要把这些结构对应的数据都打印出来。


DEX解析库

首先分享一个现有的python库:

https://github.com/bunseokbot/dexparser

这个库是两年前写的,非常简洁明了。

其实关于dex解析的库还是很多的,我比较喜欢这个库的直观性,说到底是解析Dex的文件格式,这种c风格的写法,非常浅显易懂,直接触摸到文件结构。也因为它的简单,在它的基础之上,我们可以继续做扩充。

这个dexparser库利用了mmap和struct模块,对dex文件做解析。

画风是这样的:

初始化和解析文件头

这样的:

文件头数据赋值

还有这样的:

读取字符串列表

这里用struct,直接从dex文件的映射区域self.mmap中,通过索引读出数据,然后根据结构说明继续转索引或者直接使用。

上面的string_list代码,首先锁定了string索引的区域,[string_ids_size, string_ids_off],也就是索引的总数是string_ids_size大小;

然后根据这个大小遍历,分别从区域相关位置中取出某一个字符串的索引off;

接着,通过这个偏移数值定位到字符串真实数据的区域self.mmap[off],并根据格式[size, char]进行读取;

最后就形成了一个字符串的队列。

dexparser模块中的其它函数也是类似的。


解析和打印

现在用这个库,我要把前面介绍的文件头和索引区域的五大区域都打印出来。

构建一个Dexparser对象

(自己解压一个Apk,拿出其中的dex作为测试用)

初始化

打印文件头

打印文件头(代码)

画风是这样的:

打印文件头(结果)

打印字符串列表

打印字符串(代码)

画风是这样的:

打印字符串(结果)

打印类名列表

打印类名列表(代码)

画风是这样的:

打印类名列表(结果)

打印函数原型列表

如下图所示,Dexparser中提供的列表其实只有索引,我在这里进一步做了补充,根据函数原型的结构,将参数原型的描述也解析了出来。

打印函数原型(代码)

画风是这样的:

其中,函数名的部分我用了'%s'来替代,是为了后面解析方法区域时用的。

打印函数原型(结果)

打印方法列表

下图中就用到了上面函数原型列表中的'%s',把函数名称填写进去。

打印方法列表(代码)

画风是这样的:

打印方法列表(结果)

打印类属性列表

打印类属性列表(代码)

画风是这样的:

打印类属性列表(结果)

保存信息

最后,把打印出来的五大索引区域的列表信息,都保存到文件中。

保存到文件



【未完待续】


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容

  • 什么是dex文件 他是Android系统的可执行文件,包含应用程序的全部操作指令以及运行时数据。 由于dalvik...
    SmileUsers阅读 33,860评论 3 53
  • ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。 O...
    我想起个好名字阅读 5,307评论 0 9
  • 什么是dex文件 他是Android系统的可执行文件,包含应用程序的全部操作指令以及运行时数据。 由于dalvik...
    _枫_阅读 2,734评论 0 2
  • 咄咄逼人 “抱歉,我不应该直接让女生看这么血腥的照片……”陆启文故意的说:“虽然你看起来完全没有被吓到。” 缪笑没...
    花京体验阅读 153评论 0 0
  • 林先生用温暖平实的语言为我们娓娓道来他的处事哲学。即心有欢喜过生活。因为这漫长的一生总有苦难在其中,不如将其当作惊...
    有一种春日叫早早阅读 3,226评论 5 8