Android Dex文件格式(二)
//Direct-mapped "class_def_item".
struct DexClassDef {
u4 classIdx; //类的类型, DexTypeId中的索引下标
u4 accessFlags; //访问标志
u4 superclassIdx; //父类类型, DexTypeId中的索引下标
u4 interfacesOff; //接口偏移, 指向DexTypeList的结构
u4 sourceFileIdx; //源文件名, DexStringId中的索引下标
u4 annotationsOff; //注解偏移, 指向DexAnnotationsDirectoryItem的结构
u4 classDataOff; //类数据偏移, 指向DexClassData的结构
u4 staticValuesOff; //类静态数据偏移, 指向DexEncodedArray的结构
};
struct DexClassData {
DexClassDataHeader header; //指定字段与方法的个数
DexField* staticFields; //静态字段
DexField* instanceFields; //实例字段
DexMethod* directMethods; //直接方法
DexMethod* virtualMethods; //虚方法
};
struct DexClassDataHeader {
uleb128 staticFieldsSize; //静态字段个数
uleb128 instanceFieldsSize; //实例字段个数
uleb128 directMethodsSize; //直接方法个数
uleb128 virtualMethodsSize; //虚方法个数
};
struct DexMethod {
uleb128 methodIdx; //指向DexMethodId的索引
uleb128 accessFlags; //访问标志
uleb128 codeOff; //指向DexCode结构的偏移
};
struct DexCode {
u2 registersSize; 使用的寄存器个数
u2 insSize; 参数个数
u2 outsSize; 调用其他方法时使用的寄存器个数
u2 triesSize; Try/Catch个数
u4 debugInfoOff; 指向调试信息的偏移
u4 insnsSize; 指令集个数, 以2字节为单位
u2 insns[1]; 指令集
//followed by optional u2 padding
//followed by try_item[triesSize]
//followed by uleb128 handlersSize
//followed by catch_handler_item[handlersSize]
};

| index | classIdx | accessFlags | superclassIdx | interfacesOff | sourceFileIdx | annotationsOff | classDataOff | staticValuesOff |
| 0 | 0x00 | 0x01 | 0x02 | 0x00 | 0x03 | 0x00 | 0x388 | 0x00 |
| 0_string | LHello; | public | Ljava/lang/Object; | no interfaces | Hello.java | no annotations |
DexClassData:

在程序中,一般使用32位比特位来表示一个整型的数值。不过,一般能够使用到的整数值都不会太大,使用32比特位来表示就有点太浪费了。对于普通计算机来说,这没什么问题,毕竟存储空间那么大。但是,对于移动设备来说,存储空间和内存空间都非常宝贵,不能浪费,能省就省。
DEX_INLINE int readUnsignedLeb128(const u1** pStream) {
const u1* ptr = *pStream;
int result = *(ptr++);
if (result > 0x7f) {
int cur = *(ptr++);
result = (result & );
if (cur > 0x7f) {
cur = *(ptr++);
result |= (cur & ;
if (cur > 0x7f) {
cur = *(ptr++);
result |= (cur & ;
if (cur > 0x7f) {
cur = *(ptr++);
result |= cur << ;
}
}
}
}
*pStream = ptr;
return result;
}
| index | staticFieldsSize | instanceFieldsSize | directMethodsSize | virtualMethodsSize |
| 0 | 0 | 0 | 3 | 0 |
通过对DexClassDataHeader的解析, 得到有3个直接方法, 后面紧跟的就是DexMethod结构,该结构中的u4也是uleb128编码的

| index | methodIdx | accessFlags | codeOff |
| 0 | 0x0 | 0x10001 | 0x1B0 |
| 0_string | void LHello;-><init>() | public|constructor | |
| 1 | 0x01 | 0x09 | 0x1C8 |
| 1_string | void LHello;->MyPrint(Ljava/lang/String;) | public|static | |
| 2 | 0x01(看010Editor解析此处也是0x01) | 0x09 | 0x210 |
| 2_string | 但是字符串描述也是下表为0x02的信息 | public|static |
DexMethod表中下标0中成员methonIdx所指向的Method信息:

| DexMethod_index | registersSize | insSize | outsSize | triesSize | debugInfoOff | insnsSize | insns |
| 0 | 0x01 | 0x01 | 0x01 | 0x00 | 0x372 | 0x04 | 0x70, 0x10, 0x05, 0x00, 0x00, 0x00, 0x0E, 0x00 |
| 1 | 0x04 | 0x01 | 0x03 | 0x00 | 0x377 | 0x1C | 0x62, 0x00, 0x00, 0x00, 0x22, 0x01, 0x04, 0x00, 0x70, 0x10, 0x06, 0x00, 0x01, 0x00, 0x6E, 0x20, 0x07, 0x00, 0x31, 0x00, 0x0C, 0x01, 0x1A, 0x02, 0x00, 0x00, 0x6E, 0x20, 0x07, 0x00, 0x21, 0x00, 0x0C, 0x01, 0x6E, 0x10, 0x08, 0x00, 0x01, 0x00, 0x0C, 0x01, 0x12, 0x02, 0x23, 0x22, 0x07, 0x00, 0x6E, 0x30, 0x03, 0x00, 0x10, 0x02, 0x0E, 0x00 |
| 2 | 0x03 | 0x01 | 0x02 | 0x00 | 0x380 | 0x0D | 0x1A, 0x00, 0x14, 0x00, 0x71, 0x10, 0x01, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x1A, 0x01, 0x02, 0x00, 0x6E, 0x20, 0x04, 0x00, 0x10, 0x00, 0x0E, 0x00 |
下面就开始解析这3个方法中每个方法的指令格式:


单独使用位标识还无法确定一条指令,必须通过指令格式标识来指定指令的格式编码。 它的约定如下:指令格式标识大多由三个字符组成,前两个是数字,最后一个是字母第一个数字是表示指令有多少个16位的字组成第二个数字是表示指令最多使用寄存器的个数。特殊标记“r”标识使用一定范围内的寄存器第三个字母为类型码,表示指令用到的额外数据的类型

















解析完dex之后我们有很多事都可以做了1、我们可以检测一个apk中是否包含了指定系统的api(当然这些api没有被混淆),同样也可以检测这个apk是否包含了广告,以前我们可以通过解析AndroidManifest.xml文件中的service,activity,receiver,meta等信息来判断,因为现在的广告sdk都需要添加这些东西,如果我们可以解析dex的话,那么我们可以得到他的所有字符串内容,就是string_ids池,这样就可以判断调用了哪些api。那么就可以判断这个apk的一些行为了,当然这里还有一个问题,假如dex加密了我们就蛋疼了。好吧,那就牵涉出第二件事了。2、我们在之前说过如何对apk进行加固,其实就是加密apk/dex文件内容,那么这时候我们必须要了解dex的文件结构信息,因为我们先加密dex,然后在动态加载dex进行解密即可3、我们可以更好的逆向工作,其实说到这里,我们看看apktool源码也知道,他内部的反编译原理就是这些,只是他会将指令翻译成smail代码,这个网上是有相对应的jar包api的,所以我们知道了dex的数据结构,那么原理肯定就知道了,同样还有一个dex2jar工具原理也是类似的4、 .....等等等等
Android Dex文件格式学习笔记pdf版下载:
链接: http://pan.baidu.com/s/1eR745Rs
密码: qqqk
Android Dex文件格式(二)的更多相关文章
- Android Dex文件格式(一)
dex是Android平台上(Dalvik虚拟机)的可执行文件, 相当于Windows平台中的exe文件, 每个Apk安装包中都有dex文件, 里面包含了该app的所有源码, 通过反编译工具可以获取到 ...
- dex文件格式二
一. dex文件头 (1) magic value 在DexFile.c dexFileParse函数中 会先检查magic opt 啥是magic opt呢? 我们刚刚从cache目录拷贝出来的 ...
- Android Dex文件格式解析
Dex文件是Android虚拟机下的可执行文件,包含了应用程序所用到所有操作指令和运行时数据.在程序编译过程中,java源文件先被编译成class文件,然后通过dx工具将多个class文件整合为一个d ...
- dex文件格式一
一.生成dex文件 我们可以通过java文件来生成一个简单的dex文件 编译过程: 首先编写java代码如下: (1) 编译成 java class 文件 执行命令 : javac Hello.jav ...
- dex文件格式学习
一.dex文件的生成 我们可以通过java文件来生成一个简单的dex文件 编译过程: 首先编写java代码如下: (1) 编译成 java class 文件 执行命令 : javac Hello.ja ...
- Android逆向之旅---解析编译之后的Dex文件格式
一.前言 新的一年又开始了,大家是否还记得去年年末的时候,我们还有一件事没有做,那就是解析Android中编译之后的classes.dex文件格式,我们在去年的时候已经介绍了: 如何解析编译之后的xm ...
- [Android Security] DEX文件格式分析
copy from : https://segmentfault.com/a/1190000007652937 0x00 前言 分析 dex 文件格式最好的方式是找个介绍文档,自己再写一个简单的 de ...
- Android反编译(二)之反编译XML资源文件
Android反编译(二) 之反编译XML资源文件 [目录] 1.工具 2.反编译步骤 3.重新编译APK 4.实例 5.装X技巧 6.学习总结 1.工具 1).反编译工具 apktool http ...
- Android Bug:Error:com.android.dex.DexException: Multiple dex files define Landroid/support/design/widget/CoordinatorLayout$LayoutParams;
项目编译通过,运行时出现异常: Error:com.android.dex.DexException: Multiple dex files define Landroid/support/desig ...
随机推荐
- 利用Continuous Testing实现Eclipse环境自动单元测试
当你Eclipse环境中修改项目中的某个方法时,你可能由于各种原因没有运行单元测试,结果代码提交,悲剧就可能随之而来. 所幸infinitest(http://infinitest.github.io ...
- 线程,yield让出cpu调度
public class Yield01 extends Thread { public static void main(String[] args) { new Yield01().start() ...
- SQL Server performance tips
Refer to: http://harriyott.com/2006/01/sql-server-performance-tips A colleague of mine has been look ...
- CSS3中-webkit-overflow-scrolling: touch 的使用方法详解
-webkit-overflow-scrolling 属性控制元素在移动设备上是否使用滚动回弹效果. auto 使用普通滚动, 当手指从触摸屏上移开,滚动会立即停止. touch 使用具有回弹效果的滚 ...
- android platform下载地址
大陆直接访问Android的光放网站一般情况下比较困难,特此列出了Android各个SDK版本的直接下载地址. ADT 23.0.4:https://dl.google.com/android/ADT ...
- STL学习 - map
C++中map容器提供一个键值对容器,map与multimap差别仅仅在于multiple允许一个键对应多个值. 一.map的说明 1 头文件 #include <map> 2 ...
- 解决json日期格式问题的3种方法
这篇文章主要介绍了解决json日期格式问题的3种方法 ,需要的朋友可以参考下 开发中有时候需要从服务器端返回json格式的数据,在后台代码中如果有DateTime类型的数据使用系统自带的工具类序列化后 ...
- cs11_c++_lab5待修改
heap.hh #ifndef HEAP_HH #define HEAP_HH #include <iostream> #include <stdexcept> #includ ...
- Debian7下初次尝试Nginx+Uwsgi部署Django开发环境
之前一直都用的是新浪的SAE,但是由于各种限制,各种不爽,终于下定决心开始折腾VPS,于是在搬瓦工上买了个年付VPS,开始折腾之旅. 由于对Linux一窍不通,所以不知道如何在Linux上部署开发环境 ...
- Asp.net 未处理异常
页面级捕获未处理异常 - Page 的 Error 事件 Protected Sub Page_Error(ByVal sender As Object, ByVal e As System.Even ...