菜单

处理器架构支持

相关源文件

介绍

本页介绍 Ghidra 如何实现对不同处理器架构的支持,从而能够在广泛的平台上对二进制文件进行逆向工程。处理器架构支持是 Ghidra 的核心功能之一,为反汇编、反编译和分析功能奠定了基础。

Ghidra 使用一套复杂的系统,通过规范文件(定义寄存器、指令、内存空间和语义行为)来建模处理器架构。这使得该工具能够准确地反汇编和反编译不同处理器的代码,而无需为每个处理器单独实现。

有关 x86 或 ARM 等特定架构支持的信息,请参阅 x86 架构支持ARM 架构支持。有关用于定义处理器规范的语言的详细信息,请参阅 处理器规范语言

架构概述

Ghidra 的处理器架构支持围绕一个由规范文件和运行时组件组成的系统构建,该系统将机器代码转换为 Ghidra 的中间表示。该系统旨在实现准确性和可扩展性。

来源: Ghidra/Processors/x86/data/languages/x86.ldefs Ghidra/Processors/ARM/data/languages/ARM.ldefs Ghidra/Processors/x86/data/languages/x86.slaspec Ghidra/Processors/ARM/data/languages/ARM.sinc

核心组件

处理器架构支持包含几个关键组件:

  1. 语言定义文件 (.ldefs):XML 文件,定义每个受支持处理器的元数据,包括字节序、地址大小和变体信息。

  2. SLEIGH 规范文件 (.slaspec, .sinc):使用 SLEIGH 规范语言定义处理器指令集、寄存器和语义的文件。

  3. 处理器规范文件 (.pspec):XML 文件,定义处理器特定行为,如堆栈指针寄存器、默认调用约定等。

  4. 编译器规范文件 (.cspec):XML 文件,定义给定处理器的编译器特定约定,如调用约定、数据组织等。

  5. SLEIGH 编译器:将规范文件转换为可由运行时组件使用的已编译规范文件 (.sla)。

这些组件协同工作,提供了处理器架构的完整描述,可供 Ghidra 的反汇编和反编译引擎使用。

来源: Ghidra/Processors/x86/data/languages/x86.ldefs1-121 Ghidra/Processors/ARM/data/languages/ARM.ldefs1-105

语言定义结构

语言定义文件 (.ldefs) 通过指定处理器的元数据并指向其规范文件,为处理器支持提供了入口点。每个处理器可以定义多个变体,以支持不同的模式或功能。

例如,x86 处理器有 16 位实模式、32 位保护模式和 64 位长模式的变体,而 ARM 处理器则有不同指令集版本(v4、v5、v7、v8)和字节序配置的变体。

以下是 x86 语言定义文件的一个示例:

<language processor="x86"
          endian="little"
          size="32"
          variant="default"
          version="4.4"
          slafile="x86.sla"
          processorspec="x86.pspec"
          manualindexfile="../manuals/x86.idx"
          id="x86:LE:32:default">
  <description>Intel/AMD 32-bit x86</description>
  <compiler name="Visual Studio" spec="x86win.cspec" id="windows"/>
  <compiler name="gcc" spec="x86gcc.cspec" id="gcc"/>
  <!-- Additional compilers and external names -->
</language>

来源: Ghidra/Processors/x86/data/languages/x86.ldefs4-35 Ghidra/Processors/ARM/data/languages/ARM.ldefs4-25

寄存器和内存空间定义

每个处理器架构都需要定义其寄存器和内存空间。这些定义在 SLEIGH 规范文件中,为所有指令和语义定义提供了基础。

以下是 ARM 的寄存器和空间定义示例:

define space ram type=ram_space size=4 default;
define space register type=register_space size=4;

define register offset=0x0020 size=4 [ r0 r1 r2 r3  r4  r5  r6  r7 r8 r9 r10 r11 r12 sp lr pc ];
define register offset=0x0060 size=1 [ NG ZR CY OV tmpNG tmpZR tmpCY tmpOV shift_carry TB Q GE1 GE2 GE3 GE4 ]; 
define register offset=0x0070 size=4 [ cpsr spsr ];

以及 x86 的示例:

define space ram type=ram_space size=$(SIZE) default;
define space register type=register_space size=4;

# General purpose registers
define register offset=0 size=4      [  EAX  ECX  EDX  EBX  ESP  EBP  ESI  EDI ];
define register offset=0 size=2      [  AX _ CX _ DX _ BX _ SP _ BP _ SI _ DI ];
define register offset=0 size=1      [  AL AH _ _ CL CH _ _ DL DH _ _ BL BH ];

这些定义建立了处理器的寄存器集,包括通用寄存器、状态寄存器和专用寄存器。对于 AVX 或 NEON 等 SIMD 扩展,还会定义额外的寄存器集。

来源: Ghidra/Processors/ARM/data/languages/ARM.sinc4-28 Ghidra/Processors/x86/data/languages/ia.sinc10-32

指令定义

处理器指令使用 SLEIGH 模式定义,将位模式映射到指令语义。这些定义是处理器架构支持的核心,因为它们决定了机器代码如何被解释并转换为 Ghidra 的中间表示(P-code)。

以下是指令定义结构的简化视图:

例如,这是 ARM ADC 指令的定义:

:adc^COND Rd,Rn,Rm is TMode=0 & ARMcond=1 & COND & c2027=0b0010101 & Rn & Rd & c0407=0b1001 & Rm
{
    build COND;
    local val = Rn + Rm + zext(CY);
    tmpCY = carry(Rn, Rm) || carry(Rn + Rm, zext(CY));
    tmpOV = scarry(Rn, Rm) ^^ scarry(Rn + Rm, zext(CY));
    Rd = val;
    resflags(val);
}

以及 x86 ADD 指令的定义:

:ADD^lockx m8,imm8 is vexMode=0 & lockx & unlock & $(BYTE_80_82); m8 & reg_opcode=0 ... ; imm8 
{ 
    build lockx; 
    build m8;
    addflags(m8, imm8:1); 
    resultflags(m8);
    build unlock;
}

这些定义包括匹配二进制编码的模式、助记符和操作数格式,以及描述指令行为的 P-code 语义。

来源: Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc607-641 Ghidra/Processors/x86/data/languages/lockable.sinc7-23

主要支持的架构

Ghidra 支持广泛的处理器架构,其中 x86/x64 和 ARM/AARCH64 的支持最为广泛。以下是一些主要受支持架构及其变体的表格:

架构变体描述
x86LE:32:default32 位 x86
LE:16:Real Mode16位实模式
LE:16:Protected Mode16位保护模式
LE:32:System Management Mode系统管理模式
x86-64LE:64:default64位 x86-64
LE:64:compat3264位 32位兼容模式
ARMLE:32:v8ARM/Thumb v8 小端序
LE:32:v8TARM/Thumb v8 (Thumb 默认)
BE:32:v8ARM/Thumb v8 大端序
LE:32:v7ARM/Thumb v7 小端序
BE:32:v7ARM/Thumb v7 大端序
LE:32:CortexARM Cortex/Thumb 小端序
AARCH64LE:64:v8AAARCH64 v8A 小端序
BE:64:v8AAARCH64 v8A 大端序

每个架构都支持多种变体,以处理不同的模式、指令集扩展和字节序配置。

来源: Ghidra/Processors/x86/data/languages/x86.ldefs4-120 Ghidra/Processors/ARM/data/languages/ARM.ldefs4-195

架构特定功能

x86 架构功能

x86 架构支持包括:

  1. 多种模式:支持 16 位实模式、16 位保护模式、32 位保护模式和 64 位长模式。
  2. 指令集扩展:支持 MMX、SSE、AVX、AVX2、AVX-512 和其他扩展。
  3. 调用约定:支持多种编译器特定的调用约定(cdecl、stdcall、fastcall 等)。

指令集扩展作为单独的包含文件 (sinc 文件) 实现,根据处理器变体选择性地包含。

@include "ia.sinc"
@include "lockable.sinc"
with : lockprefx=0 {
@include "avx.sinc"
@include "avx_manual.sinc"
@include "avx2.sinc"
@include "avx2_manual.sinc"
@include "avx512.sinc"
@include "avx512_manual.sinc"
}

来源: Ghidra/Processors/x86/data/languages/x86.slaspec1-9 Ghidra/Processors/x86/certification.manifest1-105

ARM 架构功能

ARM 架构支持包括:

  1. 指令集:支持 ARM、Thumb、Thumb-2 和 ThumbEE 指令集。
  2. SIMD 扩展:支持 NEON/高级 SIMD 指令。
  3. VFP:支持向量浮点协处理器指令。
  4. 字节序:支持小端序和大端序模式。
  5. 混合字节序:支持指令和数据字节序不同的配置。

ARM 指令集支持被组织成不同指令集版本和扩展的包含文件。

@if defined(SIMD) || defined(VFPv2) || defined(VFPv3)
@define INCLUDE_NEON "" # Neon instructions included with SIMD, VFPv2 or VFPv3
@endif

@if defined(T_VARIANT)
@define AMODE   "TMode=0"  # T_VARIANT must restrict ARM instruction decoding and require TMode=0
@else
@define AMODE "epsilon"    # THUMB instructions not supported - ARM only
@endif

ARM 还支持 ARM 和 Thumb 指令集之间的上下文切换,这通过 TMode 上下文变量处理。

define context contextreg
@ifdef T_VARIANT
  TMode           = (0,0)    # 1 if in Thumb instruction decode mode
  T               = (0,0)    # exact copy (alias!) of TMode
  LowBitCodeMode  = (0,0)    # 1 if low bit of instruction address is set on a branch
  ISA_MODE        = (0,0)    # 1 for Thumb instruction decode mode
@endif

来源: Ghidra/Processors/ARM/data/languages/ARMinstructions.sinc1-25 Ghidra/Processors/ARM/data/languages/ARM.sinc78-93

与反编译器集成

处理器架构规范对反编译器至关重要,因为它们提供了将机器代码转换为 Ghidra 的中间表示(P-code)的功能,而反编译器就是分析这种表示。

关键集成点包括

  1. P-code 生成:处理器规范定义了机器指令如何转换为 P-code 操作。
  2. 调用约定:编译器规范定义了函数参数和返回值如何传递。
  3. 寄存器使用:处理器规范定义了寄存器角色(例如,堆栈指针、帧指针)。
  4. 数据组织:编译器规范定义了数据类型大小和对齐要求。

来源: Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/app/plugin/assembler/sleigh/ARMAssemblyTest.java21-138 Ghidra/Processors/ARM/data/languages/ARM_win.cspec1-10 Ghidra/Processors/AARCH64/data/languages/AARCH64_win.cspec1-31

测试与验证

处理器架构支持通过广泛的测试进行验证:

  1. 反汇编测试:验证指令是否正确反汇编。
  2. 汇编测试:验证反汇编的指令是否可以正确重新汇编。
  3. 语义测试:验证指令语义是否正确实现。

例如,ARM 汇编测试套件测试了各种指令形式。

来源: Ghidra/Framework/SoftwareModeling/src/test/java/ghidra/app/plugin/assembler/sleigh/ARMAssemblyTest.java31-95

添加新架构支持

添加对新处理器架构的支持涉及创建必要的规范文件:

  1. 语言定义 (.ldefs):定义新处理器的元数据。
  2. SLEIGH 规范 (.slaspec, .sinc):定义寄存器、指令和语义。
  3. 处理器规范 (.pspec):定义处理器特定行为。
  4. 编译器规范 (.cspec):定义编译器特定约定。

该过程通常涉及

  1. 研究处理器的指令集架构文档。
  2. 创建寄存器和空间定义。
  3. 实现指令模式和语义。
  4. 测试和完善实现。

对于复杂的架构,通常可以从类似的现有架构作为模板开始。

来源: Ghidra/Processors/ARM/data/languages/ARM.opinion1-4 Ghidra/Processors/AARCH64/certification.manifest1-9

结论

Ghidra 的处理器架构支持为逆向工程各种二进制文件提供了灵活而强大的基础。SLEIGH 规范语言允许对处理器行为进行详细建模,而模块化设计则易于扩展以支持新架构。

架构支持与 Ghidra 的反编译器和分析功能集成,可在多个平台上实现高级逆向工程功能。每个受支持的架构都经过严格测试,以确保准确的反汇编、反编译和分析。

有关特定架构的更详细信息,请参阅以下链接页面:x86 架构支持ARM 架构支持处理器规范语言