shuiyu 发表于 2018-1-17 20:45:06

《解密系列-系统篇》第五讲:PE结构详解5

本帖最后由 shuiyu 于 2018-9-10 17:45 编辑

越努力,越幸运。欢迎大家来看我的笔记{:10_297:},不对的请各位大佬指正,谢谢{:10_254:}


一、手动查找PE文件各类数值




(1)DOS首部
1.DOS可执行文件标志(MZ)很容易找,就不说了

2. +3ch      DWORD    e_lfanew   指向PE文件头的偏移地址:B8 00 00 00

(2)PE文件头
3.根据e_lfanew找到PE文件头(是一个IMAGE_NT_HEADER 结构)
IMAGE_NT_HEADERS STRUCT
{
+0h      DWORD                           Signature            
+4h      IMAGE_FILE_HEADER               FileHeader
+18h      IMAGE_OPTIONAL_HEADER32            OptionlHeader //可选择的32位文件头
}IMAGE_NT_HEADERS ENDS

4.Signature字段被设置为00004550h,ASCII码字符是"PE00"。

5.IMAGE_FILE_HEADER(结构里面的结构)
具体可看第二讲:http://bbs.fishc.com/thread-103040-1-1.html
在PE头处(从50 45 00 00 开始数)偏移+4h可找到IMAGE_FILE_HEADER结构。
typedefstruct_IMAGE_FILE_HEADER
{
      WORD      Machine;-------------------------------//运行平台
      WORD      NumberOfSections;------------------//文件的区块数目
      DWORD      TimeDateStamp;---------------------//文件创建日期和时间
      DWORD      PointerToSymbolTable;-------------//指向符号表(主要用于调试)
      DWORD      NumberOfSymbols;------------------//符号表中符号个数(主要用于调试)
      WORD      SizeOfOptionalHeader;--------------//IMAGE_FILE_HEADER32结构大小
      WORD      Characteristics;//文件属性
}IMAGE_FILE_HEADER,*PIMAGE_FILE_HEADER;
重点摘要:
Machine;//运行平台-------------------------------014C为32位,8664为64位

TimeDateStamp;//文件创建日期和时间----------得到的是16进制的值,要先转为10进制,然后到https://unixtime.51240.com/转换就行了

SizeOfOptionalHeader;//IMAGE_FILE_HEADER32结构大小--------------32位PE文件通常为:00E0,对于64位PE文件通常为:00F0


6.IMAGE_OPTIONAL_HEADER32(可选择的32位文件头)
在PE头处偏移+18h可找到IMAGE_OPTIONAL_HEADER32结构。
具体情况可看第三讲:http://bbs.fishc.com/thread-103190-1-1.html

7.找到块表(也称为:区块表、节表。区块是可执行文件中真正保存内容的地方。)
根据"IMAGE_FILE_HEADER结构"末尾的地址,加上,IMAGE_FILE_HEADER结构中" SizeOfOptionalHeader;//IMAGE_FILE_HEADER32结构大小"    来到PE文件头的末尾,也就是区块表的开始地址。可以在右边ASCII码栏看到 " .text "。

二、块表(也称为:区块表、节表)
继续上一讲的块表讲解:

(1)区块表内容(union共用体结构,表示里面的任选一个),每个区块表占40(28h)个字节;个个区块表之间没有间隙,都是首位相连的。
typedef struct _IMAGE_SECTION_HEADER
{
      BYTE Name;   // 节表名称,如“.text”
      //IMAGE_SIZEOF_SHORT_NAME=8
      union
         {
                DWORD PhysicalAddress;      // 物理地址
                DWORD VirtualSize;                // 真实长度,这两个值是一个联合结构,可以使用其中的任何一个,一般是取后一个
      } Misc;
      DWORD VirtualAddress;            // 节区的 RVA 地址
      DWORD SizeOfRawData;            // 在文件中对齐后的大小
      DWORD PointerToRawData;      // 在文件中的偏移量
      DWORD PointerToRelocations;   // 在OBJ文件中使用,重定位的偏移
      DWORD PointerToLinenumbers;   // 行号表的偏移(供调试使用地)
      WORD NumberOfRelocations;      // 在OBJ文件中使用,重定位项数目
      WORD NumberOfLinenumbers;    // 行号表中行号的数目
      DWORD Characteristics;            // 节属性如可读,可写,可执行等
}IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

(2)重点摘要:
Name:如果在汇编中它叫Name1,因为在win32汇编中它与一个关键字发生了冲突,所以叫Name1。但是我们这里是C语言的定义,所以没影响。
Name:区块名。这是一个由8位的ASCII 码名(DWORD,8个字节,超过则没有终止标志“NULL”)。并且前边带有“$”的相同名字的区块在载入时候会被合并,在合并之后的区块中,它们是按照"$"后边的字符的字母顺序进行合并的。

SizeOfRawData:在文件中对齐后的大小。该区块在磁盘中所占的大小。在可执行文件中,该字段是已经被FileAlignment 潜规则处理过的长度。

PointerToRawData:在文件中的偏移量。该区块在磁盘中的偏移。这个数值是从文件头开始算起的偏移量哦。

Characteristics:该区块的属性。该字段是按位来指出区块的属性(如代码/数据/可读/可写等)的标志。


三、如何判断区块的属性
(1)如何判断区块的属性(Characteristics),例如:
Characteristics字段为"6000 0020",因为该段是"按位"来指出区块属性的,且用"or"(或,一真为真)来计算的,那么:
1.将"6000 0020"转化为二进制:0110 0000 0000 0000 0000 0000 0010 0000

2.可以从二进制看出(因为or嘛,只要一个是1就会得到1),该区块共有三个属性,二进制表示为:
10 0000
10 0000 0000 0000 0000 0000 0000 0000
100 0000 0000 0000 0000 0000 0000 0000

3.转换为16进制,然后对比下面的对照表,就可以知道该区块具体是什么属性了。
对照表:


(2)区块表详解:http://blog.csdn.net/chengfeng0_0/article/details/7780252



谢谢小甲鱼带来的视频教程,感谢!! {:10_303:}

本节结束,多谢览阅!
越努力,越幸运。谢谢大家来看我的笔记{:10_297:},不对的请各位大佬指教,谢谢{:10_254:}

Krystian 发表于 2019-7-26 15:48:34

打卡学习

回忆浅离 发表于 2019-8-5 08:45:51

有没有办法在加密时降低时间复杂度
页: [1]
查看完整版本: 《解密系列-系统篇》第五讲:PE结构详解5