ARM汇编(第一部分)ARM汇编基础知识简介


 欢迎使用本系列教程,了解有关ARM组件的基础知识。这是有关ARM利用开发的后续教程系列的准备。在深入研究创建ARM shellcode和构建ROP链之前,我们需要首先介绍一些ARM Assembly基础知识。

以下主题将逐步介绍:

ARM 汇编基础教程系列:

  • 第1部分:ARM Assembly简介
  • 第2部分:数据类型寄存器
  • 第3部分:ARM指令集
  • 第4部分:内存指令:加载和存储数据
  • 第5部分:加载和存储多个
  • 第6部分:有条件的执行和分支
  • 第7部分:堆栈和函数

 要继续执行示例,您将需要一个基于ARM的实验室环境。如果您没有ARM设备(例如Raspberry Pi),则可以按照本教程使用QEMU和Raspberry Pi发行版在虚拟机中设置自己的实验室环境。如果您不熟悉GDB的基本调试,则可以在本教程中获得基本知识。在本教程中,重点是ARM 32位,示例在ARMv6上编译。

为什么选择ARM?

 本教程通常面向想要学习ARM汇编基础知识的人们。特别适合那些对在ARM平台上进行漏洞利用编写感兴趣的人。您可能已经注意到ARM处理器无处不在。当我环顾四周时,与英特尔处理器相比,在家中可以看到配备ARM处理器的设备数量要多得多。其中包括电话,路由器,不要忘记这些天似乎在销售中爆炸的IoT设备。也就是说,ARM处理器已成为世界上最广泛使用的CPU内核之一。这使我们认识到,与PC一样,IoT设备也容易受到不正确的输入验证滥用(例如缓冲区溢出)的影响。考虑到基于ARM的设备的广泛使用和滥用的可能性,对这些设备的攻击变得更加普遍。

 但是,尽管ARM汇编语言可能是广泛使用的最简单的汇编语言,但是与x86相比,我们拥有更多专门从事x86安全研究的专家。那么,为什么没有更多的人专注于ARM?也许是因为与ARM相比,存在更多关于Intel开发的学习资源。只需考虑一下模糊安全性或Corelan团队撰写的有关Intel x86 Exploit的出色教程即可–此类指南可帮助对此特定领域感兴趣的人们获得实践知识,并从这些教程所涵盖的内容中汲取学习的启发。如果您对x86漏洞利用代码编写感兴趣,那么Corelan和Fuzzysec教程就是您的理想起点。在本教程系列中,我们将重点介绍汇编基础知识和利用ARM进行开发的代码。

ARM处理器与INTEL处理器

 英特尔和ARM之间有很多区别,但主要区别是指令集。英特尔是CISC(复杂指令集计算)处理器,具有更大,功能更丰富的指令集,并允许许多复杂的指令访问内存。因此,与ARM相比,它具有更多的操作,寻址模式,但寄存器更少。CISC处理器主要用于普通PC,工作站和服务器。

 ARM是RISC(精简指令集计算)处理器,因此比CISC具有简化的指令集(100条或更少的指令)和更多的通用寄存器。与英特尔不同,ARM使用仅在寄存器上操作的指令,并使用“加载/存储”内存模型进行内存访问,这意味着只有“加载/存储”指令才能访问内存。这意味着递增ARM上特定内存地址上的32位值将需要三种类型的指令(加载,递增和存储),以便首先将特定地址上的值加载到寄存器中,在寄存器中递增并存储。它从寄存器返回到存储器。

 精简指令集有其优点和缺点。优点之一是指令可以更快地执行,从而有可能提高速度(RISC系统通过减少每条指令的时钟周期来缩短执行时间)。不利的一面是,更少的指令意味着更多地强调使用有限的可用指令来有效地编写软件。还需要注意的重要一点是ARM有两种模式,ARM模式和Thumb模式。Thumb指令可以是2个字节或4个字节(有关第3部分:ARM指令集的更多信息)。

ARM和x86之间的更多区别是:

  • 在ARM中,大多数指令可用于条件执行。
  • Intel x86和x86-64系列处理器使用 little-endian格式
  • 在版本3之前,ARM体系结构为低端字节序。从那时起,ARM处理器成为BI-endian,并具有允许可切换字节序的设置。

 英特尔和ARM之间不仅存在差异,而且不同ARM版本之间也存在差异。本教程系列旨在尽可能地保持通用性,以使您对ARM的工作方式有一个大致的了解。一旦了解了基础知识,就很容易了解所选目标ARM版本的细微差别。本教程中的示例是在32位ARMv6(Raspberry Pi 1)上创建的,因此说明与该确切版本有关。

不同ARM版本的命名也可能会造成混淆:

ARM家族ARM架构
ARM7ARM v4
ARM9ARM v5
ARM11ARM v6
Cortex-AARM v7-A
Cortex-RARM v7-R
Cortex-MARM v7-M

编写汇编


 在开始深入研究ARM利用开发之前,我们首先需要了解汇编语言编程的基础知识,这需要一些背景知识,然后您才能开始欣赏它。但是,为什么我们甚至需要ARM Assembly,这还不足以用“常规”编程/脚本语言编写我们的漏洞利用程序吗?并非如此,如果我们希望能够进行逆向工程并了解ARM二进制文件的程序流程,构建我们自己的ARM Shellcode,制作ARM ROP链并调试ARM应用程序。

 您不需要了解汇编语言的每一个小细节就可以进行逆向工程和利用开发,但是其中一些知识对于理解更广阔的前景是必不可少的。基础知识将在本教程系列中介绍。如果您想了解更多信息,可以访问本章末尾列出的链接。

 那么汇编语言到底是什么?汇编语言只是位于机器代码之上的薄语法层,该机器语法由指令组成,这些指令以二进制表示形式(机器代码)编码,这是我们的计算机可以理解的。那么,为什么我们不只是编写机器代码呢?好吧,那将是一个痛苦的屁股。因此,我们将编写汇编程序,ARM汇编程序,这对于人类来说更容易理解。我们的计算机本身无法运行汇编代码,因为它需要机器代码。我们将用来组装汇编代码转换为机器代码的工具是从一个GNU汇编GNU Binutils的命名项目 作为其与具有* .S扩展名的源文件的工作。

 用扩展名* .s编写汇编文件后,您需要使用as进行汇编并将 其与ld链接:

$ as program.s -o program.o
$ ld program.o -o program

在这里插入图片描述

汇编之下的底层


 让我们从最底层开始,逐步发展到汇编语言。在最低层,电路上有电信号。通过将电压切换到两个电平之一(例如0伏(“关”)或5伏(“开”))来形成信号。因为仅通过查看我们无法轻易分辨出电路的电压,所以我们选择使用可视表示形式(数字0和1)来编写开/关电压模式,不仅表示不存在或存在信号,也因为0和1是二进制系统的数字。然后,我们将0和1的序列分组以形成机器代码指令,该机器代码指令是计算机处理器的最小工作单元。这是机器语言指令的示例:

1110 0001 1010 0000 0010 0000 0000 0001

 到目前为止,一切都很好,但我们不记得这些模式(分别为0和1)的含义。因此,我们使用了助记符(缩写词)来帮助我们记住这些二进制模式,其中每个机器代码指令都被赋予了一个名称。这些助记符通常由三个字母组成,但这不是必须的。我们可以使用这些助记符作为指令编写程序。该程序称为汇编语言程序,用于表示计算机的机器代码的助记符集称为该计算机的汇编语言。因此,汇编语言是人类用来编程计算机的最低级别。指令的操作数位于助记符之后。这是一个例子:

MOV R2,R1

 现在我们知道汇编程序由称为助记符的文本信息组成,我们需要将其转换为机器代码。作为ARM的情况下,如上所述,装配,GNU Binutils的 项目给我们提供了一个工具,叫做为。使用汇编等的处理作为从(ARM)汇编语言(ARM)机器代码转换被称为组装。

 总而言之,我们了解到计算机可以理解(响应)电压(信号)的存在或不存在,并且我们可以以0和1s(位)的顺序表示多个信号。我们可以使用机器代码(信号序列)使计算机以某种定义明确的方式做出响应。因为我们不记得所有这些序列的含义,所以给它们起了缩写-助记符,并用它们来表示指令。这组助记符是计算机的汇编语言,我们使用称为汇编程序的程序将代码从助记符表示形式转换为计算机可读的机器代码,就像编译器为高级语言所做的一样。

进一步阅读


  1. ARM汇编的旋风之旅。
    https://www.coranac.com/tonc/text/asm.htm

  2. Raspberry Pi中的ARM汇编器。
    http://thinkingeek.com/arm-assembler-raspberry-pi/

  3. 实用逆向工程:x86,x64,ARM,Windows内核,逆向工具和Bruce Dang,Alexandre Gazet,Elias Bachaalany和Sebastien Josse的混淆。

  4. 《 ARM参考手册》。
    http://infocenter.arm.com/help/topic/com.arm.doc.dui0068b/index.html

  5. 汇编程序用户指南。
    http://www.keil.com/support/man/docs/armasm/default.htm

相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页