移动安全 | 逆向基础

编译简介

       在学习逆向之前,我觉得很有必要了解一下编译原理。编译是将源代码转换成目标代码的过程及动作,通常是将高级语言转变成汇编语言或机器语言。

       在这里,首先简单介绍一下高级语言、汇编语言以及机器语言,然后再介绍APK的编译过程,为后续逆向打下基础。

       当然,编译涉及到的知识远远不止这些,这里我只是结合APK的编译过程,选择性地介绍一些需要的知识而已。避免介绍过多的编译知识,反而导致大家无法理解的情况发生。

       如果有兴趣,校友们可以去查阅相关书籍,了解更多关于编译的知识。

编译详解

编译

       编译通常涉及到三种语言:高级语言、汇编语言、机器语言。

       首先大家要明确的是,计算机只能理解二进制,它并不理解用C、Java、Python等高级语言写的源代码。在我们眼里,这是相加,这是调用函数;但在计算机眼里,这就是屎。

       就和之前《网络层 | 网际协议IP(1)》介绍的”点分十进制“一样,高级语言只是对人类友好,方便人类阅读而已,如果也想让计算机理解,就必须将高级语言解释成计算机能理解的机器语言,这就是编译的作用。

       机器语言:二进制指令集,计算机能直接识别和执行,也被称为机器码。比如0101代表加,1010代表减等等。它与硬件结构相关,不同种类的计算机,其机器语言是不相通的。所以按某种计算机机器指令编写的程序不能在另一种计算机上执行。

       由于机器语言是由一系列0和1的构成的指令代码,对人类来说,可读性差且容易出错,于是便产生了汇编语言。

       汇编语言:机器语言的符号化,所以又称为符号语言。用助记符来表示机器代码,比如机器语言0101写成汇编语言就是add,这样就比机器语言更加便于记忆,也更形象。

       汇编语言是面向机器的,是机器语言的符号化,因此和机器语言一样,不同的计算机有着不同的汇编语言,它的通用性和可移植性也很差。汇编代码需通过汇编器转译成机器代码才能执行。

       由于汇编语言依赖于硬件,且助记符量大难记,于是人们又发明了更便于使用的所谓高级语言。

       高级语言:像Java、C、C++等都是高级语言,高度封装。相对汇编语言来说,更接近自然语言和数学公式,有较高的可读性,且和计算机硬件结构关系不大,可移植性高。

       一般我们都是使用高级语言编写代码。高级语言写的源代码会被编译器编译成目标代码,目标代码通常是汇编代码或者机器代码。如果编译产出的是汇编代码,则用汇编器进一步将汇编代码汇编成机器代码。

       绝大部分情况,编译的“故事发展”路线大致可以简化成如下两条:

1
2
源代码——》机器代码
源代码——》汇编代码——》机器代码

       但是APK走的是另外一种路线。

1
源代码——》字节码——》机器代码

       字节码,是编译产生的中间代码,需要通过特定的虚拟机将字节码转译成物理主机的机器代码。对虚拟机来说,字节码就是虚拟机的机器码,但不是物理主机的机器码。

       这样做有什么好处?不同机器,其机器代码都是不一样的。一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标语言。而将源代码编译成字节码后,只需要安装特定的软件和软件环境,就可以将其转译成机器代码。只需要编译一次,而不需要考虑平台的问题,平台的差异全部交给软件去处理。Java就是采用这种方式,因此可以”一次编译,到处运行“。

       举个例子,生产红、蓝、绿三种颜色的纸张。如果采用寻常的编译方式,则需要三个车床分别生产;而采用字节码的编译方式,我只需要一个生产白色纸张的车床,然后交给第三方去染色就行了。这个例子应该很形象吧?

APK编译

       目前android应用开发主流语言是Java,还有近几年被官宣的Kotlin,当然还支持其他语言,这里我们只讲Java。

       首先给出APK编译打包的流程图。

       这里我将APK的编译过程简化成如下:

1
源文件——》.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编译打包不止这五个步骤,也不止这么点细节,但我觉得了解这五个步骤差不多足够了,免得讲多了大家一头雾水。后续有需要的话,我也会适当补充的。

免责声明

       安全小白团是帮助用户了解信息安全技术、安全漏洞相关信息的微信公众号。安全小白团提供的程序(方法)可能带有攻击性,仅供安全研究与教学之用,用户将其信息做其他用途,由用户承担全部法律及连带责任,安全小白团不承担任何法律及连带责任。

0%