与高级语言相似,ARM支持操作不同类型的数据类型。我们可以load(or stroe)的数据类型有signed and unsigned words、halfwords、or bytes. 这些数据类型的extensions分别是:halfwords是-h or -sh,bytes是-b or -sb,word没有extension. signed and unsinged 数据的区别: 1.signed data type 能储存正数和负数 2.unsigned data type 可以保存大的正值(包括“零”),但不能保存负值。
R15:PC(Program Counter).程序计数器根据所执行指令的大小自动递增。 此大小在 ARM 状态下始终为 4 个字节,在 THUMB 模式下始终为 2 个字节。 当执行分支指令时,PC 持有目的地址。 在执行过程中,PC 在 ARM 状态下存储当前指令加 8(两条 ARM 指令)的地址,在 Thumb(v1) 状态下存储当前指令加 4(两条 Thumb 指令)的地址。 这与 x86 不同,在 x86 中 PC 总是指向要执行的下一条指令。
源程序如下:
在GDB中我们设置断点_start然后运行
断点的现场状态如下:
单步运行后:
奇妙的事情发生了,查看R0中的地址。 虽然我们希望 R0 包含先前读取的 PC 值 (0x10054),但它保存的是我们先前读取的 PC (0x1005c) 前两条指令的值。 从这个例子可以看出,当我们直接读取PC时,它遵循PC指向下一条指令的定义; 但在调试时,PC 指向当前 PC 值(0x10054 + 8 = 0x1005C)之前的两条指令。 这是因为较旧的 ARM 处理器总是在当前执行的指令之前获取两条指令。 ARM 保留此定义的原因是为了确保与早期处理器的兼容性。
寄存器 $CPSR 显示当前程序状态寄存器 (CPSR) 的值,在其下方您可以看到标志拇指、快速中断、溢出、进位、零和负数。 这些标志代表 CPSR 寄存器中的某些位,根据 CPSR 的值设置,激活时变为1。 N、Z、C 和 V 位与 x86 上 EFLAG 寄存器中的 SF、ZF、CF 和 OF 位相同。 这些位用于在程序集级别支持条件和循环中的条件执行
Negative|Zero|Carry|Overflow|underflow| |Jazelle| |Greater than or Equal for SIMD| |Endianness| Abort disable| IRQ disable | FIQ disable | Thumb| Processor mode(Privilege mode)|
APSR包含下列ALU的状态标志:
N-当操作结果为负数时设置;
Z-当操作结果为0时设置;
C-当操作导致进位时设置;
V-当操作造成溢出时设置。
在下列情况下,进位发生:
如果加法、减法或比较的结果大于或等于 2^31,或小于 –2^31,溢出发生。
ARM 处理器有两个主要的状态可以运行(这里不计算 Jazelle),ARM 和 Thumb。 这些状态与特权级别无关。 例如,在 SVC 模式下运行的代码可以是 ARM 或 Thumb。 这两种状态的主要区别在于指令集,其中ARM状态的指令总是32位的,Thumb状态的指令是16位的(但也可以是32位的)。 了解何时以及如何使用 Thumb 对于我们的 ARM 漏洞利用开发目的尤其重要。 在编写 ARM shellcode 时,我们需要去掉 NULL 字节,使用 16 位 Thumb 指令而不是 32 位 ARM 指令减少了拥有它们的机会。
ARM使用load-store模式进行内存的访问,这意味着只能使用load/store(LDR and LDR)指令能访问内存。而x86允许直接在内存上操作数据,在arm上数据在操作前必须被move到寄存器中。这意味着在 ARM 上的特定内存地址处递增 32 位值将需要三种类型的指令(load, increment, and store) 来首先将特定地址处的值加载到寄存器中,在寄存器中递增它,然后将它从寄存器存储回内存。为了解释 ARM 上加载和存储操作的基本原理,我们从一个基本示例开始,然后继续介绍三种基本偏移量形式,每种偏移量形式具有三种不同的地址模式。 对于每个示例,我们将使用具有不同 LDR/STR 偏移形式的同一段汇编代码,以保持简单。
MNEMONIC -Short name (mnemonic) of the instruction
{S} -An optional suffix. If S isspecified, the condition flags are updated on the result of the operation
{condition} -Condition that isneeded to be met inorder forthe instruction to be executed
{Rd} -Register (destination) forstoring the result of the instruction
Operand1 -First operand. Either a register oran immediate value
Operand2 -Second (flexible) operand. Can be an immediate value (number) ora register with an optional shift
MNEMONIC -Short name (mnemonic) of the instruction
{S} -An optional suffix. If S isspecified, the condition flags are updated on the result of the operation
{condition} -Condition that isneeded to be met inorder forthe instruction to be executed
{Rd} -Register (destination) forstoring the result of the instruction
Operand1 -First operand. Either a register oran immediate value
Operand2 -Second (flexible) operand. Can be an immediate value (number) ora register with an optional shift
#123 - Immediate value (with limited set of values).
Rx -Register x (like R1, R2, R3 ...)
Rx, ASR n -Register x with arithmetic shift right by n bits (1=n =32)
Rx, LSL n -Register x with logical shift left by n bits (0=n =31)
Rx, LSR n -Register x with logical shift right by n bits (1=n =32)
Rx, ROR n -Register x with rotate right by n bits (1=n =31)
Rx, RRX -Register x with rotate right by one bit, with extend
#123 - Immediate value (with limited set of values).
Rx -Register x (like R1, R2, R3 ...)
Rx, ASR n -Register x with arithmetic shift right by n bits (1=n =32)
Rx, LSL n -Register x with logical shift left by n bits (0=n =31)
Rx, LSR n -Register x with logical shift right by n bits (1=n =32)
Rx, ROR n -Register x with rotate right by n bits (1=n =31)
Rx, RRX -Register x with rotate right by one bit, with extend
ADD R0, R1, R2 -Adds contents of R1 (Operand1) andR2 (Operand2 ina form of register) andstores the result into R0 (Rd)
ADD R0, R1, #2 - Adds contents of R1 (Operand1) and the value 2 (Operand2 in a form of an immediate value) and stores the result into R0 (Rd)
MOVLE R0, #5 - Moves number 5 (Operand2, because the compiler treats it as MOVLE R0, R0, #5) to R0 (Rd) ONLY if the condition LE (Less Than or Equal) is satisfied
MOV R0, R1, LSL #1 - Moves the contents of R1 (Operand2 in a form of register with logical shift left) shifted left by one bit to R0 (Rd). So if R1 had value 2, it gets shifted left by one bit and becomes 4. 4 is then moved to R0.
ADD R0, R1, R2 -Adds contents of R1 (Operand1) andR2 (Operand2 ina form of register) andstores the result into R0 (Rd)
ADD R0, R1, #2 - Adds contents of R1 (Operand1) and the value 2 (Operand2 in a form of an immediate value) and stores the result into R0 (Rd)
MOVLE R0, #5 - Moves number 5 (Operand2, because the compiler treats it as MOVLE R0, R0, #5) to R0 (Rd) ONLY if the condition LE (Less Than or Equal) is satisfied
MOV R0, R1, LSL #1 - Moves the contents of R1 (Operand2 in a form of register with logical shift left) shifted left by one bit to R0 (Rd). So if R1 had value 2, it gets shifted left by one bit and becomes 4. 4 is then moved to R0.
Instruction
Description
Instruction
Description
MOV
Move data
EOR
Bitwise XOR
MVN
Move and negate
LDR
Load
ADD
Addition
STR
Store
SUB
Subtraction
LDM
Load Multiple
MUL
Multiplication
STM
Store Multiple
LSL
Logical Shift Left
PUSH
Push on Stack
LSR
Logical Shift Right
POP
Pop off Stack
ASR
Arithmetic Shift Right
B
Branch
ROR
Rotate Right
BL
Branch with Link
CMP
Compare
BX
Branch and eXchange
AND
Bitwise AND
BLX
Branch with Link and eXchange
ORR
Bitwise OR
SWI/SVC
System Call
LDR R2, [R0] @ [R0] -origin address isthe value found inR0.
STRR2, [R1] @ [R1] -destination address isthe value found inR1.
LDR R2, [R0] @ [R0] -origin address isthe value found inR0.
STRR2, [R1] @ [R1] -destination address isthe value found inR1.
.data /*the .data section isdynamically created andits addresses cannot be easily predicted */
var1: .word 3/*variable 1inmemory */
var2: .word 4/*variable 2inmemory */
.text /*start of the text (code) section */
.global_start
_start:
ldr r0, adr_var1 @ load the memory address of var1 via label adr_var1 into R0
ldr r1, adr_var2 @ load the memory address of var2 via label adr_var2 into R1
ldr r2, [r0] @ load the value (0x03) at memory address found inR0 to register R2
strr2, [r1] @ store the value found inR2 (0x03) to the memory address found inR1
bkpt
adr_var1: .word var1 /*address to var1 stored here */
adr_var2: .word var2 /*address to var2 stored here */
.data /*the .data section isdynamically created andits addresses cannot be easily predicted */
var1: .word 3/*variable 1inmemory */
var2: .word 4/*variable 2inmemory */
.text /*start of the text (code) section */
.global_start
_start:
ldr r0, adr_var1 @ load the memory address of var1 via label adr_var1 into R0
ldr r1, adr_var2 @ load the memory address of var2 via label adr_var2 into R1
ldr r2, [r0] @ load the value (0x03) at memory address found inR0 to register R2
strr2, [r1] @ store the value found inR2 (0x03) to the memory address found inR1
bkpt
adr_var1: .word var1 /*address to var1 stored here */
adr_var2: .word var2 /*address to var2 stored here */
ldr r0, adr_var1 @ load the memory address of var1 via label adr_var1 into R0
ldr r1, adr_var2 @ load the memory address of var2 via label adr_var2 into R1
ldr r2, [r0] @ load the value (0x03) at memory address found inR0 to register R2
strr2, [r1, #2] @ address mode: offset. Store the value found in R2 (0x03) to the memory address found in R1 plus 2. Base register (R1) unmodified.
strr2, [r1, #4]! @ address mode: pre-indexed. Store the value found in R2 (0x03) to the memory address found in R1 plus 4. Base register (R1) modified: R1 = R1+4
ldr r3, [r1], #4 @ address mode: post-indexed. Load the value at memory address found in R1 to register R3. Base register (R1) modified: R1 = R1+4