|
继承PE系列笔记的更新
PE其它笔记索引可前往:
PE文件笔记一 PE介绍
继承具体学习PE的各个结构细节,前面学完了标准PE头,接着学习扩展PE头
由于PE文件头的内容较多,故要拆分为多个笔记,此笔记主要为扩展PE头
PS:扩展PE头的成员较多,可以先看个大概后联合下面的实战分析来学习扩展PE头的成员
扩展PE头
扩展PE头所属
扩展PE头是PE文件头中的一个成员
32位所属
typedef struct _IMAGE_NT_HEADERS { DWORD Signature; //PE文件头标识 IMAGE_FILE_HEADER FileHeader; //标准PE头 IMAGE_OPTIONAL_HEADER32 OptionalHeader; //扩展PE头 32位} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;64位所属
typedef struct _IMAGE_NT_HEADERS64 { DWORD Signature; //PE文件头标识 IMAGE_FILE_HEADER FileHeader; //标准PE头 IMAGE_OPTIONAL_HEADER64 OptionalHeader; //扩展PE头 64位} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;两种扩展PE头差异
两种结构
扩展PE头的结构根据步伐是32位或64位而分成了两种结构,而PE文件头则因扩展PE头的差异也被分成了两种结构
PE文件头结构说明_IMAGE_NT_HEADERS32位步伐对应的PE文件头结构_IMAGE_NT_HEADERS6464位步伐对应的PE文件头结构_IMAGE_NT_HEADERS对应C中的结构体(类型)说明"PE",0,0DOWRDPE标识IMAGE_FILE_HEADERIMAGE_FILE_HEADER标准PE头IMAGE_OPTIONAL_HEADER32IMAGE_OPTIONAL_HEADER32扩展PE头 32位_IMAGE_NT_HEADERS64对应C中的结构体(类型)说明"PE",0,0DOWRDPE标识,固定值不可变IMAGE_FILE_HEADERIMAGE_FILE_HEADER标准PE头IMAGE_OPTIONAL_HEADER64IMAGE_OPTIONAL_HEADER64扩展PE头 64位结构体比较
32位结构体
typedef struct _IMAGE_OPTIONAL_HEADER { WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; DWORD BaseOfData; 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;64位结构体
typedef struct _IMAGE_OPTIONAL_HEADER64 { WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; ULONGLONG 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; ULONGLONG SizeOfStackReserve; ULONGLONG SizeOfStackCommit; ULONGLONG SizeOfHeapReserve; ULONGLONG SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;差异
成员\扩展PE头_IMAGE_OPTIONAL_HEADER_IMAGE_OPTIONAL_HEADER64BaseOfDataDWORD无此成员ImageBaseDWORDULONGLONGSizeOfStackReserveDWORDULONGLONGSizeOfStackCommitDWORDULONGLONGSizeOfHeapReserveDWORDULONGLONGSizeOfHeapCommitDWORDULONGLONG可以看到,64位相比于32位其实并没有太大的区别,只是删去了一个成员 以及 五个成员的数据类型由DWORD变为ULONGLONG
因为其区别并不明显,因此以32位结构体作为例子分析,64位结构体也近似相同
32位扩展PE头分析
扩展PE头中的成员较多,一般情况只需掌握部分重点即可(重点为表格中加黑的成员)
下面的分析参考自官方文档:ns-winnt-image_optional_header32和《Windows PE 权威指南》
PS:下面的分析较为冗长,类似参考文档,可以先跳过,先看下面的实战分析,根据实战里的数据到对应的成员参考其含义
成员数据宽度说明MagicWORD(2字节)镜像文件的状态,可用于判断步伐是32位还是64位MajorLinkerVersionBYTE(字节)链接器的主要版本号MinorLinkerVersionBYTE(字节)链接器的次要版本号SizeOfCodeDWORD(4字节)代码段的大小SizeOfInitializedDataDWORD(4字节)初始化数据段的大小SizeOfUninitializedDataDWORD(4字节)未初始化数据段的大小AddressOfEntryPointDWORD(4字节)步伐入口BaseOfCodeDWORD(4字节)代码开始的基址BaseOfDataDWORD(4字节)数据开始的基址ImageBaseDWORD(4字节)内存镜像基址SectionAlignmentDWORD(4字节)内存对齐FileAlignmentWORD(2字节)文件对齐MajorOperatingSystemVersionWORD(2字节)标识操作体系版本号 主版本号MinorOperatingSystemVersionWORD(2字节)标识操作体系版本号 次版本号MajorImageVersionWORD(2字节)PE文件自身的版本号MinorImageVersionWORD(2字节)PE文件自身的版本号MajorSubsystemVersionWORD(2字节)运行所需子体系版本号MinorSubsystemVersionWORD(2字节)运行所需子体系版本号Win32VersionValueDWORD(4字节)子体系版本的值,必须为0SizeOfImageDWORD(4字节)Image大小SizeOfHeadersDWORD(4字节)所有头+节表按照文件对齐后的大小CheckSumDWORD(4字节)校验和SubsystemWORD(2字节)子体系DllCharacteristicsWORD(2字节)文件特性 不只是针对DLL文件的SizeOfStackReserveDWORD(4字节)初始化时保存的栈大小SizeOfStackCommitDWORD(4字节)初始化时实际提交的大小SizeOfHeapReserveDWORD(4字节)初始化时保存的堆大小SizeOfHeapCommitDWORD(4字节)初始化时实践提交的大小LoaderFlagsDWORD(4字节)调试相关NumberOfRvaAndSizesDWORD(4字节)目次项数目DataDirectory[16]IMAGE_DATA_DIRECTORY[16]=128字节指向数据目次中第一个IMAGE_DATA_DIRECTORY结构的指针(数据目次项)Magic
镜像文件的状态。该成员可以是以下值之一
值含义IMAGE_NT_OPTIONAL_HDR_MAGIC该文件是一个可执行的映像。这个值在32位应用步伐中定义为IMAGE_NT_OPTIONAL_HDR32_MAGIC,在64位应用步伐中定义为IMAGE_NT_OPTIONAL_HDR64_MAGICIMAGE_NT_OPTIONAL_HDR32_MAGIC=0x10b该文件是一个可执行的映像(32位)IMAGE_NT_OPTIONAL_HDR64_MAGIC=0x20b该文件是一个可执行的映像(64位)IMAGE_ROM_OPTIONAL_HDR_MAGIC=0x107该文件是ROM镜像MajorLinkerVersion
链接器版本号
MinorLinkerVersion
链接器次要版本号
SizeOfCode
代码段的大小(以字节为单元),假如有多个代码段,则为所有这些代码段的总和。是文件对齐后的大小 编译器填的 没用(不一定正确)
SizeOfInitializedData
初始化数据段的大小(以字节为单元),假如有多个初始化数据段,则为所有这些数据段的总和。是文件对齐后的大小 编译器填的 没用(不一定正确)
SizeOfUninitializedData
未初始化数据段的大小(以字节为单元),假如有多个未初始化数据段,则为所有这些数据段的总和。是文件对齐后的大小 编译器填的 没用(不一定正确)
AddressOfEntryPoint
一个指向入口点函数的指针,相对于Image的基址。
- 对于可执行文件,这是起始地点
- 对于设备驱动步伐,这是初始化函数的地点
- 入口点函数对于dll是可选的。当没有入口点存在时,该成员为零
BaseOfCode
指向代码段开头的指针,相对于ImageBase。编译器填的 没用(不一定正确)
BaseOfData
指向数据段开头的指针,相对于ImageBase。编译器填的 没用(不一定正确)
ImageBase
Image(PE文件)载入内存时第一个字节的首选地点。该值是64K字节的倍数
- dll的默认值是0x10000000
- 应用步伐的默认值为0x00400000,
- Windows CE上的默认值为0x00010000
SectionAlignment
加载到内存中的节的对齐方式,以字节为单元。该值必须大于或即是FileAlignment(文件对齐)成员。默认值是体系的页面大小
FileAlignment
Image(PE文件)中各节的原始数据(以字节为单元)的对齐方式。该值应该是512到64K(包括)之间2的幂。缺省值是512。假如SectionAlignment成员小于体系页面大小,则该成员必须与SectionAlignment相同
MajorOperatingSystemVersion
所需操作体系的主要版本号
MinorOperatingSystemVersion
所需操作体系的次要版本号
MajorImageVersion
镜像(PE文件)的主版本号
MinorImageVersion
镜像(PE文件)的次要版本号
MajorSubsystemVersion
子体系的主要版本号
Win32VersionValue
该成员是保存的,并且必须为0
SizeOfImage
Image的大小,以字节为单元,包括所有头。必须是多个SectionAlignment
内存中整个PE文件的映射的尺寸,可比实际的值大,必须是SectionAlignment的整数倍
SizeOfHeaders
下列项的组合大小,舍入为“文件对齐”成员中指定值的倍数
- IMAGE_DOS_HEADER(DOS MZ头) 中的最后一个成员e_lfanew
- PE文件头标志 signature 的 大小 4字节
- IMAGE_FILE_HEADER(标准PE头)的大小
- 扩展PE头的大小
- 所有节头(节表)的大小
SizeOfHeaders=
{
e_lfanew
+sizeof(signature)
+sizeof(_IMAGE_FILE_HEADER)
+sizeof(_IMAGE_OPTIONAL_HEADER)
+sizeof(_IMAGE_SECTION_HEADER)
}(文件对齐)
即 DOS部首+PE文件头+节表 按照文件对齐后的大小
CheckSum
Image(PE文件)校验和。以下文件在加载时举行验证:所有驱动步伐,在引导时加载的任何DLL,以及加载到关键体系进程中的任何DLL
Subsystem
运行此映像所需的子体系。定义了以下值:
宏定义值含义IMAGE_SUBSYSTEM_UNKNOWN0未知的子体系IMAGE_SUBSYSTEM_NATIVE1不必要子体系(设备驱动步伐和本机体系进程)IMAGE_SUBSYSTEM_WINDOWS_GUI2Windows图形用户界体面体系IMAGE_SUBSYSTEM_WINDOWS_CUI3Windows字符模式用户界面(CUI)子体系IMAGE_SUBSYSTEM_OS2_CUI5OS/2 CUI子体系IMAGE_SUBSYSTEM_POSIX_CUI7POSIX CUI子体系IMAGE_SUBSYSTEM_WINDOWS_CE_GUI9Windows CE体系IMAGE_SUBSYSTEM_EFI_APPLICATION10可扩展固件接口(EFI)应用步伐IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER11带有引导服务的EFI驱动步伐IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER12带有运行时服务的EFI驱动步伐IMAGE_SUBSYSTEM_EFI_ROM13EFI ROM镜像IMAGE_SUBSYSTEM_XBOX14Xbox体系IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION16启动应用步伐DllCharacteristics
官方文档版本
Image的DLL特性,定义了以下值
宏定义值含义无0x0001保存,必须为0无0x0002保存,必须为0无0x0004保存,必须为0无0x0008保存,必须为0IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA0x0020具有64位地点空间的ASLRIMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE0x0040DLL可以在加载时重新定位IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY0x0080逼迫举行代码完备性查抄。假如你设置了这个标志,并且section只包含未初始化的数据,那么将该section的IMAGE_SECTION_HEADER的PointerToRawData成员设置为0;否则,由于无法验证数字签名,Image将无法加载IMAGE_DLLCHARACTERISTICS_NX_COMPAT0x0100该映像与数据执行预防(DEP)兼容IMAGE_DLLCHARACTERISTICS_NO_ISOLATION0x0200映像可以被隔离,但不应该被隔离IMAGE_DLLCHARACTERISTICS_NO_SEH0x0400该映像不使用结构化异常处理(SEH)。在此映像中不能调用任何处理步伐IMAGE_DLLCHARACTERISTICS_NO_BIND0x0800不要绑定映像IMAGE_DLL_CHARACTERISTICS_APPCONTAINER0x1000映像应该在AppContainer中执行IMAGE_DLLCHARACTERISTICS_WDM_DRIVER0x2000一个WDM驱动IMAGE_DLL_CHARACTERISTICS_GUARD_CF0x4000映像支持控制流掩护(Control Flow Guard)IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE0x8000该映像是终端服务器感知的PE权威指南版本
SizeOfStackReserve
为堆栈保存的字节数。只有SizeOfStackCommit成员指定的内存在加载时被提交;其余的页面每次只提供一个页面,直到达到这个预留大小
SizeOfStackCommit
要提交给堆栈的字节数
SizeOfHeapReserve
为本地堆保存的字节数。只有SizeOfHeapCommit成员指定的内存在加载时被提交;其余的页面每次只提供一个页面,直到达到这个预留大小
SizeOfHeapCommit
要为本地堆提交的字节数
LoaderFlags
该成员已逾期
NumberOfRvaAndSizes
可选头的其余部分中的目次条目数。每个条目都形貌了一个位置和大小
DataDirectory
指向数据目次中第一个IMAGE_DATA_DIRECTORY结构的指针
所需目次条目标索引号。该参数可以是以下值之一:
宏定义值含义IMAGE_DIRECTORY_ENTRY_ARCHITECTURE7特定于体系结构的数据,预留为0IMAGE_DIRECTORY_ENTRY_BASERELOC5基地点重定位表IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT11绑定导入表IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR14COM形貌符表IMAGE_DIRECTORY_ENTRY_DEBUG6调试表IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT13延迟导入表IMAGE_DIRECTORY_ENTRY_EXCEPTION3异常表IMAGE_DIRECTORY_ENTRY_EXPORT0导出表IMAGE_DIRECTORY_ENTRY_GLOBALPTR8全局指针的相对捏造地点IMAGE_DIRECTORY_ENTRY_IAT12导入地点表IMAGE_DIRECTORY_ENTRY_IMPORT1导入表IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG10加载配置表IMAGE_DIRECTORY_ENTRY_RESOURCE2资源表IMAGE_DIRECTORY_ENTRY_SECURITY4安全表IMAGE_DIRECTORY_ENTRY_TLS9线程本地存储表实战分析
获取数据
从先前分析的标准PE头的结尾开始看起,选中部分为扩展PE头,共占224字节
按顺序依次将数据填入对应的成员得到:
成员值Magic0x010BMajorLinkerVersion0x09MinorLinkerVersion0x00SizeOfCode0x00199200SizeOfInitializedData0x000BEC00SizeOfUninitializedData0x00000000AddressOfEntryPoint0x0016AF12BaseOfCode0x00001000BaseOfData0x0019B000ImageBase0x00400000SectionAlignment0x00001000FileAlignment0x00000200MajorOperatingSystemVersion0x0005MinorOperatingSystemVersion0x0000MajorImageVersion0x0000MinorImageVersion0x0000MajorSubsystemVersion0x0005MinorSubsystemVersion0x0000Win32VersionValue0x00000000SizeOfImage0x00298000SizeOfHeaders0x00000400CheckSum0x0025cd89Subsystem0x0002DllCharacteristics0x8140SizeOfStackReserve0x00100000SizeOfStackCommit0x00001000SizeOfHeapReserve0x00100000SizeOfHeapCommit0x00001000LoaderFlags0x00000000NumberOfRvaAndSizes0x00000010DataDirectory[16]留作之后的笔记分析数据
鉴于篇幅和实用性考虑,只分析比较紧张的成员
Magic
Magic的值为0x010B,根据前面的分析可知:该文件是一个可执行的映像(32位)
AddressOfEntryPoint
AddressOfEntryPoint的值为0x0016AF12,根据前面的分析可知:一个指向入口点函数的指针,相对于Image的基址是0x0016AF12
而Image的基址就是后面的 ImageBase = 0x00400000
于是该指针的的绝对地点为基址+偏移=0x00400000+0x0016AF12=0x0056AF12
于是得到了该步伐的步伐入口点为0x0056AF12,为了验证其正确性,使用OD打开步伐
可以看到OD自动停止在了步伐入口点0x0056AF12
PS:假如OD停息到了其它地方,则必要设置一下OD的停止点:
选项→调试设置(或使用快捷键Alt+0)
变乱→主模块入口点
ImageBase
ImageBase的值为0x00400000,根据前面的分析可知:ImageBase恰好是应用步伐的默认值0x00400000
且ImageBase=0x00400000是64K字节的倍数
SectionAlignment、FileAlignment、SizeOfHeaders
有关内存对齐和文件对齐的相关内容 在PE文件笔记二 PE文件的两种状态已经学习过了,这里不再赘述
SizeOfImage
SizeOfImage的值为0x00298000,根据前面的分析可知:
SizeOfImage表示内存中整个PE文件的映射的尺寸,可比实际的值大,必须是SectionAlignment的整数倍
于是打开步伐,并使用WinHex查看其在内存中的状态(在PE文件笔记二 PE文件的两种状态中已经演示过,这里不再赘述,直接看结果)
用WinHex附加上步伐后,拉到最底部,查看文件的最大偏移量
可以看到此时的最大偏移量为697FFF,用最大偏移量减去ImageBase 0x400000得到相对偏移为297FFF=SizeOfImage-1
验证了SizeOfImage可以比实际的值大
再验证SizeOfImage为内存对齐SectionAlignment的整数倍:
SizeOfImage/SectionAlignment=0x00298000/0x1000=0x298,可以整除,验证完毕
CheckSum
CheckSum从头部开始 两两字节不断相加,一直相加到最后,期间假如溢出,则直接舍去溢出部分,最后加完的结果再加上整个文件的长度就得到了CheckSum,操作体系就是通过这种方式来查验文件是否被修改
但只对以下文件在加载时举行验证:所有驱动步伐,在引导时加载的任何DLL,以及加载到关键体系进程中的任何DLL
此时步伐自己并不属于上面提到的文件类型,于是此时的CheckSum并不生效
由于CheckSum的计算比较麻烦,于是这里就略去CheckSum计算的验证,简朴说明了CheckSum的计算原理
下面来验证一下CheckSum的作用范围,此时步伐的CheckSum应该是无效的
CheckSum的值为0x0025cd89,将它修改为0
1.找到CheckSum
2.选中CheckSum,鼠标右键→编辑
3.填充选块
4.填充0
5.修改完毕
6.保存,然后打开步伐
使用快捷键 Ctrl+S 保存,确定
打开步伐,仍然可以正常运行,验证完毕
Subsystem
Subsystem的值为0x0002,根据前面的分析可知:运行该步伐所需子体系为:Windows图形用户界体面体系
DllCharacteristics
DllCharacteristics的值为0x8140
通过PE权威指南
转化为二进制得到:1000000101000000
数据位为1的位数有:第6位,第8位,第15位
根据前面的分析可知:DLL可以在加载时重新定位、该映像与数据执行预防(DEP)兼容、该映像是终端服务器感知的
通过官方文档
DllCharacteristics的值为0x8140=0x8000+0x0100+0x0040
根据前面的分析可知:DLL可以在加载时重新定位、该映像与数据执行预防(DEP)兼容、该映像是终端服务器感知的
自写代码解析PE文件头
在先前代码的根本上,进一步改进
// PE.cpp : Defines the entry point for the console application.//#include #include #include //在VC6这个比较旧的情况里,没有定义64位的这个宏,必要自己定义,在VS2019中无需自己定义#define IMAGE_FILE_MACHINE_AMD64 0x8664int main(int argc, char* argv[]){ //创建DOS对应的结构体指针 _IMAGE_DOS_HEADER* dos; //读取文件,返回文件句柄 HANDLE hFile = CreateFileA("C:\\Users\\lyl610abc\\Desktop\\dbgview64.exe", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); //根据文件句柄创建映射 HANDLE hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, 0); //映射内容 LPVOID pFile = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); //类型转换,用结构体的方式来读取 dos = (_IMAGE_DOS_HEADER*)pFile; //输出dos->e_magic,以十六进制输出 printf("dos->e_magic:%X\n", dos->e_magic); //创建指向PE文件头标志的指针 DWORD* peId; //让PE文件头标志指针指向其对应的地点=DOS首地点+偏移 peId = (DWORD*)((UINT)dos + dos->e_lfanew); //输出PE文件头标志,其值应为4550,否则不是PE文件 printf("peId:%X\n", *peId); //创建指向可选PE头的第一个成员magic的指针 WORD* magic; //让magic指针指向其对应的地点=PE文件头标志地点+PE文件头标志大小+标准PE头大小 magic = (WORD*)((UINT)peId + sizeof(DWORD) + sizeof(_IMAGE_FILE_HEADER)); //输出magic,其值为0x10b代表32位步伐,其值为0x20b代表64位步伐 printf("magic:%X\n", *magic); //根据magic判断为32位步伐还是64位步伐 switch (*magic) { case IMAGE_NT_OPTIONAL_HDR32_MAGIC: { printf("32位步伐\n"); //确定为32位步伐后,就可以使用_IMAGE_NT_HEADERS来接收数据了 //创建指向PE文件头的指针 _IMAGE_NT_HEADERS* nt; //让PE文件头指针指向其对应的地点 nt = (_IMAGE_NT_HEADERS*)peId; printf("Machine:%X\n", nt->FileHeader.Machine); printf("Magic:%X\n", nt->OptionalHeader.Magic); break; } case IMAGE_NT_OPTIONAL_HDR64_MAGIC: { printf("64位步伐\n"); //确定为64位步伐后,就可以使用_IMAGE_NT_HEADERS64来接收数据了 //创建指向PE文件头的指针 _IMAGE_NT_HEADERS64* nt; nt = (_IMAGE_NT_HEADERS64*)peId; printf("Machine:%X\n", nt->FileHeader.Machine); printf("Magic:%X\n", nt->OptionalHeader.Magic); break; } default: { printf("error!\n"); break; } } return 0;}运行结果
32位步伐
64位步伐
代码说明
代码基于上一次的笔记PE文件笔记四 PE文件头之标准PE头改进了判断步伐32位或64位的方法,并没有什么太大的变动,有关代码的分析在上一次笔记已经给出,这里也就不再赘述
总结
- 扩展PE头根据步伐是32位或64位而对应两种不同的结构
- 根据扩展PE头的第一个成员Magic可以判断出步伐是32位的还是64位的
- 两种扩展PE头结构实际相差不多,掌握了32位的结构其实也相当于掌握了64位的结构
- 扩展PE头英文虽然为optional header,译为可选头,但它其实必不可少且极其紧张
- 扩展PE头中的DataDirectory内容涉及较多,留作之后
附件
附上本笔记中分析的EverEdit文件:点我下载
来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|