WINDOWS逆向笔记-PE结构

WINDOWS逆向笔记-PE结构

  • pe结构的对齐,其一节省硬盘空间,更重要的所有的对齐都是为了提升访问速度;
    • 硬盘对齐:200h
    • 内存对齐:1000h
**HEADERS:
DOS头-0x40字节
MZ标记和e_lfanew
PE签名signature-DWORD
PE标准文件头-0x20字节
PE可选文件头-E0或F0字节或定义
节区块表-目录
每个节区目录0x28字节
**各节区:
.text
.rdata
.DATA块
其他块区

PE结构

DOS头

struct _IMAGE_DOS_HEADER {
0x00 WORD e_magic;//"MZ标记" 用于判断是否为可执行文件. //notepad.exe 5a4dh WORD = U
0x02 WORD e_cblp;//0090h
0x04 WORD e_cp;//0003h
0x06 WORD e_crlc;//0000h
0x08 WORD e_cparhdr;//0004h
0x0a WORD e_minalloc;//0000h
0x0c WORD e_maxalloc;//ffffh
0x0e WORD e_ss;//0000h
0x10 WORD e_sp;//00b8h
0x12 WORD e_csum;//0000h
0x14 WORD e_ip;//0000h
0x16 WORD e_cs;//0000h
0x18 WORD e_lfarlc;//0040h
0x1a WORD e_ovno;//0000h
0x1c WORD e_res[4];//0000 0000 0000 0000h
0x24 WORD e_oemid;//00 00 h
0x26 WORD e_oeminfo;//0000h
0x28 WORD e_res2[10];
0x3c DWORD e_lfanew;//PE头相对于文件的偏移,用于定位PE文件//00 00 00 e8 *
};

NT头部

struct _IMAGE_NT_HEADERS {
0x00 DWORD Signature;               //5045h  pe标记
0x04 _IMAGE_FILE_HEADER FileHeader;//标准PE头
0x18 _IMAGE_OPTIONAL_HEADER OptionalHeader;//可选PE头
};
标准PE头
struct _IMAGE_FILE_HEADER {
0x00 WORD Machine;    //程序运行的CPU型号:0x0 任何处理器/0x14C 386及后续处理器
0x02 WORD NumberOfSections;//文件中存在的节的总数,如果要新增节或者合并节 就要修改这个值
0x04 DWORD TimeDateStamp;//时间戳:文件的创建时间(和操作系统的创建时间无关),编译器填写的
0x08 DWORD PointerToSymbolTable;
0x0c DWORD NumberOfSymbols;
0x10 WORD SizeOfOptionalHeader;//可选PE头的大小,32位PE文件默认E0h 64位PE文件默认为F0h  大小可以自定义.
0x12 WORD Characteristics;//每个位有不同的含义,可执行文件值为10F 即0 1 2 3 8位置1 
};
可选PE头**(很多重要属性)
struct _IMAGE_OPTIONAL_HEADER {
0x00 WORD Magic;    //说明文件类型:10B 32位下的PE文件     20B 64位下的PE文件
0x02 BYTE MajorLinkerVersion;
0x03 BYTE MinorLinkerVersion;
0x04 DWORD SizeOfCode;    //所有代码节的和,必须是FileAlignment的整数倍 编译器填的  没用
0x08 DWORD SizeOfInitializedData;//已初始化数据大小的和,必须是FileAlignment的整数倍 编译器填的  没用
0x0c DWORD SizeOfUninitializedData;//未初始化数据大小的和,必须是FileAlignment的整数倍 编译器填的  没用
0x10 DWORD AddressOfEntryPoint;//程序入口
0x14 DWORD BaseOfCode;//代码开始的基址,编译器填的   没用
0x18 DWORD BaseOfData;//数据开始的基址,编译器填的   没用
0x1c DWORD ImageBase; //内存镜像基址
0x20 DWORD SectionAlignment;//内存对齐
0x24 DWORD FileAlignment;//文件对齐
0x28 WORD MajorOperatingSystemVersion;
0x2a WORD MinorOperatingSystemVersion;
0x2c WORD MajorImageVersion;
0x2e WORD MinorImageVersion;
0x30 WORD MajorSubsystemVersion;
0x32 WORD MinorSubsystemVersion;
0x34 DWORD Win32VersionValue;
0x38 DWORD SizeOfImage;//内存中整个PE文件的映射的尺寸,可以比实际的值大,但必须是SectionAlignment的整数倍
0x3c DWORD SizeOfHeaders;//所有头+节表按照文件对齐后的大小,否则加载会出错
0x40 DWORD CheckSum;//校验和,一些系统文件有要求.用来判断文件是否被修改.
0x44 WORD Subsystem;
0x46 WORD DllCharacteristics;
0x48 DWORD SizeOfStackReserve;//初始化时保留的堆栈大小 
0x4c DWORD SizeOfStackCommit;//初始化时实际提交的大小
0x50 DWORD SizeOfHeapReserve;//初始化时保留的堆大小 
0x54 DWORD SizeOfHeapCommit;//初始化时实践提交的大小 
0x58 DWORD LoaderFlags;
0x5c DWORD NumberOfRvaAndSizes;//目录项数目
0x60 _IMAGE_DATA_DIRECTORY DataDirectory[16];
};

节表-节的描述信息,目录;

IMAGE_SECTION_HEADER *pISH = (IMAGE_SECTION_HEADER *)((DWORD)pFileBuf + pIDH->e_lfanew + sizeof(IMAGE_NT_HEADERS));
typedef struct _IMAGE_SECTION_HEADER {// length:0x28;
    0x00 BYTE Name[IMAGE_SIZEOF_SHORT_NAME];//8个字节 一般情况下是以"\0"结尾的ASCII吗字符串来标识的名称,内容可以自定义.注意:该名称并不遵守必须以"\0"结尾的规律,如果不是以"\0"结尾,系统会截取8个字节的长度进行处理.
    union {
    0x08  DWORD PhysicalAddress;
    0x08 DWORD VirtualSize;//内存中没有对齐前的实际大小,内存中的大小和sizeOfRawData大小不一样
    } Misc;//双字 是该节在没有对齐前的真实尺寸,该值可以不准确。
    0x0c DWORD VirtualAddress;//节区在内存中的偏移地址。加上ImageBase才是在内存中的真正地址.
    0x10 DWORD SizeOfRawData; //节在文件中对齐后的尺寸.
    0x14 DWORD PointerToRawData; //节区在文件中的偏移.
    0x18 DWORD PointerToRelocations;//在obj文件中使用 对exe无意义
    0x1c DWORD PointerToLinenumbers;//行号表的位置 调试的时候使用
    0x20 WORD NumberOfRelocations;//在obj文件中使用  对exe无意义
    0x22 WORD NumberOfLinenumbers;//行号表中行号的数量 调试的时候使用
    0x24 DWORD Characteristics;//节的属性
};
//节的特征属性中,可执行、可读、可写、包含可执行代码等等。
标志(属性块) 常用特征值对照表:

[:00000020h] [IMAGE_SCN_CNT_CODE                // Section contains code.(包含可执行代码)]
[:00000040h] [IMAGE_SCN_CNT_INITIALIZED_DATA    // Section contains initialized data.(该块包含已初始化的数据)]
[:00000080h] [IMAGE_SCN_CNT_UNINITIALIZED_DATA  // Section contains uninitialized data.(该块包含未初始化的数据)]
[:00000200h] [IMAGE_SCN_LNK_INFO                // Section contains comments or some other type of information.]
[:00000800h] [IMAGE_SCN_LNK_REMOVE              // Section contents will not become part of image.]
[:00001000h] [IMAGE_SCN_LNK_COMDAT              // Section contents comdat.]
[:00004000h] [IMAGE_SCN_NO_DEFER_SPEC_EXC       // Reset speculative exceptions handling bits in the TLB entries for this section.]
[:00008000h] [IMAGE_SCN_GPREL                   // Section content can be accessed relative to GP.]
[:00500000h] [IMAGE_SCN_ALIGN_16BYTES           // Default alignment if no others are specified.]
[:01000000h] [IMAGE_SCN_LNK_NRELOC_OVFL         // Section contains extended relocations.]
[:02000000h] [IMAGE_SCN_MEM_DISCARDABLE         // Section can be discarded.]
[:04000000h] [IMAGE_SCN_MEM_NOT_CACHED          // Section is not cachable.]
[:08000000h] [IMAGE_SCN_MEM_NOT_PAGED           // Section is not pageable.]
[:10000000h] [IMAGE_SCN_MEM_SHARED              // Section is shareable(该块为共享块).]
[:20000000h] [IMAGE_SCN_MEM_EXECUTE             // Section is executable.(该块可执行)]
[:40000000h] [IMAGE_SCN_MEM_READ                // Section is readable.(该块可读)]
[:80000000h] [IMAGE_SCN_MEM_WRITE               // Section is writeable.(该块可写)]

内存镜像+重载

  • FileBuffer 文件镜像–> ImageBuffer内存镜像(还不到加载运行的时候)
    1. 首先内存中动态申请malloc(sizeOfImage)的内存,初始化为0memset(ptr,0,sizeOfImage)
    2. 拷贝sizeOfHeaders到ImageBuffer内存镜像
    3. 拷贝第一个节到内存镜像中,按照PointerToRawData在文件中的位置,拷贝sizeOfRawData或者Misc/VirtualSize(安全起见最好使用前面一个)个到VirtualAddress+申请内存首地址中
    4. 把所有的节区按照标准PE头中sizeOfSection的大小,循环copy节到内存镜像中
    5. 内存镜像某个值701323在哪个节区里面,701323-700000(动态内存首地址)以后,第一、一定要大于某一个节的VirtualAddress,第二一定要小于VirtualAddress+misc.VirtualSize。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值