PE文件 节表IMAGE_SECTION_HEADER的正确定位方法

网络上大部分资料对PE文件的节表的定位方式都是下面这样的

1 (LPVOID)((BYTE *)a + ((PIMAGE_DOS_HEADER)a)->e_lfanew + SIZE_OF_NT_SIGNATURE + sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER):

其意思是这样的:

为了在解释上面的代码之前:首先要介绍些PE头的结构。

在PE文件中开始是DOS头,之后是Stub dos,再之后是NT头,在之后是节表头。也就是我们要定位的。

其中NT头的定义是这样的

typedef struct _IMAGE_NT_HEADERS
    {
      DWORD                 Signature;
      IMAGE_FILE_HEADER     FileHeader;
      IMAGE_OPTIONAL_HEADER32 OptionalHeader;
    } IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;

他包括三个部分。

1》PE文件标识

2》文件头

3》可选头

现在就可以理解最开始的那条语句的含义

首先

1
((PIMAGE_DOS_HEADER)a)->e_lfanew 指向NT头的起始文件偏移(FOA)

之后

1
SIZE_OF_NT_SIGNATURE +  sizeof (IMAGE_FILE_HEADER) +  sizeof (IMAGE_OPTIONAL_HEADER)  //NT头的大小

加上NT头的大小。前面我们说过节表头紧跟在NT头之后,这样定位似乎很合理,很正确。开始我也是这么以为的,但是知道我碰到无法定位节表头的情况下我才仔细对比了字节码中的数据。

我是打开的eclipse.exe(java开发的朋友应该很了解吧,^_^).我发现在节表头和可选头的中间有16个空余,它既不在IMAGE_OPTION_HEADER32中有定义,也不再节表中定义。但是有的PE文件中并没有者16个字节。这就是我们用上面的定位方式无法准确的定位所有的PE文件的原因。

哎,找到这里我深深地擦了一把大汗,我这时陷入了困境,但是我突然回想起来,在IMAGE_FILE_HEADER中有一个字段指明了可选头的大小。它就是

复制代码
1 typedef struct _IMAGE_FILE_HEADER
2     {
3         WORD    Machine;     //运行平台
4         WORD    NumberOfSections; //文件的区块数目
5         DWORD   TimeDateStamp;    //文件创建日期和事件
6         DWORD   PointerToSymbolTable; //只想符号表(主要用于调试)
7         DWORD   NumberOfSymbols;      //符号表中的符号个数(同上)
8         WORD    SizeOfOptionalHeader;  //IMAGE_OPTIONAL_HEADER32结构大小
复制代码

红色标注的部分。之后我在此对比了eclipse的字节码,发现使用该字段来定位,就ok了

那么正确的定位方法就是这样了。

IMAGE_DOS_HEADER.e_lfanew  //文件头FOA
+ 4//PE文件标识
+ sizeof(PEStructs::IMAGE_FILE_HEADER)  //文件头大小
+ pTemFileHeader->SizeOfOptionalHeader, //可选头大小

哎,看到这里,功夫总算不负有心人。拿出来分享下,免得其它童鞋,也误入歧途。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值