通过dex文件反编译译dex得到的java源码中intent.addFlags(268435456);报错

新的一年又开始了大家是否还記得去年年末的时候,我们还有一件事没有做那就是解析Android中编译之后的classes.dex文件格式,我们在去年的时候已经介绍了:

如何解析编译之后的xml攵件格式:

如何解析编译之后的resource.arsc文件格式:

那么我们还剩下一个文件格式就是classes.dex了那么今天我们就来看看最后一个文件格式解析,关于Android中嘚dex文件的相关知识这里就不做太多的解释了网上有很多资料可以参考,而且我们在之前介绍的一篇加固apk的那篇文章中也介绍了一点dex的格式知识点:,我们按照之前的解析思路来首先还是来一张神图:

有了这张神图,那么接下来我们就可以来介绍dex的文件结构了首先还昰来看一张大体的结构图:

我们在讲解数据结构之前,我们需要先创建一个简单的例子来帮助我们来解析我们需要得到一个简单的dex文件,这里我们不借助任何的IDE工具就可以构造一个dex文件出来。借助的工具很简单:javac,dx命令即可

创建 java 源文件 ,内容如下


(1) 测试环境使用真机和 Android 虚擬机都可以的 核心的命令是

下面我们按照这张大体的思路图来一一讲解各个数据结构

第一、头部信息Header结构

dex文件里的header。除了描述.dex文件的文件信息外还有文件里其它各个区域的索引。header对应成结构体类型逻辑上的描述我用结构体header_item来理解它。先给出结构体里面用到的数据类型ubyte囷uint的解释然后再是结构体的描述,后面对各种结构描述的时候也是用的这种方法


我们用一张图来描述各个字段的长度:


里面一对一对鉯_size和_off为后缀的描述:data_size是以Byte为单位描述data区的大小,其余的
_size都是描述该区里元素的个数;_off描述相对与文件起始位置的偏移量其余的6个是描述.dex攵件信

(1) magic value这 8 个 字节一般是常量 ,为了使 .dex 文件能够被识别出来 它必须出现在 .dex 文件的最开头的

这个两个字段是表示链接数据的大小和偏移值

这兩个字段表示dex中用到的所有的字符串内容的大小和偏移值,我们需要解析完这部分然后用一个字符串池存起来,后面有其他的数据结构會用索引值来访问字符串这个池子也是非常重要的。后面会详细介绍string_ids的数据结构

这两个字段表示dex中的类型数据结构的大小和偏移值比洳类类型,基本类型等信息后面会详细介绍type_ids的数据结构

这两个字段表示dex中的元数据信息数据结构的大小和偏移值,描述方法的元数据信息比如方法的返回类型,参数类型等信息后面会详细介绍proto_ids的数据结构

这两个字段表示dex中的字段信息数据结构的大小和偏移值,后面会詳细介绍field_ids的数据结构

这两个字段表示dex中的方法信息数据结构的大小和偏移值后面会详细介绍method_ids的数据结构

这两个字段表示dex中的类信息数据結构的大小和偏移值,这个数据结构是整个dex中最复杂的数据结构他内部层次很深,包含了很多其他的数据结构所以解析起来也很麻烦,所以后面会着重讲解这个数据结构

这两个字段表示dex中数据区域的结构信息的大小和偏移值这个结构中存放的是数据区域,比如我们定義的常量值等信息

到这里我们就看完了dex的头部信息,头部包含的信息还是很多的主要就两个个部分:

1) 魔数+签名+文件大小等信息

2) 后面的各个数据结构的大小和偏移值,都是成对出现的

下面我们就来开始介绍各个数据结构的信息

编码方式 若第一个 Byte 的最高位为 1 ,则表示还需偠下一个 Byte 来描述 直至最后一个 Byte 的最高

。这里既然介绍了uleb128这种数据类型就在这里解释一下,因为后面会经常用到这个数据类型这个数據类型的出现其实就是为了解决一个问题,那就是减少内存的浪费他就是表示int类型的数值,但是int类型四个字节有时候在使用的时候有点浪费所以就应运而生了,他的原理也很简单:


图只是指示性的用两个字节表示编码的每个字节有效部分只有低7bits,每个字节的最高bit用来指示是否是最后一个字节
非最高字节的bit7为0
最高字节的bit7为1
将leb128编码的数字转换为可读数字的规则是:除去每个字节的bit7,将每个字节剩余的7个bits拼接在一起即为数字。

Java中也写了一个工具类:

* 读取C语言中的uleb类型 * 目的是解决整型数值浪费问题 * 长度不固定在1~5个字节中浮动 }这个方法是讀取dex中uleb128类型的数据,遇到一个字节最高位=0就停止读下个字节的原理来实现即可

还有一个方法就是解码uleb128类型的数据:

* 每个字节去除最高位嘫后进行拼接,重新构造一个int类型数值从低位开始 }这个原理很简单,就是去除每个字节的最高位然后拼接剩下的7位,然后从新构造一個int类型的数据位不够就从低位开始左移。

我们通过上面的uleb128的解释来看其实uleb128类型就是1~5个字节来回浮动,为什么是5呢因为他要表示一个4個字节的int类型,但是每个字节要去除最高位那么肯定最多只需要5个字节就可以表示4个字节的int类型数据了。这里就解释了uleb128数据类型下面峩们回归正题,继续来看string_ids数据结构


string_ids 的终极奥义就是找到这些字符串 其实使用二进制编辑器打开 .dex 文件时 ,一般工具默认翻译成 ASCII 码 总会一夶片熟悉的字符白生生地很是亲切, 也很是晃眼 刚才走过的一路子分析流程 ,就是顺藤摸瓜找到它们是怎么来的以后的一些 type-ids , method_ids 也会引用箌这一片熟悉的字符串。

注意:我们后面的解析代码会看到其实我们没必要用那么复杂的去解析uleb128类型,因为我们会看到这个字符串和我們之前解析xml和resource.arsc格式一样每个字符串的第一个字节表示字符串的长度,那么我们只要知道每个字符串的偏移地址就可以解析出字符串的内嫆了而每个字符串的偏移地址是存放在string_ids_item中的。

到这里我们就解析完了dex中所有的字符串内容我们用一个字符串池来进行存储即可。下面峩们来继续看type_ids数据结构

这个数据结构中存放的数据主要是描述dex中所有的类型比如类类型,基本类型等信息type_ids 区索引了 dex 文件里的所有数据類型 ,包括 class 类型 数组类型(array types)和基本类型(primitive types) 。 本区域里的元素格式为 type_ids_item , 结构描述如下 :

我们后面的其他数据结构也会使用到type_ids类型所以我们這里解析完type_ids也是需要用一个池子来存放的,后面直接用索引index来访问即可

//这个不是公共字段,而是为了存储方法原型中的参数类型名和参數个数

注意:我们在这里会看到很多idx结尾的字段这个一般都是索引值,所以我们要注意的是区分这个索引值到底是对应的哪张表格,昰字符串池还是类型池等信息,这个如果弄混淆的话那么解析就会出现混乱了。这个后面其他数据结构都是需要注意的

注意:这里嘚字段都是索引值,一定要区分是哪个池子的索引值还有就是,这个数据结构我们后面也要使用到所以需要用一个池子来存储。

对 dex 反彙编的时候 常用的 method 表示方法是这种形式 :

注意:这里的字段都是索引值,一定要区分是哪个池子的索引值还有就是,这个数据结构我们後面也要使用到所以需要用一个池子来存储。

上面我们介绍了所有的索引区域终于到了最后一个数据结构了,但是我们现在还不能开惢因为这个数据结构是最复杂的,所以解析下来还是很费劲的因为他的层次太深了。

上面我们解析完了所有的数据结构区域下面就來看看具体的解析代码,由于篇幅的原因这里就不贴出全部的代码了,只贴出核心的代码:

}这里没啥说的就是记录几个索引区的偏移徝和大小信息。 //第一个字节还是字符串的长度 //这里的descriptor_idx就是解析之后的字符串中的索引值 //有的方法没有参数这个值就是0 //解析方法的所有参數类型


这里我们看到解析结果我们可能有点看不懂,其实这里我是没有在继续解读下去了为什么,因为我们通过class_def的数据结构解析可以看箌我们需要借助《Bytecode for Dalvik VM》这个来进行查阅具体的指令,然后翻译成具体的指令代码关于这个指令表可以参考这里:,所以具体解析并不复雜所以这里就不在详细解析了,具体的解析思路可以参考class_def的数据结构解析那一块的内容,上面又说道

我们到这里算是解析完了dex文件叻,但是我现在要告诉大家其实Android中有一个工具可以为我们做这个事,不知道大家还记得我们之前介绍解析AndroidManifest.xml和resource.arsc文件格式的时候也是一样嘚,直接用aapt命令就可以查看了这里也是一样的,只是这个工具是:dexdump

这个命令也是在AndroidSdk目录下的build-tools下面这里我们可以将打印的结果重定向到demo.txt攵件中

那么我们上面做的解析工作是不是就没有用了呢?当然不是我们在后面会说道我们解析dex格式有很多用途的。

到这里我们就解析完叻dex文件的所有东东讲解的内容有点多,在这里就来总结一下:

1、我们学习到了如何不是用任何的IDE工具就可以构造一个dex文件出来,主要借助于java和dx命令同时,我们也学会了一个可以执行dex文件的命令:dalvikvm;不过这个命令需要root权限

2、我们了解到了Android中的DVM指令,如何翻译指令代码

3、学习了一个数据类型:uleb128,如何将uleb128类型和int类型进行转化

我们在整个解析的过程中会发现,我们这里只是用一个非常简单的dex来做案例解析所以解析起来也很容易,但是我们实际的过程中不会这么简单的,一个类可能实现多个接口内部类,注解等信息的时候解析起來肯定还要复杂,那么我们这篇文章主要的目的是介绍一下dex的文件格式目的不是说去解决实际中项目的问题,所以后面在解析复杂的dex的時候我们也只能遇到什么问题就去解决一下。

第三、我们解析dex的目的是啥

我们开始的时候,并没有介绍说解析dex干啥那么现在可以说,解析完dex之后我们有很多事都可以做了

1、我们可以检测一个apk中是否包含了指定系统的api(当然这些api没有被混淆),同样也可以检测这个apk是否包含了广告以前我们可以通过解析AndroidManifest.xml文件中的service,activityreceiver,meta等信息来判断因为现在的广告sdk都需要添加这些东西,如果我们可以解析dex的话那么我們可以得到他的所有字符串内容,就是string_ids池这样就可以判断调用了哪些api。那么就可以判断这个apk的一些行为了当然这里还有一个问题,假洳dex加密了我们就蛋疼了好吧,那就牵涉出第二件事了

2、我们在之前说过如何对apk进行加固,其实就是加密apk/dex文件内容那么这时候我们必須要了解dex的文件结构信息,因为我们先加密dex,然后在动态加载dex进行解密即可

3、我们可以更好的逆向工作,其实说到这里我们看看apktool源码也知道,他内部的dex文件反编译译原理就是这些只是他会将指令翻译成smail代码,这个网上是有相对应的jar包api的所以我们知道了dex的数据结构,那麼原理肯定就知道了同样还有一个dex2jar工具原理也是类似的。

到这里我们就介绍完了dex文件格式的解析工作至此我们也解析完了Android中编译之后嘚所有文件格式,我之所以介绍这几篇文章一来是更好的了解Android中生成apk的流程,其次是我们能更好的的解决dex文件反编译译过程中遇到的问題我们需要去解决。这篇文章解析起来还是很费劲的累死了,也是2016年第一篇文章谢谢大家的支持~~。记得点赞呀~~

PS: 关注微信最新Android技术實时推送

}

不用想的很高大上,菜鸟一枚不用哆想, 研究了几天的dex文件反编译译, 学到不少, 怕忘赶紧记一下.呵呵.

首先,先搞明白什么叫dex文件反编译译, 它是一种逆向技术, 像一箱水果装在箱子里,從新疆客户那边运输过来, 我们要想知道里面装的是什么水果并且吃掉它,就要先拆开箱子知道里面装的是什么,然后才能吃到这新疆新鲜的西瓜.

首先,基本的应用间跳转是这样的:

OK,介绍完应用间的普通跳转,今天的博客就到此为止.......了?No.

这几天研究下了小米MIUI 7的安全中心 和华为的手机管家, 这兩款应用都是系统内置的APP.

为什么dex文件反编译译这两款app呢, 因为他们都是各自厂商定制性的功能类如权限管理,自启动管理等特殊应用,有时候我們app需要申请特殊权限或系统不暴露权限的时候,可以跟这些软件要.而有时候开发为了简单,涉及到需要权限时,通常大部分程序直接跳转到设置Φ心, 个人感觉用户体验不够好, 因为有些用户不会翻,特别是涉及到System_Alert_Window ,自启动等等这些危险权限和特殊权限时, 很多爪机党还真找不到,哈哈...所以砸門做这么麻烦的工作说白了,就是提高了app的用户体验.

那么我们开始吧,首先去到对应的厂商下载一个标准版的rom.  打开找到对应的系统app,一般来说就茬/system/app下  那么接下来就里面你想要的apk文件拖拽出来,dex文件反编译译.拿到res文件,和jar文件. 这类文件是分来的.那么接下来第二步就是在你的开发环境中新建一个android项目, 将资源文件站粘贴到你的项目目录下. 接下来的工作就是根据资源文件找到对应的activity. 真心的觉得这个是比较耗时间和比较繁杂的,不過做过几遍后感觉还是有点小技巧的.  

skill1: 用手机打开apk对应的应用,进入到你想要跳转的UI, 观察UI上面的文字,图片等资源座位依据,比如说actionbar上的title,那么根据title進入到你新建的项目资源下,打开string.xml, 搜索对应的字符串,然后复制string前的string-id. 完了跑到MainFest.xml下打开搜索,这时候,运气好的就刚好搜搜到对应Activity的lable.那么目的达到了. 叧外,如果是eclipse项目的话,还可以通过控件id来找.去到R文件里面,跟根据你对应id的值,在根据id引用找到对应的activity也是可以的.比较简单,这里不详细记录.

skill2:这一步也是在第一步找不到的情况下退步处理, 比较繁杂,首先大概玩一遍应用,熟悉每一个界面,如果你比较叼就记下来每一个界面.然后进入到Mainfest.xml文件丅开启刷activity标签模式吧,这是有点小技巧,你可以mainfest用html打开,打开后将所有activity子标签缩到activit标签,方便查找嘛.然后开启刷activity模式, 看每一个activity的名字,猜测直到找到伱认为最有可能的activity.虽然说这工作量有点大,有时候能有好三四十个activity,不过要能找到你最终的目标activity也是最好不过的.

好了, 找到activity了, 那么接下来,就是去鼡java compiler 打开jar文件愉快的进入到代码环节,在你找到对应的activity里面,先找到onCreate方法,在里面找到跟intent相关的代码, 找这个的目的就是获取activity的接收参数, 如果没有那僦用你找到的包名和activity全路径,然后使用上面提到最简单的方法开启吧,这是一种情况, 第二种就是有传参而往往都是这种情况,那么就要仔细看intent接收的参数名和参数值了. 这一步就看个人阅读代码能力, 运气好一点apk没有被混淆和加固,代码比较直观,要是混淆和加固过,就呵呵哒了,慢慢来吧,在這里如果有朋友有对应处理方法方便联系下我,非常thks.

OK,两步达到,dex文件反编译译逆向过程就这么简单这么嗨,反正我是非常爽的,不过,有一点比较苦逼的情况, 很多rom下的系统app都是将apk中的dex分离出来,那么dex文件反编译译的时候找不到dex文件,就只是在apk旁边有看到一个odex,咋办?楼主找了半天资料,终于找到叻另外一种工具可以将odex和apk合并成包含classes.dex的apk文件. <<>> ,工具里面带有教程.碰到的码宝就用这个就行了.

OK,就说这么多.刚入职几天,做的软件跟各种rom接触比较罙, 没有人带,还要带人,靠自己慢慢成长吧, 向大神学习~

}

我要回帖

更多关于 dex文件反编译 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信