ARM模式、THUMB模式若干工程实践问题

ARM架构中有一个CPSR寄存器,它的的bit-5是T位(Thumb state flag),置1表示THUMB模式,置0表示ARM模式。二者区别很多,对于逆向工程来说,可以简单理解成ARM模式都是4字节指令,THUMB模式尽可能采用2字节指令编码方案;这种说法很不严谨,但不影响大局。此处只考虑32-bits ARM。

☆ ARM模式、THUMB模式简介

ARM架构中有一个CPSR寄存器,它的的bit-5是T位(Thumb state flag),置1表示THUMB模式,置0表示ARM模式。二者区别很多,对于逆向工程来说,可以简单理解成ARM模式都是4字节指令,THUMB模式尽可能采用2字节指令编码方案;这种说法很不严谨,但不影响大局。此处只考虑32-bits ARM。

一段代码中可以先出现ARM模式的指令,接着设法修改CPSR寄存器T位,切入THUMB模式,在THUMB模式下执行一系列指令后,再次设法修改CPSR寄存器T位,切回ARM模式。这两种模式可以混着用。

☆ GDB中判断当前CPU模式

GDB里如何知道当前CPU模式是ARM模式还是THUMB模式?

参看:

《ARMv5 Architecture Reference Manual》

A1.1.3 Status registers (P31)
A2.5 Program status registers (P49)
A2.5.8 The T and J bits (P53)

CPSR寄存器的bit-5是T位(Thumb state flag),置1表示THUMB模式,置0表示ARM模式。

GDB中可以直接查看CPSR寄存器:

如果等于0x20,表示是THUMB模式,如果等于0,表示是ARM模式。

☆ ARM模式与THUMB模式的切换

1) 切换方案

参看:

《ARMv5 Architecture Reference Manual》
A2.6 Exceptions
A2.8.1 Unaligned instruction fetches (P76)
A3.3 Branch instructions (P113)
A3.10.1 CPSR value (P127)
A4.1.10 BX (P170)
A6.1.1 Entering Thumb state (P496)
A6.1.2 Exceptions (P497)
A6.3.3 Branch with exchange (P501)
A7.1.19 BX (P548)
A7.1.49 POP (P598)

异常处理始终在ARM模式进行,异常处理完成后靠SPSR恢复T位。

有多种方案修改CPSR寄存器T位,最常用的是BX指令,它无论如何都会修改T位,不管当前是哪种模式。BX指令的伪操作如下:

现实世界中很多代码利用BX指令从ARM模式切至THUMB模式,上述第一条伪操作给很多人带来误解,认为PC寄存器的bit-0用于确定CPU模式;事实上只有CPSR的T位用于确定CPU模式,仅仅是BX的Rm[0]可以为1,以此修改T位,而Rm被装载到PC寄存器时,Rm[0]被掩码按位与掉了,PC寄存器的bit-0永远为0,无论哪种模式。

ARM模式与THUMB模式的切换有多种具体实现,对于编写shellcode的人群,小结两种实现:

两种实现没有考虑规避’\0’或者出现在可打印字符范围这类问题。

如果觉得这里坑多,参看:

《ARMv5 Architecture Reference Manual》
A2.4.3 Register 15 and the program counter (P47)

When an instruction reads the PC, the value read depends on whichinstruction set it comes from:

For an ARM instruction, the value read is the address of the instructionplus 8 bytes. Bits [1:0] of this value are always zero, because ARM instructions are always word-aligned.

For a Thumb instruction, the value read is the address of the instruction plus 4 bytes. Bit [0] of this value is always zero, because Thumb instructions are always halfword-aligned.

2) arm_thumb_switch_1.s

arm_thumb_switch_1首先在ARM模式下运行,调用:

接着利用BX指令修改CPSR寄存器T位切入THUMB模式,在THUMB模式下调用:

再次利用BX指令修改CPSR寄存器T位切回ARM模式,在ARM模式下调用:

3) ELF for the ARM Architecture

ld时我故意没有指定”-s”,如果strip过,后面的实验会变。

objdump能识别出中部(0x10070)的THUMB模式代码,是因为符号表中有几个特殊符号($a、$t):

arm_thumb_switch_1中保留了as产生的$a、$t,objdump靠这些信息识别出中部(0x10070)的THUMB模式代码。

关于.symtab section中的$a、$t、$d,参看:

参看:

《ELF for the ARM Architecture》
《ARM Mapping Symbols》

此时objdump无法识别出中部的THUMB模式代码:

0x10070处THUMB模式代码按ARM模式反汇编了。注意,$a、$t是否存在只影响ELF工具的反汇编效果,不影响实际执行效果。

4) GDB中ARM模式与THUMB模式的切换

set arm fallback-mode (arm|thumb|auto)

gdb uses the symbol table, when available, to determine whether instructions are ARM or Thumb. This command controls gdb’s default behavior when the symbol table is not available. The default is auto, which causes gdb to use the current execution mode (from the T bit in the CPSR register).

GDB尝试寻找$a、$t,找不到时GDB按此设置切换模式。如果此设置是auto,GDB从CPSR中取T位来确定模式。

set arm force-mode (arm|thumb|auto)

This command overrides use of the symbol table to determine whether instructions are ARM or Thumb. The default is auto, which causes gdb to use the symbol table and then the setting of “set arm fallback-mode”.

若此设置为auto,GDB受”set arm fallback-mode”影响,否则完全不理符号表,强制使用指定模式。如果正在逆向非ELF格式的裸格式固件,忘了符号表吧。

如果CPU在THUMB模式,但某些地址处的代码实际是ARM模式的,此时可以

 

“set arm force-mode”、”set arm fallback-mode”默认均为auto,如果动态调试到某地址,”x/5i $pc”时没有问题,不必手工设置什么,GDB会根据CPSR中的T位自动确定模式。如果不使用上述设置,GDB有个邪门办法在ARM模式下强制查看THUMB模式代码:

这事你在GDB手册里可能找不到。注意显示出来的地址,其最低位均置1了。

5) IDA中指定ARM模式与THUMB模式

光标停在指令处,Alt-G,弹出”Segment Register Value”对话框,选中T/Value:

0 ARM模式,反汇编窗口显示”CODE32″
1 THUMB模式,反汇编窗口显示”CODE16″

☆ ARM汇编编程中的几个坑

这节就当是留给那些永远充满好奇心的读者的作业吧,针对arm_thumb_switch_1.s提几个小问题:

1) “.syntax divided”换成”.syntax unified”会如何
2) “.arch armv5te”换成”.arch armv6t2″会如何
3) “.arm”、”.thumb”这些Directives意义何在
4) 如果_start处一上来就是”.thumb”,ld命令该如何写
5) 为什么没有写成”add r1,pc,#0x3a”
6) “.align 2″意义何在

☆ 参考资源

[1] 《ARMv5 Architecture Reference Manual》
https://developer.arm.com/docs/ddi0100/latest/armv5-architecture-reference-manual

[2] 《ELF for the ARM Architecture》
http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044e/IHI0044E_aaelf.pdf

[3] 《ARM Mapping Symbols》
https://sourceware.org/binutils/docs/as/ARM_002dDependent.html

发表评论