u1timate
发布于 2025-03-03 / 20 阅读
0
0

2. 汇编基础

0x01 vitual stdio

  • 基于cpp实现汇编(内敛汇编),注意cpp实现的汇编只支持32位的,不支持64位的, 实现方式如下:

void main(){
  __asm {
    mov eax, 1
  • 原生开发,环境准备

    • 新建空项目

    • 新建源文件, 后缀名使用asm,文件名称必须使用英文

    • 定义项目的入口函数(汇编需要自定义)

      • 编写x86测试代码

    .586
    .MODEL flat, stdcall  
    .code
    main proc
    	mov eax,1
    main endp
    END main
    • 64位汇编

.code
main proc
	mov eax,1
main endp
END main

语法格式如下:

mov eax, 1
操作符 被操作数,操作的内容

0x02 寄存器

通用寄存器

  • EAX

  • EBX

  • ECX

  • EDX

E表示32位,R表示64位

  • EBP:EBP通常用于标记当前函数的栈帧的基址(栈底),这使得在执行过程中可以方便地访问函数的参数和局部变量。与ESP不同,EBP的值在函数内部通常是不变的,

  • ESP:ESP指向当前堆栈的顶部(栈顶)。栈在内存中通常是向下增长的,也就是说随着数据的压入(push),ESP的值会减小,而随着数据的弹出(pop),ESP的值会增大。

  • EIP:指向下一步运行的指针

  • ESI:指向字符串指针

0x03 内存

表现形式

MOV EAX,DWORD PTR DS:[0x03567783](立即数表现形式

MOV EBX,0x03567783

MOV EAX,DWORD PTR DS:[EBX](寄存器表现形式)

MOV EBX,0x03567783

MOV EAX,DWORD PTR DS:[EBX+4](偏移量表现形式1)

MOV EAX,0x03567783

MOV EBX,0x2

MOV ECX,DWORD PTR DS:[EAX+EBX*4](偏移量表现形式2)

0x04运算符

ADD destination, source

ADC destination, source


mov eax, 5        ; 将 5 加载到 EAX
add eax, 3        ; EAX = 5 + 3 = 8
;ADC 的作用是带进位加法,除了加法本身,还会将标志寄存器中进位标志 CF 的值加到运算结果中,有符合还是无符号的区别
//结果都在第一个
eax+ebx=eax

sub destination, source

结果存储在寄存器 EAX 中

sub eax, ebx
sbb eax,ebx

MUL operand

用于无符号乘法。当你使用 MUL EBX(或其他寄存器/内存)时,它会执行一个乘法操作,将累加器寄存器的值乘上指定操作数(如 EBX),结果存储在特定的寄存器(EAX)中。

imux operand

mul ebx
imul ebx  ;只有一个参数乘以的是eax

mov eax,2
mov ebx, 3
mul ebx
mov eax, eax

DIV operand

商在eax 余数在edx

两个数字做除法

商也是数字 余数也是数字

占的位数一样

mov eax, 6
mov ebx, 3
cdq
div ebx

堆栈操作

  • PUSH

push eax: 将eax中的数据压入栈中

  • POP

pop eax,直接弹栈顶内容到eax中

数据移动

  • MOV

mov eax,ebx ;将ebx中的数据传入eax中

  • LEA:计算内存地址的有效地址并将其加载到目的寄存器中。它只进行地址计算,不会访问实际的内存。

LEA destination, source


LEA EAX, [EBX + 4]
; 将 EBX 寄存器加上 4 的结果加载到 EAX 中
  • XCHG:(Exchange,交换)指令用于交换两个寄存器或一个寄存器与内存位置中的数据。执行此操作时不需要借助中间寄存器实现数据的交换。

XCHG destination, source

XCHG EAX, EBX
; 将 EAX 和 EBX 寄存器的值交换

比较

  • cmp:于比较两个操作数。它本质上是进行一次减法操作,但不存储结果,仅根据运算结果更新标志寄存器。

CMP destination, source

mov eax, 5          ; 将 5 加载到 EAX
cmp eax, 3          ; 比较 EAX 和 3(本质是 EAX - 3)
jge greater_or_equal ; 如果 EAX >= 3,跳转到 greater_or_equal
  • test:指令执行按位的 AND 操作,结果不存储,而是根据按位操作的结果更新标志寄存器。常用于测试特定位是否为 0,以及其他按位逻辑条件检查。

TEST destination, source

mov eax, 3          ; 将 3 加载到 EAX
test eax, eax       ; 测试 EAX 是否为非零(EAX & EAX)
jnz not_zero        ; 如果 EAX 非零,则跳转到 not_zero

跳转

JMP target :target:指跳转地址,可以是一个标号、相对地址、或使用寄存器和内存间接指定的地址。

  • jmp:无条件跳转

  • j(n)e:等于(不等于)跳转

  • j(n)z:等于(不等于)0 跳转

  • j(n)a: ig无符号的大于跳转

  • j(n)b:无符号的小于跳转

字符串

  • movs:指令组用于从源地址复制数据到目标地址。它移动一个字节、字(word)、双字(dword)、或四字(qword)的数据。

MOVS destination, source     ; 隐式使用寄存器,只需指定数据大小
MOVSB                        ; 逐字节(byte)移动
MOVSW                        ; 逐字(word,2字节)移动
MOVSD                        ; 逐双字(dword,4字节)移动
MOVSQ                        ; 逐四字(qword,8字节,64位模式下使用)
  • stos:指令组用于向内存中存储数据,典型场景是初始化一段内存地址或重复填充某个值到内存中。

STOSB                        ; 存储一个字节
STOSW                        ; 存储一个字(word,2 字节)
STOSD                        ; 存储一个双字(dword,4 字节)
STOSQ                        ; 存储一个四字(qword,8 字节,64 位模式下)
mov edi, buffer            ; 将目标内存地址加载到 EDI
mov al, 0xFF               ; 字节值 0xFF
mov ecx, 10                ; 填充 10 个字节
rep stosb                  ; 向内存写入 10 次 AL 的值

函数

call

指令用于跳转到一个子程序,同时它会保存当前执行点的返回地址,以便子程序完成后能够返回到调用点继续执行。

CALL target

call 函数名称(写汇编的时候是这么写的)

call 地址 (反汇编的时候是这么写的)

当我们call函数的时候如果有参数就得先把参数push进去

    ; 调用前准备参数
    push 5              ; 第一个参数 (5)
    push 10             ; 第二个参数 (10)

通过栈(Stack)传递参数时,函数参数的压栈顺序与 C 等高级语言中函数调用的书写顺序通常是相反的

int add(int x, int y) {
    return x + y;
}

int result = add(5, 10);  // 调用函数时,传入的参数为 5 和 10

生产汇编代码

push 10                ; 将第二个参数 (y) 压栈
push 5                 ; 将第一个参数 (x) 压栈
call add               ; 调用函数
add esp, 8             ; 调用者负责清理栈

ret

指令用于从子程序返回到调用点。
它会从栈中弹出一个地址(返回地址),并将程序流跳转到该地址继续执行。

RET                ; 默认从栈弹出返回地址
RET n              ; 返回时,同时调整栈指针,移除 n 个字节(用于清理栈 参数)。

ret (写汇编的时候是这么写的)返回

retn(反汇编的时候是这么写的)

0x05 PE结构

PE(Portable Executable,便携式可执行文件)结构 是 Windows 操作系统下的可执行文件格式,例如 .exe.dll。PE 文件基于更通用的 COFF(Common Object File Format,通用目标文件格式),为 Windows 提供了一种组织二进制文件的标准方式。

PE 文件是一个数据结构,它包含了加载和运行应用程序或动态链接库所需的所有信息。它包括了程序指令、全局变量、动态库引用(例如导入表和导出表)、资源(如图标和字符串)、调试信息等内容。

  • 主要组成部分

    • DOS头

    • DOS引导

    • NT Header

      • PE签名

      • 文件头

      • 可选头

    • Selection table:PE 文件中各节的目录,每一节都有相应的描述条目。

      • 每节保存不同类型的数据(如代码、变量、资源等)。

      • 常见的区节段包括:

        • .text:存储可执行代码。

        • .data:存储初始化的全局变量。

        • .rdata:存储只读数据。

        • .reloc:存储重定位信息。

        • .rsrc:存储资源信息(如图标、对话框等)。

    • selection:Section 是 PE 文件最关键的内容部分,存储了文件实际需要执行或使用的数据:

      • 程序代码(.text 节)。

      • 全局变量(.data 节)。

      • 动态链接库的导入/导出表。

      • 程序所需资源(如图标、对话框布局等)。

  • PE结构的作用

PE 结构是 Windows 系统加载、执行程序和动态库的基础,其主要作用包括以下几点:

  1. 文件的装载与执行

    • PE 文件包含了所有必要信息,指导操作系统的加载器(Loader)将其正确加载进内存,并运行。

    • 包含程序的入口点地址(Entry Point),即程序从哪条指令开始运行。

  2. 动态链接

    • 包括导入表和导出表,记录了程序使用的 DLL 函数或其自身提供给其他文件的接口。

    • 提供了模块化编程的能力,使程序可以动态加载共享库。

  3. 虚拟内存映射

    • PE 文件内的数据并不是直接加载进内存,而是通过节表组织数据并映射到虚拟内存的不同区域。

    • 通过节头部的虚拟地址(VA)来管理文件中逻辑地址与内存位置的映射。

  4. 资源管理

    • .rsrc 节存储了文件的资源,例如图标、字符串表、对话框模板等,为程序提供了一种统一读取资源的方式。

  5. 调试与维护

    • PE 文件中可以包含调试符号和代码的映射信息(如 .debug 节),方便开发者和调试工具对程序进行调试和跟踪。

  6. 安全性

    • 包含各种信息,如数字签名(在特定节内),以验证文件的完整性、防止篡改。

常用的类型

  • WORD类型,占4个位置,2个字节

  • DOWRD类型,占8个位置,4个字节

  • BYTE了类型,占2个位置,1个字节

#include<Windows.h>

_IMAGE_DOS_HEADER;
_IMAGE_NT_HEADERS;
_IMAGE_SECTION_HEADER;

IMAGE_DOS_HEADER;

#endif

typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
    WORD   e_magic;                     // Magic number   这里是需要重点关注的。 以5a 4d开头,表示PE(小端序读法)
    WORD   e_cblp;                      // Bytes on last page of file
    WORD   e_cp;                        // Pages in file
    WORD   e_crlc;                      // Relocations
    WORD   e_cparhdr;                   // Size of header in paragraphs
    WORD   e_minalloc;                  // Minimum extra paragraphs needed
    WORD   e_maxalloc;                  // Maximum extra paragraphs needed
    WORD   e_ss;                        // Initial (relative) SS value
    WORD   e_sp;                        // Initial SP value
    WORD   e_csum;                      // Checksum
    WORD   e_ip;                        // Initial IP value
    WORD   e_cs;                        // Initial (relative) CS value
    WORD   e_lfarlc;                    // File address of relocation table
    WORD   e_ovno;                      // Overlay number
    WORD   e_res[4];                    // Reserved words
    WORD   e_oemid;                     // OEM identifier (for e_oeminfo)
    WORD   e_oeminfo;                   // OEM information; e_oemid specific
    WORD   e_res2[10];                  // Reserved words
    LONG   e_lfanew;                    // File address of new exe header
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

WORD e_magic; // Magic numb er 标志位(Mz 4d5a 只占2字节)

LONG e_fanew; // File address of new exe header 偏移位置 // (一般接下来就是文件签名)

IMAGE_NT_HEADERS;

typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;  // 00 00 45 50  小端序读法
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} 

IMAGE_FILE_HEADER

typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine; //表示运行的架构  如0x8664
    WORD    NumberOfSections; //当前有多少区节段
    DWORD   TimeDateStamp; //文件是什么时候写好的,远一点的时间可以查ioc,比较近就是新的威胁情报
    DWORD   PointerToSymbolTable;
    DWORD   NumberOfSymbols;
    WORD    SizeOfOptionalHeader;
    WORD    Characteristics; //相关映射关系见下表,如果没有找到就看看是哪几个加在一起的,比如0x22 就是0x20+0x02
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;

Characteristic文件特征详细表


IMAGE_FILE_RELOCS_STRIPPED	0x0001	文件中移除了重定位信息,这表示文件必须装载到它的首选基址,如果基址不可用,加载器会报错。
IMAGE_FILE_EXECUTABLE_IMAGE	0x0002	表明该文件是一个可执行文件(无未解析的外部引用)。
IMAGE_FILE_LINE_NUMS_STRIPPED	0x0004	COFF 行号信息被移除(已经不再使用)。
IMAGE_FILE_LOCAL_SYMS_STRIPPED	0x0008	文件中已移除 COFF 符号表的条目(通常用于减小文件大小)。
IMAGE_FILE_AGGRESIVE_WS_TRIM	0x0010	激进地修剪工作集。这个标志已过时。
IMAGE_FILE_LARGE_ADDRESS_AWARE	0x0020	应用程序可以处理 2GB 以上的地址空间(即支持大地址空间)。
IMAGE_FILE_BYTES_REVERSED_LO	0x0080	低字节的字节顺序是反转的(已过时)。
IMAGE_FILE_32BIT_MACHINE	0x0100	目标机器支持 32 位字(即该文件是为 32 位架构编译的)。
IMAGE_FILE_DEBUG_STRIPPED	0x0200	调试信息被移除(通常用作发布版本)。
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP	0x0400	如果该文件位于可移动介质上,应将其复制到交换文件再运行。
IMAGE_FILE_NET_RUN_FROM_SWAP	0x0800	如果该文件是从网络运行的,运行前需要将其复制到交换文件。
IMAGE_FILE_SYSTEM	0x1000	该文件是一个系统文件。
IMAGE_FILE_DLL	0x2000	文件是一个 DLL 文件,不能直接运行,但可供其他程序动态加载和调用。
IMAGE_FILE_UP_SYSTEM_ONLY	0x4000	文件只能在单处理器系统上运行(不支持多线程/多处理器)。
IMAGE_FILE_BYTES_REVERSED_HI	0x8000	高字节的字节顺序是反转的(已过时)。

IMAGE_OPTIONAL_HEADER32 可选头

typedef struct _IMAGE_OPTIONAL_HEADER {
    //
    // Standard fields.
    //

    WORD    Magic; //文件类型标识,0x10B表示32位镜像文件,0x107表示一个ROM镜像,0x20B表示64位镜像文件
    BYTE    MajorLinkerVersion;  //链接器的主版本号
    BYTE    MinorLinkerVersion; // 链接器副版本号
    DWORD   SizeOfCode;  //text总大小
    DWORD   SizeOfInitializedData;
    DWORD   SizeOfUninitializedData;
    DWORD   AddressOfEntryPoint;
    DWORD   BaseOfCode;
    DWORD   BaseOfData;

    //
    // NT additional fields.
    //

    DWORD   ImageBase;
    DWORD   SectionAlignment;
    DWORD   FileAlignment;
    WORD    MajorOperatingSystemVersion;
    WORD    MinorOperatingSystemVersion;
    WORD    MajorImageVersion;
    WORD    MinorImageVersion;
    WORD    MajorSubsystemVersion;
    WORD    MinorSubsystemVersion;
    DWORD   Win32VersionValue;
    DWORD   SizeOfImage;
    DWORD   SizeOfHeaders;
    DWORD   CheckSum;
    WORD    Subsystem;
    WORD    DllCharacteristics;
    DWORD   SizeOfStackReserve;
    DWORD   SizeOfStackCommit;
    DWORD   SizeOfHeapReserve;
    DWORD   SizeOfHeapCommit;
    DWORD   LoaderFlags;
    DWORD   NumberOfRvaAndSizes;
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; 
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

WORD Magic; //文件类型标识,0x10B表示32位镜像文件,0x107表示一个ROM镜像,0x20B表示64位镜像文件

DWORD SizeOfCode; //text存储可执行代码的总大小

DWORD SizeOfInitializedData; 存储初始化的全局变量

DWORD SizeOfUninitializedData; bss总大小。

bss:BSS段通常是指用来存放程序中未初始化的或者初始化为0的全局变量和静态变量的一块内存区域。特点是可读写的,在程序执行之前BSS段会自动清0。

下面三个都是以偏移量表示(非常重要,需要记住)

DWORD AddressOfEntryPoint;程序的虚拟入口地址(运行起来的第一行代码的位置)

BaseofCode;代码基址DWORD,写代码的第一行

BaseOfData;数据基址DWORD

以上三个的值都是以偏移量的形式表示,最终的值是需要加上下面的imageBase

DWORD ImageBase;入口点,当加载进内存时镜像的第1个字节的首选地址。它必须是64K的倍数。

DLL默认是10000000H。WindowsCE的EXE默认是00010000H。Windows 系列的EXE默认是00400000H。

SectionAlignment;当加载进内存时节的对齐值(以字节计)(内存)DWORD

DWORD FileAlignment;用来对齐镜像文件的节中的原始数据的对齐因子(以字节计)(磁盘)

对齐

一个pe文件无论在磁盘和内存中存放都会进行对齐,但他们的对齐值会不相同。PE 文件头里边的FileAligment 定义了磁盘区块的对齐值。每一个区块从对齐值的倍数的偏移位置开始存放。而区块的实际代码或数据的大小不一定刚好是这么多,所以在多余的地方一般以00h 来填充,这就是区块间的间隙。PE文件头里边的SectionAligment 定义了内存中区块的对齐值。PE文件被映射到内存中时,区块总是至少从一个页边界开始。

WORD MajorOperatingSystemVersion;

WORDMinorOperatingSystemVersion;

WORDMajorlmageVersion;

WORDMinorlmageVersion;

WORDMajorSubsystemVersion;

WORDMinorSubsystemVersion;

以上全是版本号

DWORD Win32VersionValue;win32版本(必须为0)

DWORD SizeOflmage;总大小
DWORD SizeOfHeaders; 头的大小
DWORD CheckSum; 校验和,用来检测文件是否被修改

WORD Subsystem; 子系统,下面为子系统表

描述

0

未知子系统

1

设备驱动程序和Native Windows进程

2

Windows图形用户界面(GUI)子系统(一般程序)

3

Windows字符模式(CUI)子系统(从命令提示符后动的)

7

Posix字符模式子系统

9

Windows CE

10

可扩展固件接口(EFI)应用程序

11

带引导服务的EEI驱动程序

12

带运行时服务的EFI驱动程序

13

EFI ROM镜像

14

XBOX

WORD DllCharacteristics; dll特征

#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0X0040  // DLL can move. aslr随机地址关掉
#define IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY  0x0080 // Code Integrity Image
#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT  0x0100  // Image is NX compatible
#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION Ox0200  // Image understands isolatio
#define IMAGE_DLLCHARACTERISTICS_NO_SEH  0x0400  // Image does not use SEH. N
 //seh的保护机制
#define IMAGE_DLLCHARACTERISTICS_NO_BIND   0x0800   // Do not bind this image.  
//0x1000 Reserved.
#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000  // Driver uses WDM model
//大部分的d11都有这个
// 0x4000   Reserved.
#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE  0X8000

DWORDSizeOfStackReserve;栈保留大小

DWORD SizeOfStackCommit;栈申请大小

DWORDSizeOfHeapReserve;堆保留大小

DWORDSizeOfHeapCommit;堆申请大小

DWORDLoaderFlags;标志位(必须为0)

DWORD NumberOfRvaAndSizes;数据目录(16)

IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; API导入表存在的位置,

IMAGE_SECTION_HEADER 节头


typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];
    union {
            DWORD   PhysicalAddress;
            DWORD   VirtualSize;
    } Misc;
    DWORD   VirtualAddress;
    DWORD   SizeOfRawData;
    DWORD   PointerToRawData;
    DWORD   PointerToRelocations;
    DWORD   PointerToLinenumbers;
    WORD    NumberOfRelocations;
    WORD    NumberOfLinenumbers;
    DWORD   Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

BYTE NaMe[IMAGE SIZEOF SHORT NAME];本节的名字DWORD PhysicalAddress;本节的物理地址

DWORD Virtualsize;本节的实际大小

为什么有union大括号:2选1,通常选后面,因为不知道具体的物理地址

DWORD VirtualAddress;本节的RVA

DWORD SizeOfRawData;本节在磁盘中的大小

DWORD PointerToRawData;本节在磁盘中的偏移

DWORD PointerToRelocations;exe文件无意义

DWORD PointerToLinenumbers;行号表的位置(调试用,不过基本没用)

WORD NumberOfRelocations;重定位数量

WORD NumberOfLinenumbers;行号表数量

DWORD Characteristics;特征,特征类型如下


IMAGE_SCN_TYPE_NO_PAD	0x00000008	节数据不会对齐到文件边界,此标志已被弃用。
IMAGE_SCN_CNT_CODE	0x00000020	节包含可执行代码。
IMAGE_SCN_CNT_INITIALIZED_DATA	0x00000040	节包含已初始化的数据。
IMAGE_SCN_CNT_UNINITIALIZED_DATA	0x00000080	节包含未初始化的数据(BSS 段)。
IMAGE_SCN_LNK_OTHER	0x00000100	保留,不用于实际用途。
IMAGE_SCN_LNK_INFO	0x00000200	节包含注释或其他信息(仅在目标文件中使用)。
IMAGE_SCN_LNK_REMOVE	0x00000800	从最终的 PE 文件中移除该节(仅在目标文件中使用)。
IMAGE_SCN_LNK_COMDAT	0x00001000	节包含 COMDAT 数据(即重复节的消除,通常用于目标文件)。
IMAGE_SCN_GPREL	0x00008000	节中的数据是全局指针相对的。
IMAGE_SCN_MEM_PURGEABLE	0x00020000	保留标志。
IMAGE_SCN_MEM_LOCKED	0x00040000	保留标志。
IMAGE_SCN_MEM_PRELOAD	0x00080000	保留标志,指示节应该预先加载到内存中。
IMAGE_SCN_LNK_NRELOC_OVFL	0x01000000	节包含扩展重定位项,NumberOfRelocations 为 0xFFFF 表示超出 16 位字段限制。
IMAGE_SCN_MEM_DISCARDABLE	0x02000000	节可以被丢弃,例如在运行时不需要的初始化数据。
IMAGE_SCN_MEM_NOT_CACHED	0x04000000	节不可被缓存。
IMAGE_SCN_MEM_NOT_PAGED	0x08000000	节不可被分页 OUT(总是保持在内存中)。
IMAGE_SCN_MEM_SHARED	0x10000000	节可以在进程之间共享。
IMAGE_SCN_MEM_EXECUTE	0x20000000	节包含可执行代码。
IMAGE_SCN_MEM_READ	0x40000000	节包含可读取的数据。
IMAGE_SCN_MEM_WRITE	0x80000000	节包含可写入的数据。

实际用处

当我们遇到一些代码会释放文件这种操作的时候很重要,释放的位置是内存,我们不太好直接分析,这个时候就需要用到我们今天的知识来判断是否是pe,如果是,那么就下载这段内存重命名(判断exe还是dll),如果不是,就当shellcode处理

小端序

小端序(Little Endian) 是一种存储数据的字节序方式。在这种方式中,多字节数据的 低字节(最低有效字节, Least Significant Byte, LSB) 存放在内存的低地址,而 高字节(最高有效字节, Most Significant Byte, MSB) 存放在内存的高地址。

相对的,另一种方式叫 大端序(Big Endian),它将高字节存储在低地址,将低字节存储在高地址

小端序的特点:

  • 小端序是 Intel 体系结构(如 x86/x64) 的默认字节序。

  • 数据按从小到大的顺序存储在内存中,例如从最低有效字节开始。

  • 常用在现代 PC、嵌入式设备中,特别是基于 Intel 和 ARM 处理器(ARM 默认是小端序,但可以配置为大端序)。

例如,你写了一条汇编指令:

mov eax, 0x12345678

这一条指令会将 0x12345678 加载到寄存器 eax 中。然而在小端序的内存中,指令编码表示的内容可能是:

78 56 34 12

虽然你写的数值是 0x12345678,但小端序处理器将以从低到高的字节顺序存储它。

工具

  • XDPViewer

  • 010 Editor

  • python -> pefile


评论