安卓逆向之 dex、so 可执行文件结构详解 (正在更新中。。。)
我们从一个最小dex文件讲起,所谓最小dex文件就是不包含任何类的文件。
我们可以将文件头看作是头部,map看作是尾巴
我们先有一个大致的印象,至于上面串表是什么东西等等的后面详细讲解
我们看一个人人都会的hello world。
public class HW { public static void main(String[] args) { System.out.println("Hello World"); } }
将helloworld编译成dex文件,深度刨析dex文件结构,小伙伴们请系好安全带。
至于操作码和指令格式见
https://source.android.google.cn/devices/tech/dalvik/dalvik-bytecode?hl=zh-tw#instructions
https://source.android.google.cn/devices/tech/dalvik/instruction-formats.html?hl=zh-tw#formats
我们再看一个真实的apk中的dex文件分析,此次不会想上次那么详细。我们只需要关注重点。
这些字段的记录在http://source.android.com/devices/tech/dalvik/dex-format.html。
ins_size | 这段代码所对应的方法的传入参数的字数
outs_size | 这段代码在调用方法时需要的传出参数空间的字数
ins_size主要是不言自明的--它是存储方法参数(包括隐含的 "this "参数,用于非静态方法)所需的32位字数。所有的参数都需要一个 "字",除了长数(J)和双数(D),它们需要两个字。
outs_size基本上是相反的。 outs_size必须被设置得足够大,以容纳方法内发生的任何方法调用的参数。
如果你想对dex文件进行编程而不必担心这样的细节,你可以考虑使用dexlib2(为smali/baksmali开发并用于读写dex文件的库)。该库在maven仓库中可用,所以如果你使用gradle/mvn的话,很容易链接到它。
stringpIDs
TYPepIDs类型索引表是 字符串列表的索引,表示所有的数据结构
字符串偏移表的索引,我们可以从类型索引表中找到字符串偏移表的位置,从而找到该字符串,该字符串就是数据结构标识符
protopIDs 函数原型
描述=返回值类型加参数类型
返回类型
参数偏移=参数个数,参数类型
FIELDpIDS 字段索引=所有字段
METHODpIDS 所有方法
prototype 参数
CLASSpDEFS 本类定义或者叫类申明,指向累数据
CODE 函数调用
TYPEpLIST 类型列表 参数列表 包含参数个数和类型
String
Data 数据类型,函数名称,可打印字符串
CLASSpDATA 类数据。定义类中包含的元素
map是之前段的索引,属于冗余信息
偏移是文件开始的相对位置,索引是数组的下标
#dex里面的字符串和数据类型是单独定义的
public class HelloWorld { //类定义
public static void main(String[] args) {//类数据,函数原型
System.out.println("Hello World"); //代码
}
}
两个方法
stringpIDs
字符串堆-偏移表(ascii码表排序)-偏移表的偏移和偏移表的个数
TYPepIDs类型索引表是 字符串列表的索引,表示所有的数据结构
字符串偏移表的索引,我们可以从类型索引表中找到字符串偏移表的位置,从而找到该字符串,该字符串就是数据结构标识符
protopIDs 函数原型
描述=返回值类型加参数类型
返回类型
参数偏移=参数个数,参数类型
FIELDpIDS 字段索引=所有字段
METHODpIDS 所有方法
prototype 参数
CLASSpDEFS 本类定义或者叫类申明,指向累数据
CODE 函数调用
TYPEpLIST 类型列表 参数列表 包含参数个数和类型
String
Data
CLASSpDATA 类数据。
偏移是文件开始的相对位置,索引是数组的下标
#dex里面的字符串和数据类型是单独定义的
public class HelloWorld { //类定义 public static void main(String[] args) {//类数据,函数原型 System.out.println("Hello World"); //代码 } }
so文件等到有时间了再说