INTRODUCTION TO ARM ASSEMBLY BASICS

来源:互联网 发布:淘宝男士挎包 单肩包 编辑:程序博客网 时间:2024/05/16 08:44

要遵循这些示例,您将需要一个基于ARM的实验室环境。如果你没有一个ARM设备(如树莓派),您可以通过设置使用QEMU和树莓派发行虚拟机自己的实验室环境下本教程。如果您不熟悉GDB的基本调试,可以在本教程中获得基础知识。在本教程中,重点将放在ARM 32位上,这些示例在ARMv6上编译。

为什么是ARM?

本教程通常适用于想要了解ARM程序集基础知识的人员。特别是对于那些对ARM平台上的漏洞编写感兴趣的人。您可能已经注意到,ARM处理器无处不在。当我环顾我的时候,我可以算出比Intel处理器更多的在我家里使用ARM处理器的设备。这包括电话,路由器,并且不要忘记这些天似乎在销售中爆炸的IoT设备。也就是说,ARM处理器已经成为世界上最广泛的CPU内核之一。这给我们带来了像PC这样的事实,IoT设备容易受到诸如缓冲区溢出等不正当输入验证的滥用。鉴于基于ARM的设备的广泛使用和潜在的滥用,这些设备的攻击变得越来越普遍。

然而,我们有更专业的x86安全研究专家,而不是我们对于ARM,尽管ARM汇编语言可能是最广泛的汇编语言。那么为什么不会有更多的人关注ARM?也许是因为有更多的学习资源涵盖了英特尔的开发,而不是ARM。请仔细考虑Corelan团队的英特尔x86漏洞利用编写的伟大教程- 这些指南可帮助人们对这一特定领域感兴趣,以获得实践知识和灵感,了解这些教程中的内容。如果您对x86漏洞编写感兴趣,则Corelan教程是您完美的起点。在本教程系列中,我们将重点介绍汇编基础知识和利用ARM编写。

ARM处理器与英特尔处理器

英特尔与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系列处理器使用 小端格式
ARM架构在版本3之前是小端点的。从那时起,ARM处理器成为BI-endian,并具有允许可切换字节顺序的设置。
英特尔和ARM之间不仅存在差异,而且在不同的ARM版本本身之间也存在差异。本教程系列旨在尽可能保持通用,以便您对ARM的工作方式有一个全面的了解。了解基础知识后,您可以轻松了解所选目标ARM版本的细微差别。本教程中的示例是在32位ARMv6(Raspberry Pi 1)上创建的,因此这些说明与此版本有关。

不同ARM版本的命名也可能令人困惑:

这里写图片描述

在我们开始潜入ARM开发开发之前,我们首先需要了解汇编语言编程的基础知识,这需要一些背景知识才能开始欣赏。但是为什么我们甚至需要ARM汇编,不足以用“正常”编程/脚本语言编写我们的漏洞?如果我们想要能够做逆向工程,并且了解ARM二进制程序的程序流程,那么我们不能构建我们自己的ARM shellcode,制作ARM ROP链和调试ARM应用程序。

您不需要了解汇编语言的每一个细节,以便能够进行逆向工程和利用开发,但有些则需要了解更大的图景。本教程系列将介绍基础知识。如果您想了解更多,您可以访问本章末尾列出的链接。

那么汇编语言究竟是什么呢?汇编语言只是机器代码之上的一个单一的语法层,它由以二进制表示(机器码)编码的指令组成,这是我们的计算机所理解的。那么为什么我们不写代码呢?因此,我们将编写ARM程序集,这对于人们来说更容易理解。我们的计算机本身不能运行汇编代码,因为它需要机器代码。我们将用于将汇编代码组装到机器代码中的工具是GNU Binutils项目中的GNU Assembler,名称 为与具有* .s扩展名的源文件一起使用。

一旦你与延伸写你的汇编文件* .S,你需要与组装起来的 ,并链接它LD:

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

这里写图片描述

让我们从最底层开始,并按照汇编语言进行工作。在最底层,我们在电路上有电信号。信号是通过将电压切换为两个电平之一来形成的,例如0伏(“关”)或5伏(“开”)。因为只是看着我们不能轻易的告诉电路是什么电压,我们选择使用视觉表示(数字0和1)写入/关闭电压的模式,不仅代表了缺席或存在的想法信号,也是因为0和1是二进制系统的数字。然后,我们对0和1的顺序进行分组,形成一个机器码指令,它是计算机处理器的最小工作单元。以下是机器语言指令的示例:

1110 0001 1010 0000 0010 0000 0000 0001

到目前为止这么好,但是我们不记得这些模式(0和1)是什么意思。因此,我们使用所谓的助记符,缩写来帮助我们记住这些二进制模式,其中每个机器代码指令都有一个名称。这些助记符通常由三个字母组成,但这不是强制性的。我们可以使用这些助记符编写程序作为说明。该程序称为汇编语言程序,用于表示计算机机器代码的助记符集称为该计算机的汇编语言。因此,汇编语言是人类编写计算机所使用的最低级别。指令的操作数来自助记符。这是一个例子:

MOV R2,R1

现在我们知道汇编程序是由称为助记符的文本信息组成的,所以我们需要把它转换成机器代码。如上所述,在ARM装配的情况下,GNU Binutils 项目为我们提供了一个名为as的工具。使用像汇编的过程作为对来自(ARM)汇编语言(ARM)机器代码转换被称为组装。

总而言之,我们了解到计算机了解(响应)电压(信号)的存在或不存在,并且我们可以以0和1(位)的顺序表示多个信号。我们可以使用机器码(信号序列)来使计算机以一些明确的方式作出响应。因为我们不记得这些序列是什么意思,我们给他们缩写 - 助记符,并用它们来表示指令。这组助记符是计算机的汇编语言,我们使用一个名为Assembler的程序将代码从助记符转换为计算机可读机器代码,方式与编译器对高级语言相同。

阅读全文
0 0
原创粉丝点击