【文章标题】: PE文件结构处理经验总结1
【文章作者】: ddlx
【作者邮箱】: DdlxStudio@163.com
【作者QQ号】: 383394019
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
该贴不是扫盲贴,如果对Pe文件不是很熟悉,请先查阅其他人写的PE文章。
该贴是我在写加壳工具的时候遇到问题的总结。记录下来,供以后温习,希望对各位也有一定帮助。
由于本人接触该方面时间不长,免不了存在失误之处,敬请拍砖。
1. IMAGE_DOS_HEADER
Dos头需要注意的有两个字段:e_magic和e_lfanew。其它字段不用管它。这两个字段的意义大家都懂得~
2. IMAGE_NT_HEADER
通过Nt头的Signature字段和Dos头的e_magic来判断该文件是否为PE文件。
3. IMAGE_FILE_HEADER
字段:Machine。该字段通常用来判断该PE文件是否为64位格式。我原先使用字段Characteristics的IMAGE_FILE_32BIT_MACHINE位来判断是否为64位,发现这种方法不准确,32位文件可以不设置IMAGE_FILE_32BIT_MACHINE位。
字段:Characteristics。这里面记录了好多文件属性。我当前只判断IMAGE_FILE_DLL,来确认该文件是否为动态链接库Dll.(IMAGE_FILE_32BIT_MACHINE标记判断是否为64位是不可靠的)
字段: NumberOfSections。这个是区段(也叫节)个数,遍历区段头时使用该字段来控制是否遍历结束。我原先看PE文章说在遍历区段头时判断区段头数据是否为空就知道是否遍历结束了,经过我亲自试验,这种说法是错误的。
字段: SizeOfOptionalHeader. 想知道可选文件头大小就使用这个字段。有人计算可选文件头大小时使用sizeof(IMAGE_OPTIONAL_HEADER32/64),这个也是错误的,因为数据目录的个数可能不止16个。
4. IMAGE_OPTIONAL_HEADER
该字段有32和64两种版本。
通过BaseOfCode和SizeOfCode来标记代码段起始位置和大小是不可取的。数据段也一样。
SectionAlignment和FileAlignment在增加或删除区段的时候有用。如果区段变更,一定要修正SizeOfImage。否则你的程序就无法被系统加载。
SectionAlignment必须>=FileAlignment。并且都是2的幂数。
字段: SizeOfHeaders。这个是整个Pe文件头大小。CopyPE文件头数据时使用。有些人在复制文件头时使用memcpy(pToModBase, pFromModBase, pSectionH[0].PointerToRawData);以后不要这样用了,因为有一些加过壳(特别是压缩壳)的程序pSectionH[0].PointerToRawData被置成了0.
字段:CheckSum。校验和只有在驱动文件中有用。驱动加载失败首先要看一下校验和是否正确。
字段:NumberOfRvaAndSizes。不是永远等于16。可以任意。
5. IMAGE_SECTION_HEADER
字段:Name.获取Name时不要使用strcpy(pSecName,pSecH[0].Name); 应该使用memcpy(pSecName, pSecH[0].Name,IMAGE_SIZEOF_SHORT_NAME);
字段:VirtualAddress。该值必须是SectionAlignment的倍数。VirtualAddress不能为0
字段:PointerToRawData。该值必须是FileAlignment的倍数。PointerToRawData可以为0.
字段:VirtualSize:不必是SectionAlignment的倍数。
字段:SizeOfRawData:不必是FileAlignment的倍数。可以为0.
字段: Characteristics。 该字段包含了区段属性信息。可以通过IMAGE_SCN_MEM_EXECUTE标志来判断是否为可执行区段,不是很准。
另外:
1. 相邻的两个节数据不一定是连续的!
2. 获取第一个区段头地址方法:
#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \
((ULONG_PTR)ntheader + \
FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \
((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader \
))
不要使用:
[注意]看雪招聘,专注安全领域的专业人才平台!