01 编译简介
在学习逆向之前,我觉得很有必要了解一下编译原理。编译是将源代码转换成目标代码的过程及动作,通常是将高级语言转变成汇编语言或机器语言。
在这里,首先简单介绍一下高级语言、汇编语言以及机器语言,然后再介绍APK的编译过程,为后续逆向打下基础。
当然,编译涉及到的知识远远不止这些,这里我只是结合APK的编译过程,选择性地介绍一些需要的知识而已。避免介绍过多的编译知识,反而导致大家无法理解的情况发生。
如果有兴趣,校友们可以去查阅相关书籍,了解更多关于编译的知识。
02 编译详解
编译
编译通常涉及到三种语言:高级语言、汇编语言、机器语言。
首先大家要明确的是,计算机只能理解二进制,它并不理解用C、Java、Python等高级语言写的源代码。在我们眼里,这是相加,这是调用函数;但在计算机眼里,这就是屎。
就和之前《网络层 | 网际协议IP(1)》介绍的”点分十进制“一样,高级语言只是对人类友好,方便人类阅读而已,如果也想让计算机理解,就必须将高级语言解释成计算机能理解的机器语言,这就是编译的作用。
机器语言:二进制指令集,计算机能直接识别和执行,也被称为机器码。比如0101代表加,1010代表减等等。它与硬件结构相关,不同种类的计算机,其机器语言是不相通的。所以按某种计算机机器指令编写的程序不能在另一种计算机上执行。
由于机器语言是由一系列0和1的构成的指令代码,对人类来说,可读性差且容易出错,于是便产生了汇编语言。
汇编语言:机器语言的符号化,所以又称为符号语言。用助记符来表示机器代码,比如机器语言0101写成汇编语言就是add,这样就比机器语言更加便于记忆,也更形象。
汇编语言是面向机器的,是机器语言的符号化,因此和机器语言一样,不同的计算机有着不同的汇编语言,它的通用性和可移植性也很差。汇编代码需通过汇编器转译成机器代码才能执行。
由于汇编语言依赖于硬件,且助记符量大难记,于是人们又发明了更便于使用的所谓高级语言。
高级语言:像Java、C、C++等都是高级语言,高度封装。相对汇编语言来说,更接近自然语言和数学公式,有较高的可读性,且和计算机硬件结构关系不大,可移植性高。
一般我们都是使用高级语言编写代码。高级语言写的源代码会被编译器编译成目标代码,目标代码通常是汇编代码或者机器代码。如果编译产出的是汇编代码,则用汇编器进一步将汇编代码汇编成机器代码。
绝大部分情况,编译的“故事发展”路线大致可以简化成如下两条:
源代码——》机器代码
源代码——》汇编代码——》机器代码
但是APK走的是另外一种路线。
源代码——》字节码——》机器代码
字节码,是编译产生的中间代码,需要通过特定的虚拟机将字节码转译成物理主机的机器代码。对虚拟机来说,字节码就是虚拟机的机器码,但不是物理主机的机器码。
这样做有什么好处?不同机器,其机器代码都是不一样的。一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标语言。而将源代码编译成字节码后,只需要安装特定的软件和软件环境,就可以将其转译成机器代码。只需要编译一次,而不需要考虑平台的问题,平台的差异全部交给软件去处理。Java就是采用这种方式,因此可以”一次编译,到处运行“。
举个例子,生产红、蓝、绿三种颜色的纸张。如果采用寻常的编译方式,则需要三个车床分别生产;而采用字节码的编译方式,我只需要一个生产白色纸张的车床,然后交给第三方去染色就行了。这个例子应该很形象吧?
APK编译
目前android应用开发主流语言是Java,还有近几年被官宣的Kotlin,当然还支持其他语言,这里我们只讲Java。
首先给出APK编译打包的流程图。
这里我将APK的编译过程简化成如下:
源文件——》.class文件——》.dex文件——》打包成APK——》签名
首先是Java源文件编译成.class文件,这里大家应该是没有疑问的。因为这是Java的编译方式,Android应用是用Java写的,理所当然要经过这一步。
虽然Android应用是用Java开发,但它并没有采用JVM,而是采用了Dalvik虚拟机。
什么?JVM和Dalvik虚拟机是什么?
上文提到字节码需要特定的虚拟机去转译成机器码,JVM就是Java Virtual Machine,即Java虚拟机,用来将Java编译后的.class字节码文件转译成机器码。
而Dalvik虚拟机是用于Android平台的虚拟机,但它支持的是.dex字节码文件(这种格式更适合Android平台运行),因此需要将.class文件转换成.dex文件。dex即Dalvik Executable,Dalvik可执行文件。
将源代码转译成.dex格式后,然后同其他文件(图片、配置文件等)一起打包成APK。到这一步,APK文件已经生成了。
最后,Android应用程序需要签名才能在Android设备上安装。所以还需要对生成的APK文件签名。
当然,APK编译打包不止这五个步骤,也不止这么点细节,但我觉得了解这五个步骤差不多足够了,免得讲多了大家一头雾水。后续有需要的话,我也会适当补充的。
来源:freebuf.com 2019-05-06 10:32:52 by: noobsec
请登录后发表评论
注册