ARM匯編基礎教程(ARM匯編簡介)
[原文鏈接] :https://azeria-labs.com/writing-arm-assembly-part-1/
Welcome to this tutorial series on ARM assembly basics. This is the preparation for the followup tutorial series on ARM exploit development. Before we can dive into creating ARM shellcode and build ROP chains, we need to cover some ARM Assembly basics first.
歡迎使用本系列教程烫映,了解有關ARM組件的基礎知識通今。 這篇文章為學習ARM利用開發(fā)的后續(xù)教程系列作準備。 在深入研究創(chuàng)建ARM shellcode和構建ROP鏈之前脸爱,我們需要首先介紹一些ARM Assembly基礎知識抒钱。
The following topics will be covered step by step:
ARM Assembly Basics Tutorial Series:
Part 1: Introduction to ARM Assembly
Part 2: Data Types Registers
Part 3: ARM Instruction Set
Part 4: Memory Instructions: Loading and Storing Data
Part 5: Load and Store Multiple
Part 6: Conditional Execution and Branching
Part 7: Stack and Functions
ARM匯編基礎教程系列:
第1部分:ARM匯編簡介
第2部分:數(shù)據(jù)類型及寄存器
第3部分:ARM指令集
第4部分:內(nèi)存指令:加載和存儲數(shù)據(jù)
第5部分:高級內(nèi)存加載和存儲
第6部分:條件分支
第7部分:堆棧和函數(shù)
To follow along with the examples, you will need an ARM based lab environment. If you don’t have an ARM device (like Raspberry Pi), you can set up your own lab environment in a Virtual Machine using QEMU and the Raspberry Pi distro by following this tutorial. If you are not familiar with basic debugging with GDB, you can get the basics in this tutorial. In this tutorial, the focus will be on ARM 32-bit, and the examples are compiled on an ARMv6.
要跟隨示例學習了袁,您需要搭建一個基于ARM的實驗室環(huán)境坦仍。 如果您沒有ARM設備(例如樹莓派)水慨,那么您可以按照本教程使用QEMU和Raspberry Pi發(fā)行版在虛擬機中搭建一個實驗室環(huán)境得糜。 如果您不熟悉GDB的基本調試,則可以跟著本教程中學習基本知識晰洒。 在本教程中朝抖,重點將放在ARM 32位上,且示例是在ARMv6上編譯的谍珊。
為什么要學習ARM治宣?
This tutorial is generally for people who want to learn the basics of ARM assembly. Especially for those of you who are interested in exploit writing on the ARM platform. You might have already noticed that ARM processors are everywhere around you. When I look around me, I can count far more devices that feature an ARM processor in my house than Intel processors. This includes phones, routers, and not to forget the IoT devices that seem to explode in sales these days. That said, the ARM processor has become one of the most widespread CPU cores in the world. Which brings us to the fact that like PCs, IoT devices are susceptible to improper input validation abuse such as buffer overflows. Given the widespread usage of ARM based devices and the potential for misuse, attacks on these devices have become much more common.
本教程適用于想要學習ARM匯編基礎知識的人。 尤其適合那些對在ARM平臺上進行漏洞利用以及編寫感興趣的人。 您可能已經(jīng)注意到ARM處理器無處不在侮邀。 當我開始察覺時坏怪,我才發(fā)現(xiàn)與intel處理器相比,在家中看到搭載了ARM處理器的設備數(shù)量要比intel的多得多绊茧。 例如電話铝宵、
路由器等,不要忘記銷售火爆的IoT設備华畏。 換句話說鹏秋,ARM處理器已成為世界上最廣泛使用的CPU內(nèi)核之一。 我們可以得出一個這樣的結論亡笑,與PC一樣侣夷,IoT設備也容易受到不合法的輸入驗證濫用(例如緩沖區(qū)溢出)的影響。 鑒于基于ARM的設備的廣泛使用和濫用的可能性况芒,黑客對這些設備的攻擊進行攻擊的事件更加常見惜纸。
Yet, we have more experts specialized in x86 security research than we have for ARM, although ARM assembly language is perhaps the easiest assembly language in widespread use. So, why aren’t more people focusing on ARM? Perhaps because there are more learning resources out there covering exploitation on Intel than there are for ARM. Just think about the great tutorials on Intel x86 Exploit writing by [Fuzzy Security]:(https://www.fuzzysecurity.com/tutorials/expDev/1.html) or the Corelan Team – Guidelines like these help people interested in this specific area to get practical knowledge and the inspiration to learn beyond what is covered in those tutorials. If you are interested in x86 exploit writing, the Corelan and Fuzzysec tutorials are your perfect starting point. In this tutorial series here, we will focus on assembly basics and exploit writing on ARM.
作為最簡單的匯編語言,盡管ARM匯編語言已經(jīng)得到廣泛使用绝骚,但是比起擁有大量專門從事x86安全研究的專家的x86語言耐版,arm匯編語言的安全問題更加急迫。 那么压汪,為什么沒有更多的人專注于ARM呢粪牲? 也許是因為,與ARM相比止剖,在Intel領域有更多的學習資源腺阳,用戶只需考慮一下由Fuzzy Security或Corelan Team撰寫的有關Intel x86 Exploit的出色教程,這些指南就可以幫助對此特定領域感興趣的人們獲得實踐知識穿香,并從中學到的啟發(fā)來學習這些教程所涵蓋的內(nèi)容亭引。 如果您對x86漏洞利用程序編寫感興趣,那么Corelan和Fuzzysec教程就是您的理想起點:(https://www.corelan.be/index.php/2009/07/19/exploit-writing-tutorial-part-1-stack-based-overflows/)皮获。 在本教程系列中焙蚓,我們將重點介紹匯編基礎知識和利用ARM進行開發(fā)。
ARM處理器VS Intel處理器
There are many differences between Intel and ARM, but the main difference is the instruction set. Intel is a CISC (Complex Instruction Set Computing) processor that has a larger and more feature-rich instruction set and allows many complex instructions to access memory. It therefore has more operations, addressing modes, but less registers than ARM. CISC processors are mainly used in normal PC’s, Workstations, and servers.
Intel和ARM之間有很大的區(qū)別洒宝,但主要區(qū)別是指令集购公。 英特爾是CISC(復雜指令集計算)處理器,具有更大雁歌,功能更豐富的指令集宏浩,并允許許多復雜的指令訪問內(nèi)存。 因此靠瞎,與ARM相比比庄,它具有更多的操作求妹、尋址模式,但同時寄存器更少印蔗。 CISC處理器主要用于普通PC扒最,工作站和服務器。
ARM is a RISC (Reduced instruction set Computing) processor and therefore has a simplified instruction set (100 instructions or less) and more general purpose registers than CISC. Unlike Intel, ARM uses instructions that operate only on registers and uses a Load/Store memory model for memory access, which means that only Load/Store instructions can access memory. This means that incrementing a 32-bit value at a particular memory address on ARM would require three types of instructions (load, increment and store) to first load the value at a particular address into a register, increment it within the register, and store it back to the memory from the register.
ARM是RISC(精簡指令集計算)處理器华嘹,因此比CISC具有簡化的指令集(100條或更少的指令)和更多通用寄存器吧趣。 與Intel不同的是,ARM使用僅在寄存器上操作的指令耙厚,并使用load/store內(nèi)存模型進行內(nèi)存訪問强挫,這意味著只有l(wèi)oad/store指令才能訪問內(nèi)存。 這意味著遞增ARM上特定內(nèi)存地址上的32位值將需要三種類型的指令(load指令薛躬、加法指令和store指令)俯渤,以便首先將特定地址上的值加載到寄存器中,在寄存器中遞增并存儲型宝。 它從寄存器返回到存儲器八匠。
The reduced instruction set has its advantages and disadvantages. One of the advantages is that instructions can be executed more quickly, potentially allowing for greater speed (RISC systems shorten execution time by reducing the clock cycles per instruction). The downside is that less instructions means a greater emphasis on the efficient writing of software with the limited instructions that are available. Also important to note is that ARM has two modes, ARM mode and Thumb mode. Thumb instructions can be either 2 or 4 bytes (more on that in Part 3: ARM Instruction set).
精簡指令集有其優(yōu)點和缺點。 優(yōu)點之一是指令可以更快地執(zhí)行趴酣,從而有可能提高速度(RISC系統(tǒng)通過減少每條指令的時鐘周期來縮短執(zhí)行時間)梨树。 不利的一面是, 較少的指令增加了軟件(事實上是編譯器)的復雜性岖寞。還需要注意的重要一點是ARM有兩種模式抡四,ARM模式和Thumb模式。 Thumb指令可以是2個字節(jié)或4個字節(jié)(有關第3部分:ARM指令集的更多信息https://azeria-labs.com/arm-instruction-set-part-3/
)仗谆。
More differences between ARM and x86 are:
In ARM, most instructions can be used for conditional execution.
The Intel x86 and x86-64 series of processors use the little-endian format
The ARM architecture was little-endian before version 3. Since then ARM processors became BI-endian and feature a setting which allows for switchable endianness.
ARM和x86之間的更多區(qū)別是:
- 在ARM中指巡,大多數(shù)指令可用于分支跳轉的條件執(zhí)行。
- Intel x86和x86-64系列處理器使用小端字節(jié)序
- 在v3之前隶垮,ARM體系結構為小端字節(jié)序藻雪。此后,ARM處理器提供一個配置項狸吞,可以通過配置在大端和小端之間切換勉耀。
There are not only differences between Intel and ARM, but also between different ARM version themselves. This tutorial series is intended to keep it as generic as possible so that you get a general understanding about how ARM works. Once you understand the fundamentals, it’s easy to learn the nuances for your chosen target ARM version. The examples in this tutorial were created on an 32-bit ARMv6 (Raspberry Pi 1), therefore the explanations are related to this exact version.
Intel與ARM之間不僅存在差異,而且不同ARM版本之間也存在差異捷绒。 本教程系列旨在盡可能地保持通用性瑰排,以便您對ARM的工作原理有一個大致的了解贯要。 只要您了解了基礎知識暖侨,就可以輕松了解所選目標ARM版本的細微差別。 本教程中的示例是在32位ARMv6(Raspberry Pi 1)上創(chuàng)建的崇渗,因此說明與該確切版本有關字逗。
對不同版本的ARM的命名可能還會造成混淆:
image.png
編寫ARM匯編
Before we can start diving into ARM exploit development we first need to understand the basics of Assembly language programming, which requires a little background knowledge before you can start to appreciate it. But why do we even need ARM Assembly, isn’t it enough to write our exploits in a “normal” programming / scripting language? It is not, if we want to be able to do Reverse Engineering and understand the program flow of ARM binaries, build our own ARM shellcode, craft ARM ROP chains, and debug ARM applications.
在開始深入研究ARM利用開發(fā)之前京郑,我們首先需要了解匯編語言編程的基礎知識,這需要一些基礎知識葫掉,然后您才能開始認識它的優(yōu)點些举。 但是,我們?yōu)槭裁匆褂肁RM匯編來編程呢俭厚,我們不是有很多高級語言和腳本語言嗎户魏?如果你想通過了解ARM程序進行逆向工程進而了解更多的程序執(zhí)行流程,或者構建ROP鏈來實現(xiàn)你自己的ARM shellcode挪挤,亦或者調試ARM程序叼丑,你都需要ARM匯編的知識作為基礎。
You don’t need to know every little detail of the Assembly language to be able to do Reverse Engineering and exploit development, yet some of it is required for understanding the bigger picture. The fundamentals will be covered in this tutorial series. If you want to learn more you can visit the links listed at the end of this chapter.
您不需要了解匯編語言的每一個小細節(jié)就能進行逆向工程和開發(fā)扛门,但是為了理解大局您需要清楚一些基本的知識鸠信。 基礎知識將在本教程系列中介紹。 如果您想了解更多信息论寨,可以訪問本章末尾列出的鏈接星立。
So what exactly is Assembly language? Assembly language is just a thin syntax layer on top of the machine code which is composed of instructions, that are encoded in binary representations (machine code), which is what our computer understands. So why don’t we just write machine code instead? Well, that would be a pain in the ass. For this reason, we will write assembly, ARM assembly, which is much easier for humans to understand. Our computer can’t run assembly code itself, because it needs machine code. The tool we will use to assemble the assembly code into machine code is a GNU Assembler from the GNU Binutils project named as which works with source files having the *.s extension.
那么匯編語言到底是什么? 匯編語言只是機器代碼之上的一個簡單語法層葬凳,它由指令組成绰垂,這些指令以二進制表示形式(機器代碼)編碼,這是我們的計算機可以理解的沮明。 那為什么我們不只是寫機器代碼呢辕坝? 好吧,那由人來寫的話將是一團糟荐健。 因此酱畅,我們將編寫匯編程序,即ARM匯編程序江场,這對于人類來說更容易理解纺酸。 我們的計算機本身無法運行匯編代碼,因為它需要機器代碼址否。 我們將用于將匯編代碼匯編成機器代碼的工具是GNU Binutils項目中的GNU匯編器餐蔬,它可與擴展名為* .s的源文件一起使用。
Once you wrote your assembly file with the extension *.s, you need to assemble it with as and link it with ld:
最終的過程是這樣的佑附,當你編寫了后綴為“.s”的匯編文件樊诺,你可以使用as將它匯編,最后使用ld鏈接音同,如下所示:
$ as program.s -o program.o
$ ld program.o -o program
Let’s start at the very bottom and work our way up to the assembly language. At the lowest level, we have our electrical signals on our circuit. Signals are formed by switching the electrical voltage to one of two levels, say 0 volts (‘off’) or 5 volts (‘on’). Because just by looking we can’t easily tell what voltage the circuit is at, we choose to write patterns of on/off voltages using visual representations, the digits 0 and 1, to not only represent the idea of an absence or presence of a signal, but also because 0 and 1 are digits of the binary system. We then group the sequence of 0 and 1 to form a machine code instruction which is the smallest working unit of a computer processor. Here is an example of a machine language instruction:
這一節(jié)词爬,讓我們從最底層開始,自底向上权均,看看匯編語言是如何工作的顿膨。在計算機系統(tǒng)的最底層锅锨,是密布的傳輸著電信號的電路。信號是通過控制電壓恋沃,在兩個電平之間切換形成的必搞,例如0伏(低電平代表關信號)和5伏(高電平代表開信號)。對于硬件系統(tǒng)囊咏,電路中電壓的具體數(shù)值是沒有意義的恕洲,所以我們用抽象的數(shù)字0和1來表示電路的開/關電平。有意思的是梅割,0和1不僅代表了電信號研侣,也構成了一個二進制系統(tǒng)。在這個基礎上炮捧,我們將電信號序列(01序列)分組庶诡,每一組序列就是一個機器碼指令。下面是機組機器碼指令的示意(并非實際的機器碼):
1110 0001 1010 0000 0010 0000 0000 0001
So far so good, but we can’t remember what each of these patterns (of 0 and 1) mean. For this reason, we use so called mnemonics, abbreviations to help us remember these binary patterns, where each machine code instruction is given a name. These mnemonics often consist of three letters, but this is not obligatory. We can write a program using these mnemonics as instructions. This program is called an Assembly language program, and the set of mnemonics that is used to represent a computer’s machine code is called the Assembly language of that computer. Therefore, Assembly language is the lowest level used by humans to program a computer. The operands of an instruction come after the mnemonic(s). Here is an example:
MOV R2, R1
到目前為止咆课,一切都很好末誓,但是我們馬上就會迎來第一個困難,機器碼序列難以記憶。 因此书蚪,我們使用了助記符(縮寫詞)來幫助我們記住這些二進制模式喇澡,其中每個機器代碼指令都被賦予了一個名稱。 這些助記符通常由三個字母組成殊校,但這不是必須的晴玖。 我們可以使用這些助記符作為指令編寫程序。 該程序稱為匯編語言程序为流,用于表示計算機的機器代碼的助記符集稱為該計算機的匯編語言呕屎。 因此,匯編語言是人類用來編程計算機的最低級別敬察。 指令的操作數(shù)位于助記符之后秀睛。 這是一個例子:
MOV R2, R1
Now that we know that an assembly program is made up of textual information called mnemonics, we need to get it converted into machine code. As mentioned above, in the case of ARM assembly, the GNU Binutils project supplies us with a tool called as. The process of using an assembler like as to convert from (ARM) assembly language to (ARM) machine code is called assembling.
我們現(xiàn)在已經(jīng)知道了匯編程序代碼是由許多匯編指令組成的文本信息,所以我們需要把它轉化為對應的機器代碼莲祸。根據(jù)上文蹂安,對于ARM匯編,GNU Binutils項目為我們提供了一個名為as的工具來完成這個轉換锐帜。使用匯編器如as將ARM匯編程序代碼轉換成ARM機器碼的過程稱為匯編田盈。
In summary, we learned that computers understand (respond to) the presence or absence of voltages (signals) and that we can represent multiple signals in a sequence of 0s and 1s (bits). We can use machine code (sequences of signals) to cause the computer to respond in some well-defined way. Because we can’t remember what all these sequences mean, we give them abbreviations – mnemonics, and use them to represent instructions. This set of mnemonics is the Assembly language of the computer and we use a program called Assembler to convert code from mnemonic representation to the computer-readable machine code, in the same way a compiler does for high-level languages.
總而言之,我們知道計算機可以讀取并理解電信號序列缴阎,而我們可以用0和1來表示這種序列并告知計算機(這就是機器碼)允瞧。我們可以使用機器碼,令計算機以一些確定的方式做出響應,所以我們可以對計算機進行編程瓷式。但這些機器碼序列難以記憶,所以我們給它們命名從而引入了助記符语泽,并用它來表示指令贸典。這些助記符和對應的操作數(shù)語法就構成了匯編語言,我們使用一個匯編器將匯編程序代碼轉換為機器碼踱卵。這個過程和編譯器將高級語言轉換為匯編代碼是類似的廊驼。