PE文件结构

PE文件是Windows系统下可执行文件的总称,英文全称 Portable Executable 可移植的可执行文件,常见的有exe、dll、sys、com、ocx

对于学习反(木马、免杀、病毒、外挂、内核),了解PE文件结构是非常有必要且非常非常重要的!

PE结构包括:

  • MS-DOS头
  • 标准PE头
  • 扩展PE头
  • 数据目录
  • 节表

代码段(.text 或 .code): 可读 可执行 不可写

数据段(.data 或 .rdata 或.bss): 可读 可写 不可执行

未初始化数据段(.bss):可读 可写 不可执行

资源段(.rsrc): 可读 不可执行 不可写

导入表(.idata) : 简称 IAT 表 Import Address Table

导出表(.edata): 简称 EAT 表 Export Address Table

IMAGE_DOS_HEADER (长度不定)

MZ标记: 4D5A EXE程序的标志 在DOS头里 4字节

DOS_STUB (长度不定)

DOS STUB : 在dos系统下,会执行 DOS Stub 中的内容,不会出现不可预料的错误

IMAGE_NT_HEADERS (f8h)

PE Signature: PE标记 MZ偏移3C的位置 是e_lfanew 指向PE标记 PE头相对于文件的偏移地址 4字节

IMAGE_FILE_HEADER PE文件头 (14h)

Machine : PE标记后2个字节是Machine 14C代表32位CPU 8664代表64位CPU 2字节

NumberOfSections: 代表区段数量 代码段 数据段 资源段 2字节

Timestamp: 时间戳,文件创建时间, 表示从1970年1月1日 00:00:00 到文件创建时间的秒数 4字节

PointerOfSymbolTable: 用于调试 4字节

NumberOfSymbols: 用于调试 4字节

SizeOfOptionalHeader: 可选头大小 e0h 2字节

Characteristics: 文件信息标志 如dll/exe 2字节

IMAGE_OPTIONAL_HEADER 可选PE头 (e0h)

Magic :代表文件的格式 010b是32位应用程序 020b是64位应用程序 107是系统的ROM文件 2字节

Major LinkerVersion : 连接器首版本号 1字节

Minor LinkerVersion : 连接器次版本号 1字节

SizeOfCode : 代码块大小 4字节 (512为一个磁盘扇区)

SizeOfInitializedData : 已初始化数据块大小 4字节 也就是.data

SizeOfUninitializedData : 未初始化数据块大小 4字节 也就是.data

AddressOfEntryPoint : 程序执行入口(OEP) 4字节 RVA(相对偏移)(相对虚拟内存地址)

BaseOfCode: 代码块起始RVA 4字节 表示代码段起始RVA

BaseOfData : 数据块起始RVA 4字节 表示数据段的起始RVA

ImageBase: 基址 4字节 入口点

EXE,DLL文件被装载到用户内存的0~7FFFFFFF中,SYS文件被加载到80000000~FFFFFFFF中

执行PE文件的时候。PE装载器先创建进程,再将文件载入内存,然后把EIP寄存器的值设置为ImageBase+AddressOfEntryPoint

BaseofCode + ImageBase可以得到代码段的起始地址

BaseOfData + ImageBase可以得到数据段段的起始地址

SectionAlignment: 块对齐值 4字节

FileAlignment : 文件对齐值 4字节

Major Operating System Version : 操作系统首版本号 2字节

Minor Operating SystemVersion: 操作系统次版本号 2字节

Major Image Version:用户程序首版本号 2字节

Minor Image Version:用户程序次版本号 2字节

MajorSub System Version :子系统首版本号 2字节

MinorSub System Version :子系统次版本号 2字节

Win32 Version Value : 32位系统版本号值 4字节

SizeOfImage : 整个程序在内存中占用的空间(PE映像尺寸)映像大小 4字节

SizeOfHeaders : 块前头部大小 4字节 所有头(头的结构体大小)+节表的大小

Checksum : 校验和 4字节 对于驱动程序,可能会使用

SubSystem : 程序运行所需子系统 2字节 重要

DICharacteristics:当文件为dll文件时使用 2字节

SizeOf StackReserve :保留栈大小 4字节

SizeOf StackCommit :使用栈大小 4字节

SizeOf HapReserve : 保留堆大小 4字节

SizeOf HeapCommit : 使用堆大小 4字节

LoaderFlags : 设置自动调用断点或调试器 4字节 与调试有关

NumberOfRvaAndSizes: Rva的大小的数量 4字节 下面的成员,数据目录结构的项目数量

DataDirectory : Image_Data Directorys 80字节 数据目录,默认16个,16是宏,这里方便直接写成16

SECTION TABLE (长度不定)

IMAGE_SECTION_HEADER (28h)

Name :块名 8字节

VirtualSize: 内存中快大小 4字节

VirtusalAddress: 内存中块RVA值 4字节

SizeOfRawData:文件中块大小 4字节

PointerToRawData:文件中块偏移 4字节

PointerToRelocations: OBJ文件使用 4字节

PointerToLineNumbers: OBJ文件使用 4字节

NumberOfRelocations : OBJ文件使用 2字节

NumberOfLineNumbers : OBJ文件使用 2字节

Characteristics : 块属性

  • RVA 相对虚拟地址,映像文件在虚拟内存中相对于加载基址的偏移。
  • VA 虚拟地址,映像文件在虚拟内存中的地址。
  • FOA 文件偏移地址,映像文件在磁盘文件中相对于文件开头的偏移。

三个地址概念:

  • VA:( Virtual Address )虚拟内存地址,范围00000000h - 0FFFFFFFh,就是进程的基地址 + RVA相对虚拟内存地址
  • RVA:相对虚拟内存地址,RVA是相对某个模块而存在的
  • FOA:文件偏移地址,文件头的偏移地址

VA = ImageBase + RVA

RVA = VA - ImageBase

PE头部分用于宏观上记录文件的一些信息,运行平台,大小,创建日期,属性等

节表部分用于对各中类型的数据进行定义分段

节数据就是文件的数据部分,实际上我们编写程序的过程中就是对该部分的数据进行编写。

而其他的部分则是由编译器依照我们编写的部分进行相应的填写而得到

DOS头结构

在winnt.h里已经定义了,在使用的时候包含windows.h头文件即可

#include<Windows.h>

DOS头的结构体

typedef struct _IMAGE_DOS_HEADER {  // DOS-MZ文件头   
WORD   e_magic;                     // DOS 可执行文件的标识符      +0h
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;                    // 指向PE文件头   +3ch
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

其中e_magic 和 e_lfanew 比较重要, e_magic 为 "MZ" ,e_lfanew 字段是真正PE文件的相对偏移(RVA)

typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature; //该结构体中的Signature就是PE签名,标识该文件是否是PE文件。该部分占4字节,即“50 45 0000”。
    IMAGE_FILE_HEADER FileHeader;       //20字节
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;  //32位0xE0字节 64位0xF0字节
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;    //64位是PIMAGE_NT_HEADERS64
typedef struct _IMAGE_FILE_HEADER {
    WORD Machine;  // 程序允许的cpu型号,为0代表所有     重要成员
    WORD NumberOfSections;  // 节区数量           重要成员
    DWORD TimeDateStamp;  // 自1970年1月1日00:00起的秒数的低 32 位 (C 运行时time_t值) ,该值指示文件创建时间。
    DWORD PointerToSymbolTable; // COFF符号表的文件偏移量,如果没有COFF符号表,则为零。映像的此值应为零,因为 COFF 调试信息已弃用。
    DWORD NumberOfSymbols;  // 符号表中的条目数。此数据可用于查找紧跟在符号表后面的字符串表。映像的此值应为零,因为 COFF 调试信息已弃用。
    WORD SizeOfOptionalHeader;  // 可选标头的大小,这是可执行文件所必需的 32位默认E0 64位默认F0   重要成员
    WORD Characteristics;  // 指示文件属性的标志。 文件属性,每个位有不同含义  可判断是否存在重定位信息,很重要	   重要成员
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
IMAGE_OPTIONAL_HEADER {
    WORD    Magic;                                 // +0018h   -   用于标识32/64位文件 PE32: 10B PE64: 20B
    BYTE    MajorLinkerVersion;                    // +001ah   -   链接器版本号
    BYTE    MinorLinkerVersion;                    // +001bh   -   
    DWORD   SizeOfCode;                            // +001ch   -   所有代码段的总大小 按照FileAlignment对齐后的大小 编译器填入 无用
    DWORD   SizeOfInitializedData;                 // +0020h   -   所有已初始化数据区块的大小 按文件对齐 编译器填入 没用(可改)
    DWORD   SizeOfUninitializedData;               // +0024h   -   所有未初始化数据区块的大小 按文件对齐 编译器填入 没用(可改)
    DWORD   AddressOfEntryPoint;      重要成员      // +0028h   -   程序执行入口OEP RVA
    DWORD   BaseOfCode;                            // +002ch   -   代码节的起始RVA
    DWORD   BaseOfData;                            // +0030h   -   数据节的起始RVA
    DWORD   ImageBase;            重要成员          // +0034h   -   程序的建议装载地址 内存镜像基址(程序默认载入基地址)
    DWORD   SectionAlignment;     重要成员          // +0038h   -   内存中的节的对齐粒度
    DWORD   FileAlignment;        重要成员          // +003ch   -   文件中的节的对齐粒度
    WORD    MajorOperatingSystemVersion;           // +0040h   -   操作系统版本号
    WORD    MinorOperatingSystemVersion;           // +0042h   -   
    WORD    MajorImageVersion;                     // +0044h   -   该PE的版本号
    WORD    MinorImageVersion;                     // +0046h   -   
    WORD    MajorSubsystemVersion;                 // +0048h   -   所需子系统的版本号
    WORD    MinorSubsystemVersion;                 // +004ah   -   
    DWORD   Win32VersionValue;                     // +004ch   -   未用
    DWORD   SizeOfImage;         重要成员           // +0050h   -   内存中的整个PE映像尺寸,可比实际值大,必须是SectionAlignment的整数倍
    DWORD   SizeOfHeaders;       重要成员           // +0054h   -   所有头+节表的大小 对齐之后的值
    DWORD   CheckSum;                              // +0058h   -   校验和  映像校验和,一些系统.dll文件有要求,判断是否被修改
    WORD    Subsystem;                             // +005ch   -   文件的子系统
    WORD    DllCharacteristics;                    // +005eh   -   DLL文件特性,,不是针对DLL文件的,16进制转换2进制可以根据属性对应的表格得到相应的属性
    DWORD   SizeOfStackReserve;                    // +0060h   -   初始化时的栈大小
    DWORD   SizeOfStackCommit;                     // +0064h   -   初始化时实际提交的栈大小
    DWORD   SizeOfHeapReserve;                     // +0068h   -   初始化时保留的堆大小
    DWORD   SizeOfHeapCommit;                      // +006ch   -   初始化时实际提交的堆大小
    DWORD   LoaderFlags;                           // +0070h   -   与调试有关
    DWORD   NumberOfRvaAndSizes;  重要成员          // +0074h   -   下面的数据目录结构的项目数量
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];     // 0078h   -   数据目录
}
IMAGE_DATA_DIRECTORY {
    DWORD   VirtualAddress;                 // +0000h   -   数据的起始RVA
    DWORD   Size;                           // +0004h   -   数据块的长度
}
 IMAGE_SECTION_HEADER {              
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];   // +0000h   -   8个字节节名   重要成员
    union {
            DWORD   PhysicalAddress;
            DWORD   VirtualSize;        重要成员  // 区段大小,没做对齐之前的大小
    } Misc;                                  // +0008h   -   节区的尺寸
    DWORD   VirtualAddress;    重要成员       // +000ch   -   节区的RVA地址
    DWORD   SizeOfRawData;                   // +0010h   -   在文件中对齐后的尺寸
    DWORD   PointerToRawData;     重要成员    // +0014h   -   在文件中的偏移
    DWORD   PointerToRelocations;            // +0018h   -   在OBJ文件中使用
    DWORD   PointerToLinenumbers;            // +001ch   -   行号表的位置(供调试用)
    WORD    NumberOfRelocations;             // +0020h   -   在OBJ文件中使用
    WORD    NumberOfLinenumbers;             // +0022h   -   行号表中行号的数量
    DWORD   Characteristics;    重要成员      // +0024h   -   节的属性
}
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    union {
        DWORD   Characteristics;            // 0 for terminating null import descriptor
        DWORD   OriginalFirstThunk;         // RVA 指向 INT (PIMAGE_THUNK_DATA结构数组)
    } DUMMYUNIONNAME;
    DWORD   TimeDateStamp;                  // 0 if not bound,
                                            // -1 if bound, and real date\time stamp
                                            //     in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
                                            // O.W. date/time stamp of DLL bound to (Old BIND)

    DWORD   ForwarderChain;                 // -1 if no forwarders
    DWORD   Name;							//RVA指向dll名字,以0结尾
    DWORD   FirstThunk;                     // RVA 指向 IAT (PIMAGE_THUNK_DATA结构数组)
} IMAGE_IMPORT_DESCRIPTOR;
typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;
typedef struct _IMAGE_IMPORT_BY_NAME {
    WORD    Hint; //可能为空,编译器决定,如果不为空,是函数在导出表的索引
    BYTE    Name[1]; //函数名称,以0结尾
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

#include "pshpack8.h"                       // Use align 8 for the 64-bit IAT.

typedef struct _IMAGE_THUNK_DATA64 {
    union {
        ULONGLONG ForwarderString;  // 指向一个转向者字符串的RVA
        ULONGLONG Function;         // 被输入的函数的内存地址
        ULONGLONG Ordinal;			// 被输入API的序数值
        ULONGLONG AddressOfData;    // 指针指向 IMAGE_IMPORT_BY_NAME
    } u1;
} IMAGE_THUNK_DATA64;
typedef IMAGE_THUNK_DATA64 * PIMAGE_THUNK_DATA64;

#include "poppack.h"                        // Back to 4 byte packing

typedef struct _IMAGE_THUNK_DATA32 {
    union {
        DWORD ForwarderString;      // PBYTE 
        DWORD Function;             // PDWORD
        DWORD Ordinal;
        DWORD AddressOfData;        // PIMAGE_IMPORT_BY_NAME
    } u1;
} IMAGE_THUNK_DATA32;
typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;
typedef struct _IMAGE_EXPORT_DIRECTORY {
    DWORD   Characteristics;        //保留段,值为00,特征值
    DWORD   TimeDateStamp;          //导出表创建时间
    WORD    MajorVersion;           //导出表主版本号
    WORD    MinorVersion;           //导出表子版本号
    DWORD   Name;					// 指针指向该导出表文件名字符串
    DWORD   Base;					// 导出函数起始序号
    DWORD   NumberOfFunctions;		// 所有导出函数的个数
    DWORD   NumberOfNames;			// 以函数名字导出的函数个数
    DWORD   AddressOfFunctions;     // 指针指向导出函数地址表RVA
    DWORD   AddressOfNames;         // 指针指向导出函数名称表RVA
    DWORD   AddressOfNameOrdinals;  // 指针指向导出函数序号表RVA
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

正常情况下,dll才有导出表

typedef struct _IMAGE_BASE_RELOCATION {
    DWORD   VirtualAddress; // 重定位数据的开始 RVA 地址
    DWORD   SizeOfBlock;	// 重定位块的长度
//  WORD    TypeOffset[1];	// 重定位项数组
} IMAGE_BASE_RELOCATION;
typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;
typedef struct _IMAGE_TLS_DIRECTORY32 {
    DWORD   StartAddressOfRawData;		// 内存起始地址
    DWORD   EndAddressOfRawData;		//内存结束地址
    DWORD   AddressOfIndex;             // PDWORD
    DWORD   AddressOfCallBacks;         // PIMAGE_TLS_CALLBACK *
    DWORD   SizeOfZeroFill;				// 0填充区域长度
    union {
        DWORD Characteristics;			//保留字段
        struct {
            DWORD Reserved0 : 20;
            DWORD Alignment : 4;
            DWORD Reserved1 : 8;
        } DUMMYSTRUCTNAME;
    } DUMMYUNIONNAME;

} IMAGE_TLS_DIRECTORY32;
typedef IMAGE_TLS_DIRECTORY32 * PIMAGE_TLS_DIRECTORY32;

TLS表 存在TSL区段里:线程局部存储,会在程序运行之前执行完毕,用于反调试

typedef struct _IMAGE_DELAYLOAD_DESCRIPTOR {
    union {
        DWORD AllAttributes;
        struct {
            DWORD RvaBased : 1;             // Delay load version 2
            DWORD ReservedAttributes : 31;
        } DUMMYSTRUCTNAME;
    } Attributes;

    DWORD DllNameRVA;                       // RVA to the name of the target library (NULL-terminate ASCII string)
    DWORD ModuleHandleRVA;                  // RVA to the HMODULE caching location (PHMODULE)
    DWORD ImportAddressTableRVA;            // RVA to the start of the IAT (PIMAGE_THUNK_DATA)
    DWORD ImportNameTableRVA;               // RVA to the start of the name table (PIMAGE_THUNK_DATA::AddressOfData)
    DWORD BoundImportAddressTableRVA;       // RVA to an optional bound IAT
    DWORD UnloadInformationTableRVA;        // RVA to an optional unload info table
    DWORD TimeDateStamp;                    // 0 if not bound,
                                            // Otherwise, date/time of the target DLL

} IMAGE_DELAYLOAD_DESCRIPTOR, *PIMAGE_DELAYLOAD_DESCRIPTOR;

导入表(Import Table)

  • 导入表包含了程序对外部DLL函数的引用,包括函数的名字和所在的DLL名称。
  • 在编译阶段,链接器会生成导入表,其中的条目用于告诉加载器程序需要哪些外部函数。
  • 导入表中通常包含IMAGE_IMPORT_DESCRIPTOR结构,它描述了导入的DLL和函数列表。

IAT(Import Address Table)

  • IAT是在程序加载到内存时由操作系统动态填充的,它存储了从导入表中列出的DLL函数的实际内存地址。
  • 当程序加载时,加载器会解析导入表,加载所需的DLL,并将DLL中函数的实际地址填入IAT。
  • 程序执行时,它通过IAT中的地址来调用外部DLL的函数。

----------------------------------------------------------------------------------------------------------------------------

IMAGE_DOS_HEADER DOS头 0x40(64)字节

typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
    WORD   e_magic;                     // MZ标记                  勿改
    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;                    // PE头偏移                  勿改
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

仅使用了两个成员 , 其他成员都可以修改

e_magic 0x5A4D

0 + e_lfanew = PE标记

e_lfanew 到 PE标记 之间的数据为 DOS_STUB , 可随意修改

IMAGE_NT_HEADER NT头 32位: 0xF8(248)字节 64位: 0x108(264)字节

typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;                         //PE标记   0x00004550 
    IMAGE_FILE_HEADER FileHeader;            //标准PE头  0x14(20)字节
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;  //可选PE头  32位默认大小为0xE0
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

typedef struct _IMAGE_NT_HEADERS64 {
    DWORD Signature;                         //PE标记   0x00004550 
    IMAGE_FILE_HEADER FileHeader;            //标准PE头  0x14(20)字节
    IMAGE_OPTIONAL_HEADER64 OptionalHeader;  //可选PE头  64位默认大小为0xF0
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;

PE标记必须为0x00004550 , 否则程序无法启动

IMAGE_FILE_HEADER 标准PE头 0x14(20)字节

typedef struct _IMAGE_FILE_HEADER {
    WORD    Machine;                         //运行平台  0x014c 或 0x8664    
    WORD    NumberOfSections;                //节区数量                     
    DWORD   TimeDateStamp;                   //文件创建时间戳   可抹零
    DWORD   PointerToSymbolTable;            //指向符号表(用于调试)
    DWORD   NumberOfSymbols;                 //符号表中符号个数(用于调试)
    WORD    SizeOfOptionalHeader;            //可选头大小  32位:0xE0  64位:0xF0  
    WORD    Characteristics;                 //文件属性  由位组成                 
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
#define IMAGE_SIZEOF_FILE_HEADER             20

IMAGE_OPTIONAL_HEADER 可选PE头 32位默认大小为0xE0(224)字节 64位大小为0xF0(240)字节

typedef struct _IMAGE_OPTIONAL_HEADER {
    WORD    Magic;                        //镜像文件的状态,用于判断程序是32位还是64位
    BYTE    MajorLinkerVersion;           //链接器版本号
    BYTE    MinorLinkerVersion;           //链接器次要版本号
    DWORD   SizeOfCode;                   //代码段的大小(以字节为单位),如果有多个代码段,则为所有这些代码段的总和。是文件对齐后的大小 编译器填的 没用(不一定准确)
    DWORD   SizeOfInitializedData;        //已初始化数据段的大小(以字节为单位),如果有多个初始化数据段,则为所有这些数据段的总和。是文件对齐后的大小 编译器填的 没用(不一定准确)
    DWORD   SizeOfUninitializedData;      //未初始化数据段的大小(以字节为单位),如果有多个未初始化数据段,则为所有这些数据段的总和。是文件对齐后的大小 编译器填的 没用(不一定准确)
    DWORD   AddressOfEntryPoint;     //RVA 一个指向入口点函数的指针,相对于ImageBase, 1.对于可执行文件,这是起始地址 2.对于设备驱动程序,这是初始化函数的地址3.入口点函数对于dll是可选的。当没有入口点存在时,该成员为零 
    DWORD   BaseOfCode;              //代码段RVA 指向代码段开头的指针,相对于ImageBase。编译器填的  没用(不一定准确)
    DWORD   BaseOfData;              //数据段RVA 指向数据段开头的指针,相对于ImageBase。编译器填的  没用(不一定准确)
    DWORD   ImageBase;               //内存镜像基址 exe默认0x400000,dll默认0x10000000
    DWORD   SectionAlignment;        //加载到内存中的节的对齐方式,以字节为单位。该值必须大于或等于FileAlignment(文件对齐)成员。默认值是系统的页面大小
    DWORD   FileAlignment;           //Image(PE文件)中各节的原始数据(以字节为单位)的对齐方式。该值应该是512到64K(包括)之间2的幂。缺省值是512。如果SectionAlignment成员小于系统页面大小,则该成员必须与SectionAlignment相同
    WORD    MajorOperatingSystemVersion;       //所需操作系统的主要版本号
    WORD    MinorOperatingSystemVersion;       //所需操作系统的次要版本号
    WORD    MajorImageVersion;                 //镜像(PE文件)的主版本号
    WORD    MinorImageVersion;                 //镜像(PE文件)的次要版本号
    WORD    MajorSubsystemVersion;             //子系统的主要版本号
    WORD    MinorSubsystemVersion;             //子系统的次要版本号
    DWORD   Win32VersionValue;                 //保留,并且必须为0
    DWORD   SizeOfImage;                       //映像装入内存后的总大小
    DWORD   SizeOfHeaders;                     //DOS头、PE头、区块表总大小 文件对齐后大小
    DWORD   CheckSum;                          //Image(PE文件)校验和
    WORD    Subsystem;                         //运行此映像所需的子系统
    WORD    DllCharacteristics;                //Image的DLL特性
    DWORD   SizeOfStackReserve;                //为堆栈保留的字节数
    DWORD   SizeOfStackCommit;                 //要提交给堆栈的字节数
    DWORD   SizeOfHeapReserve;                 //为本地堆保留的字节数
    DWORD   SizeOfHeapCommit;                  //要为本地堆提交的字节数
    DWORD   LoaderFlags;                       //该成员已过时,与调试有关,默认为 0 
    DWORD   NumberOfRvaAndSizes;               //数据目录表的项数 
    IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; // 数据目录表
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

ImageBase + AddressOfEntryPoint (RVA) = 程序真正执行地址 (OEP)

ImageBase + 相对虚拟地址(RVA) = 虚拟内存地址(VA)

VA - ImageBase = 相对虚拟地址(RVA)

文件偏移地址(FOA)

IMAGE_DATA_DIRECTORY 数据目录表

#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES    16

typedef struct _IMAGE_DATA_DIRECTORY {
    DWORD   VirtualAddress;                    //数据块的起始RVA
    DWORD   Size;                              //目录项大小
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

导出表 / 导入表 / 重定位表 / IAT表

IMAGE_SECTION_HEADER 节表 每个40字节

#define IMAGE_SIZEOF_SECTION_HEADER          40
#define IMAGE_SIZEOF_SHORT_NAME              8

typedef struct _IMAGE_SECTION_HEADER {
    BYTE    Name[IMAGE_SIZEOF_SHORT_NAME];     //节名称 8字节 \0结尾的ASCII码字符串 可自定义
    union                                      //8字节
    {
            DWORD   PhysicalAddress;           //节的文件地址
            DWORD   VirtualSize;               //节内存中大小
    } Misc;
    DWORD   VirtualAddress;                    //(RVA)节在内存中的偏移地址
    DWORD   SizeOfRawData;                     //节在文件中的大小  对齐后
    DWORD   PointerToRawData;                  //(FOA)节在文件中的偏移地址
    DWORD   PointerToRelocations;              //.obj文件有效,重定位的偏移  
    DWORD   PointerToLinenumbers;              //调试相关
    WORD    NumberOfRelocations;               //.obj文件有效,重定位项数目  
    WORD    NumberOfLinenumbers;               //行号表中行号的数量
    DWORD   Characteristics;                   //节属性 可读 可写 可执行 60000020 
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

.data 初始化的数据

.idata 导入表

.rsrc 资源数据

.reloc 基地址重定位表

.edata 导出表

.tls thread local storage 线程局部存储器

.rdata 存放调试目录和说明字符串

最后一个节区之后的40个字节 必须为0

IMAGE_EXPORT_DIRECTORY 导出表

#define IMAGE_DIRECTORY_ENTRY_EXPORT          0   // Export Directory

typedef struct _IMAGE_EXPORT_DIRECTORY {
    DWORD   Characteristics;        // 未使用 0
    DWORD   TimeDateStamp;          // 创建导出表的时间戳
    WORD    MajorVersion;           // 未使用 0
    WORD    MinorVersion;           // 未使用 0
    DWORD   Name;                   // 指向该导出表的文件名字符串RVA
    DWORD   Base;                   // 导出函数的起始序号
    DWORD   NumberOfFunctions;      // 所有导出函数的个数  不准确
    DWORD   NumberOfNames;          // 以函数名字导出的函数个数
    DWORD   AddressOfFunctions;     // 导出函数地址表RVA
    DWORD   AddressOfNames;         // 导出函数名称表RVA
    DWORD   AddressOfNameOrdinals;  // 导出函数序号表RVA
} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

IMAGE_IMPORT_DESCRIPTOR 导入表

typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    union {
        DWORD   Characteristics;           //导入表结束标志
        DWORD   OriginalFirstThunk;        //导入名称表(INT)的地址RVA  
    } DUMMYUNIONNAME;
    DWORD   TimeDateStamp;                 //时间戳  如果是0xFFFFFFFF为绑定导入
    DWORD   ForwarderChain;                //链表的前一个结构
    DWORD   Name;                          //导入DLL文件名的地址RVA
    DWORD   FirstThunk;                    //导入地址表(IAT)的地址RVA
} IMAGE_IMPORT_DESCRIPTOR;
typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;

//成员OriginalFirstThunk 和 FirstThunk 都指向此结构
typedef struct _IMAGE_THUNK_DATA32 {
    union {
        DWORD ForwarderString;      // PBYTE  指向一个转向者字符串的RVA
        DWORD Function;             // PDWORD 被输入的函数的内存地址
        DWORD Ordinal;              // 序号
        DWORD AddressOfData;        // PIMAGE_IMPORT_BY_NAME 指向IMAGE_IMPORT_BY_NAME
    } u1;
} IMAGE_THUNK_DATA32;
typedef IMAGE_THUNK_DATA32 * PIMAGE_THUNK_DATA32;

//如果结构_IMAGE_THUNK_DATA32成员最高有效位为1时 低31位为导出序号,否则指向此结构
typedef struct _IMAGE_IMPORT_BY_NAME {
    WORD    Hint;       //导出序号(有些编译器不会填充此值)
    CHAR    Name[1];    //该值长度不准确,以0结尾的字符串,导出函数名
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

_IMAGE_BASE_RELOCATION 重定位表

typedef struct _IMAGE_BASE_RELOCATION {
    DWORD   VirtualAddress;             //重定位数据所在页的RVA
    DWORD   SizeOfBlock;                //当前页中重定位数据块的大小
} IMAGE_BASE_RELOCATION;
typedef IMAGE_BASE_RELOCATION UNALIGNED * PIMAGE_BASE_RELOCATION;

PE笔记

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <Windows.h>
#include <stdio.h>

using namespace std;

int main()
{
  FILE* pFile = fopen("C:\\Users\\Administrator\\Desktop\\PETool.exe", "rb");

  fseek(pFile, NULL, SEEK_END);
  
  int nSize = ftell(pFile);

  fseek(pFile, NULL, SEEK_SET);

  char* pFileBuffer = (char*)malloc(nSize);

  memset(pFileBuffer, 0, nSize);

  fread(pFileBuffer, nSize, 1, pFile);

  char* a =  pFileBuffer + 0x3c;

  int b = *((int*)a);

  cout << pFileBuffer << endl;
  cout << pFileBuffer + b << endl;

  FILE* pFile1 = fopen("D:\\PETool.exe", "wb");

  fwrite(pFileBuffer, nSize, 1, pFile1);

  free(pFileBuffer);

  fclose(pFile);

  return 0;
}

cout<<hex<<i<<endl; //输出十六进制数 cout<<dec<<i<<endl; //输出十进制数

cout << hex << uppercase << showbase << pDos->e_magic << endl;

抹除PE标记作业

#include "tools.h"
int main()
{
  int FileSize = 0;

  char* pFileBuffer = FileToMemory(FILE_PATH_IN, &FileSize);

  PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)pFileBuffer;

  //输出 PIMAGE_DOS_HEADER 所有信息
  cerr << hex << uppercase << showbase << pDos->e_magic << endl;
  
  cerr  << hex << uppercase << showbase << pDos->e_cblp << endl;
  cerr  << hex << uppercase << showbase << pDos->e_cp << endl;
  cerr  << hex << uppercase << showbase << pDos->e_cparhdr << endl;
  cerr  << hex << uppercase << showbase << pDos->e_crlc << endl;
  cerr  << hex << uppercase << showbase << pDos->e_cs << endl;
  cerr  << hex << uppercase << showbase << pDos->e_csum << endl;
  cerr  << hex << uppercase << showbase << pDos->e_ip << endl;
  cerr  << hex << uppercase << showbase << pDos->e_lfarlc << endl;
  cerr  << hex << uppercase << showbase << pDos->e_maxalloc << endl;
  cerr  << hex << uppercase << showbase << pDos->e_oemid << endl;
  cerr  << hex << uppercase << showbase << pDos->e_oeminfo << endl;
  cerr  << hex << uppercase << showbase << pDos->e_ovno << endl;
  for (size_t i = 0; i < 4; i++)
  {
    cerr << hex << uppercase << showbase << pDos->e_res[i] << endl;
  }
  for (size_t i = 0; i < 10; i++)
  {
    cerr << hex << uppercase << showbase << pDos->e_res2[i] << endl;
  }
  cerr  << hex << uppercase << showbase << pDos->e_sp << endl;
  cerr  << hex << uppercase << showbase << pDos->e_ss << endl;

  cerr  << hex << uppercase << showbase << pDos->e_lfanew << endl;

  memset(pFileBuffer, 0x00, 0x2);               //抹除MZ标记
  
  memset(pFileBuffer + 2, 0x00, 0x3A);          //抹除e_magic - e_lfanew 之间数据

  memset((&(pDos->e_lfanew))+ 1 , 0x00, 0xC0);  //抹除DOS_STUB

  memset((pFileBuffer + *(&(pDos->e_lfanew))), 0x00, 0x2); //抹除PE标记

  MemoryToFile(FILE_PATH_OUT, pFileBuffer, FileSize);

  return 0;
}

时间戳转时间

string StampToTime(time_t timeStamp) 
{
  struct tm* timeinfo = nullptr;
  char buffer[80];
  timeinfo = localtime(&timeStamp);
  strftime(buffer, 80, "%Y年%m月%d日 %H:%M:%S", timeinfo);
  printf("文件创建时间: %s\n", buffer);
  return string(buffer);
}

PE结构体

Machine

#define IMAGE_FILE_MACHINE_UNKNOWN           0       // 适用于任何机器
#define IMAGE_FILE_MACHINE_TARGET_HOST       0x0001  // Useful for indicating we want to interact with the host and not a WoW guest.
#define IMAGE_FILE_MACHINE_I386              0x014c  // Intel 386 以及后续处理器
#define IMAGE_FILE_MACHINE_R3000             0x0162  // MIPS little-endian, 0x160 big-endian
#define IMAGE_FILE_MACHINE_R4000             0x0166  // MIPS little-endian
#define IMAGE_FILE_MACHINE_R10000            0x0168  // MIPS little-endian
#define IMAGE_FILE_MACHINE_WCEMIPSV2         0x0169  // MIPS little-endian WCE v2
#define IMAGE_FILE_MACHINE_ALPHA             0x0184  // Alpha_AXP
#define IMAGE_FILE_MACHINE_SH3               0x01a2  // SH3 little-endian
#define IMAGE_FILE_MACHINE_SH3DSP            0x01a3
#define IMAGE_FILE_MACHINE_SH3E              0x01a4  // SH3E little-endian
#define IMAGE_FILE_MACHINE_SH4               0x01a6  // SH4 little-endian
#define IMAGE_FILE_MACHINE_SH5               0x01a8  // SH5
#define IMAGE_FILE_MACHINE_ARM               0x01c0  // ARM Little-Endian
#define IMAGE_FILE_MACHINE_THUMB             0x01c2  // ARM Thumb/Thumb-2 Little-Endian
#define IMAGE_FILE_MACHINE_ARMNT             0x01c4  // ARM Thumb-2 Little-Endian
#define IMAGE_FILE_MACHINE_AM33              0x01d3
#define IMAGE_FILE_MACHINE_POWERPC           0x01F0  // IBM PowerPC Little-Endian
#define IMAGE_FILE_MACHINE_POWERPCFP         0x01f1
#define IMAGE_FILE_MACHINE_IA64              0x0200  // Intel 64
#define IMAGE_FILE_MACHINE_MIPS16            0x0266  // MIPS
#define IMAGE_FILE_MACHINE_ALPHA64           0x0284  // ALPHA64
#define IMAGE_FILE_MACHINE_MIPSFPU           0x0366  // MIPS
#define IMAGE_FILE_MACHINE_MIPSFPU16         0x0466  // MIPS
#define IMAGE_FILE_MACHINE_AXP64             IMAGE_FILE_MACHINE_ALPHA64
#define IMAGE_FILE_MACHINE_TRICORE           0x0520  // Infineon
#define IMAGE_FILE_MACHINE_CEF               0x0CEF
#define IMAGE_FILE_MACHINE_EBC               0x0EBC  // EFI Byte Code
#define IMAGE_FILE_MACHINE_AMD64             0x8664  // AMD64 (K8)
#define IMAGE_FILE_MACHINE_M32R              0x9041  // M32R little-endian
#define IMAGE_FILE_MACHINE_ARM64             0xAA64  // ARM64 Little-Endian
#define IMAGE_FILE_MACHINE_CEE               0xC0EE

Characteristics

0102

0000 0001 0000 0010

Magic

#define IMAGE_NT_OPTIONAL_HDR32_MAGIC      0x10b   //32位PE文件
#define IMAGE_NT_OPTIONAL_HDR64_MAGIC      0x20b   //64位PE文件
#define IMAGE_ROM_OPTIONAL_HDR_MAGIC       0x107   //该文件是ROM镜像

Subsystem

DllCharacteristics

DataDirectory

#define IMAGE_DIRECTORY_ENTRY_EXPORT          0   // Export Directory  
#define IMAGE_DIRECTORY_ENTRY_IMPORT          1   // Import Directory  
#define IMAGE_DIRECTORY_ENTRY_RESOURCE        2   // Resource Directory  
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION       3   // Exception Directory  
#define IMAGE_DIRECTORY_ENTRY_SECURITY        4   // Security Directory  
#define IMAGE_DIRECTORY_ENTRY_BASERELOC       5   // Base Relocation Table  
#define IMAGE_DIRECTORY_ENTRY_DEBUG           6   // Debug Directory  
#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT       7   // (X86 usage)  
#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE    7   // Architecture Specific Data  
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR       8   // RVA of GP  
#define IMAGE_DIRECTORY_ENTRY_TLS             9   // TLS Directory  
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    10   // Load Configuration Directory  
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   11   // Bound Import Directory in headers  
#define IMAGE_DIRECTORY_ENTRY_IAT            12   // Import Address Table  
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   13   // Delay Load Import Descriptors  
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14   // COM Runtime descriptor  

Characteristics 节属性常用位含义

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/942023.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Helm 官方脚本

Helm 官方脚本 #!/usr/bin/env bash# Copyright The Helm Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # …

JSON 系列之1:将 JSON 数据存储在 Oracle 数据库中

本文为Oracle数据库JSON学习系列的第一篇&#xff0c;讲述如何将JSON文档存储到数据库中&#xff0c;包括了版本为19c和23ai的情形。 19c中的JSON 先来看一下数据库版本为19c时的情形。 创建表colortab&#xff0c;其中color列的长度设为4000。若color的长度需要设为32767&a…

C语言-结构体内存大小

#include <stdio.h> #include <string.h> struct S1 { char a;//1 int b;//4 char c;//1 }; //分析 默认对齐数 成员对齐数 对齐数(前两个最小值) 最大对齐数 // 8 1 …

PyTorch 神经网络回归(Regression)任务:关系拟合与优化过程

PyTorch 神经网络回归&#xff08;Regression&#xff09;任务&#xff1a;关系拟合与优化过程 本教程介绍了如何使用 PyTorch 构建一个简单的神经网络来实现关系拟合&#xff0c;具体演示了从数据准备到模型训练和可视化的完整过程。首先&#xff0c;利用一维线性空间生成带噪…

渐开线齿轮和摆线齿轮有什么区别?

摆线齿形与渐开线齿形的区别 虽然在比对这两种齿形&#xff0c;但有一个事情希望大家注意&#xff1a;渐开线齿轮只是摆线齿轮的一个特例。 &#xff08;1&#xff09;摆线齿形的压力角在啮合开始时最大&#xff0c;在齿节点减小到零&#xff0c;在啮合结束时再次增大到最大…

Debian 12 安装配置 fail2ban 保护 SSH 访问

背景介绍 双十一的时候薅羊毛租了台腾讯云的虚机, 是真便宜, 只是没想到才跑了一个月, 系统里面就收集到了巨多的 SSH 恶意登录失败记录. 只能说, 互联网真的是太不安全了. 之前有用过 fail2ban 在 CentOS 7 上面做过防护, 不过那已经是好久好久之前的故事了, 好多方法已经不…

Vulhub靶场Apache解析漏洞

一.apache_parsing 原理&#xff1a;Apache HTTPD ⽀持⼀个⽂件拥有多个后缀&#xff0c;并为不同后缀执⾏不同的指令。在Apache1.x/2.x中Apache 解析⽂件的规则是从右到左开始判断解析,如果后缀名为不可识别⽂件解析,就再往左判断。如 1.php.xxxxx 打开靶场 创建一个名为1.p…

MATLAB 抛物线拟合(Quadratic,二维)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 这里仍然是最小二乘法的应用,其推导过程如下所述: 1.二次函数模型: 其中,a、b 和 c 是需要确定的参数。 2.最小二乘法 假设我们有一组数据点 ( x 1 ​ , y 1

重温设计模式--原型模式

文章目录 原型模式定义原型模式UML图优点缺点使用场景C 代码示例深拷贝、浅拷贝 原型模式定义 用原型实例指定创建对象的种类&#xff0c;并且通过拷贝这些原型创建新的对象&#xff1b; 核心中的核心就是 克隆clone ,后面讲 原型模式是一种创建型设计模式&#xff0c;它的主要…

mac iterm2 使用 lrzsz

前言 mac os 终端不支持使用 rz sz 上传下载文件&#xff0c;本文提供解决方法。 mac 上安装 brew install lrzsz两个脚本 注意&#xff1a;/usr/local/bin/iterm2-send-zmodem.sh 中的 sz命令路径要和你mac 上 sz 命令路径一致。 /usr/local/bin/iterm2-recv-zmodem.sh 中…

【基础篇】1. JasperSoft Studio编辑器与报表属性介绍

编辑器介绍 Jaspersoft Studio有一个多选项卡编辑器&#xff0c;其中包括三个标签&#xff1a;设计&#xff0c;源代码和预览。 Design&#xff1a;报表设计页面&#xff0c;可以图形化拖拉组件设计报表&#xff0c;打开报表文件的主页面Source&#xff1a;源代码页码&#xff…

【magic-dash】01:magic-dash创建单页面应用及二次开发

文章目录 一、magic-dash是什么1.1 安装1.2 使用1.2.1 查看内置项目模板1.2.2 生成指定项目模板1.2.3 查看当前magic-dash版本1.2.4 查看命令说明1.2.5 内置模板列表二、创建虚拟环境并安装magic-dash三、magic-dash单页工具应用开发3.1 创建单页面项目3.1.1 使用命令行创建单页…

《Pytorch框架CV开发-从入门到实战》

目录 1.环境部署2.自动梯度计算张量 tensor3.线性回归4.逻辑回归6.人工神经网络的基本概念6.1 感知器6.2 激活函数6.3多层感知器6.4 反向传播算法——前向传播6.5 反向传播算法——反向传播6.6 反向传播算法——训练方法7.Pytorch基础数据集8.手写数字识别人工神经网络训练8.1 …

WebRTC学习二:WebRTC音视频数据采集

系列文章目录 第一篇 基于SRS 的 WebRTC 环境搭建 第二篇 基于SRS 实现RTSP接入与WebRTC播放 第三篇 centos下基于ZLMediaKit 的WebRTC 环境搭建 第四篇 WebRTC 学习一&#xff1a;获取音频和视频设备 第五篇 WebRTC学习二&#xff1a;WebRTC音视频数据采集 文章目录 系列文章…

国自然联合项目|影像组学智能分析理论与关键技术|基金申请·24-12-25

小罗碎碎念 该项目为国自然联合基金项目&#xff0c;执行年限为2019年1月至2022年12月&#xff0c;直接费用为204万元。 项目研究内容包括影像组学分析、智能计算、医疗风险评估等&#xff0c;旨在通过模拟医生诊断过程&#xff0c;推动人工智能在医疗领域的创新。 项目取得了…

怎样配备公共配套设施,才能让啤酒酿造流程高效环保?

今天&#xff0c;天泰邀请大家和我一起走进啤酒厂&#xff0c;了解水、蒸汽、压缩空气和二氧化碳这些基础设施如何助力啤酒生产&#xff0c;实现高效与环保的完美结合。 水 水是啤酒酿造的基础&#xff0c;啤酒厂对水质的要求极高。为了确保水质达标&#xff0c;啤酒厂设有专…

医疗行业 UI 设计系列合集(一):精准定位

在当今数字化时代&#xff0c;医疗行业与信息技术的融合日益紧密&#xff0c;UI 设计在其中扮演着至关重要的角色。精准定位的 UI 设计能够显著提升医疗产品与服务的用户体验&#xff0c;进而对医疗效果和患者满意度产生积极影响。 一、医疗行业 UI 设计的重要性概述 医疗行业…

本科阶段最后一次竞赛Vlog——2024年智能车大赛智慧医疗组准备全过程——12使用YOLO-Bin

本科阶段最后一次竞赛Vlog——2024年智能车大赛智慧医疗组准备全过程——12使用YOLO-Bin ​ 根据前面内容&#xff0c;所有的子任务已经基本结束&#xff0c;接下来就是调用转化的bin模型进行最后的逻辑控制了 1 .YOLO的bin使用 ​ 对于yolo其实有个简单的办法&#xff0c;也…

EMC整改

首先我们来从EMC测试项目构成说起&#xff0c;EMC主要包含两大项&#xff1a;EMI&#xff08;干扰&#xff09;和EMS&#xff08;产品抗干扰和敏感度&#xff09;&#xff0c;当然这两大项中又包括许多小项目。 EMI主要测试项&#xff1a; RE&#xff08;产品辐射&#xff0c…

Xcode 16 编译弹窗问题、编译通过无法,编译通过打包等问题汇总

问题1&#xff1a;打包的过程中不断提示 &#xff1a;codesign 想要访问你的钥匙串中的密钥“develop 或者distribution 证书” 解决&#xff1a;打开钥匙串&#xff0c;点击证书---显示简介---信任----改为始终信任 &#xff08;记住 &#xff1a;不能只修改钥匙的显示简介的…