本帖最后由 t7sqynt3 于 2020-7-22 09:39 编辑
前言:逆向工程需要汇编基础,先尝试整理目前所学的ARM汇编知识。由于水平有限,可能会有所疏漏,欢迎进行指正和讨论。此系列为原创,如引用需标明出处。然而,不建议作为学术研究的引用,因为内容未经过peer review。
0.基础知识与工具
ARM的特点
ARM,原指Acorn RISC Machine,而RISC=reduced instruction set computer,相对于CISC(complex instruction set computer)。RISC的特点是很多指令仅需1 CPU cycle即可执行,但是同样的程序所需指令的数量通常比CISC多。而CISC则相反,减少了程序所需指令数量,但是存在复杂的指令,需要数个CPU cycles执行。
ARM与Intel汇编的对比
前提
以下是此系列中用于学习的前提,不代表学习ARM汇编必须使用以下配置。
-
已有知识:C语言基础,最好有一些汇编基础(可以是非ARM汇编)和VIM编辑器基础。
-
环境:Cortex-A series CPU (armv7+) + Raspbian (RPI的OS) 或 Debian 或其他常用Linux分支 + GCC (target: arm-linux-gnueabi / arm-linux-gnueabihf)
-
Endianness: Little Endian
-
Word size: 4 bytes (32 bits)
-
Assembly Syntax: GNU
工具
-
(可选) QEMU,如果没有ARM CPU,则推荐使用(或同类模拟工具)。否则,需要GCC Arm toolchain,配置较为麻烦,而且调试仍然需要ARM CPU / simulation。如果使用Debian,可以直接用通用UEFI启动;如果使用Raspbian,注意需要使用修改过的内核启动。修改的Linux内核可以在网上搜索获取或自行patch+编译,注意versatilepb和vexpress所需内核不同,并且不同版本的Raspbian可能需要不同版本的修改内核启动。
-
(建议) ARM Keil MDK / DS-5 / Development Studio,可以用于学习指令效率。其中DS-5 / Development Studio功能比较齐全(DS-5已停止维护),可以模拟Cortex-A series CPU,但是获取途径和授权比较复杂,对于自学来说不推荐。MDK只支持模拟Microcontroller,typically Cortex-M series CPU,模拟设备的内存和ROM都比较小,并且MDK免费版(MDK-Lite)最大只支持32KB code and data,但是学习用途足够。本人选用的是MDK。
-
(建议) VIM,在Raspbian或其他Linux OS中。可以使用Emacs等其他编辑器。
工具配置
-
QEMU for windows
在cmd中运行的命令(可存为script):
".\qemu-system-arm.exe" ^
-kernel zImage ^
-m 512 ^
-M vexpress-a9 ^
-serial stdio ^
-append "root=/dev/mmcblk0p2" ^
-sd 2017-07-05-raspbian-jessie-lite.img ^
-dtb vexpress-v2p-ca9.dtb ^
-net nic ^
-net user,hostfwd=tcp::2222-:22 ^
-no-reboot
其中,zImage 为修改的linux内核启动,2017-07-05-raspbian-jessie-lite.img 为系统镜像,vexpress-v2p-ca9.dtb 是Device Tree Blob(包含模拟硬件信息,需要与修改的内核匹配)。如果有不能启动的情况,注意错误信息。有些时候会有blocks检测有问题的时候,注意img的大小是否与内核expected block size对齐,img分区有问题(包括移除不必要的gap)可以使用任意分区修改工具。
其他操作系统的QEMU配置类似,注意命令语法不同。
-
Keil MDK
可以选用DFP来更全面地模拟设备(需要注意授权,有些并非免费/自由使用),但是仅学习ARM汇编可以直接使用内置software pack。
一般学习调试时使用设备ARMCM3(Cortex-M3),software pack使用ARM CMSIS,包含完整的模拟(No FVP for MDK-Lite)。创建Project后,先打开Options for target,在Debug tab中,选择Use simulator(如果你有MDK-Pro license,也可以在右边选用Models Cortex-M Debugger,可以使用FVP以进行更好的模拟;与simulator的区别可见ARM Keil网站)。CPU DLL和Dialog DLL应该都会在创建Project选择设备后自动填充,如果没有的话,很有可能是该设备/DFP不支持simulator。ARMCM3默认值应该是CPU DLL: SARMCM3.DLL (-MPU), Dialog DLL: DCM.DLL (-pCM3)。在Manage Run-Time Environment中,CMSIS-Core勾选,Device-Startup勾选,即可正常编译和调试程序。如果需要程序redirect stdin/stdout/stderr to serial-debug (printf) window,则需要在Options for target的Target tab中选择Use MicroLIB,在Manage Run-Time Environment中勾选Compiler-I/O-STDERR/STDIN/STDOUT,并在variant选择ITM。
默认配置下,assembler是armclang/armasm而不是GCC,由于是assembler,对于研究指令效率没有什么差别。一定要使用GCC的话,配置会更复杂一些,需要使用GCC Arm toolchain(arm官方有提供),而且不直接支持redirect stdin/stdout/stderr,需要自己写代码进行redirect。并且默认的startup code可能也需要更改,虽然会提供ld script在Run-Time Environment的Device里。
-
VIM
可以使用自己习惯的.vimrc,一般来说,包括基本的syntax on,set autoindent,set smartindent即可。
汇编代码规范
-
tabstop=8,VIM默认设置,Keil MDK中可以在Edit-Configuration-Editor中设置。
-
Tab indent, no spaces (VIM关闭expandtab,set noexpandtab;Keil MDK在Edit-Configuration-Editor中不勾选Insert spaces for tabs)
-
Indent code into 4 columns:
label: operation operand(s) @comment
-
A whole line of comment:
@ a line of comment (without indentation)
-
没有一行过长的代码(typically <= 80 chars / line)
-
Appropriate file and function headers, and other comments
|