检测PE文件的有效性

2008年01月14日 星期一 13:41

       本文刊登于2007年第8期的《黑客防线》,有内容部分改动。

正文如下:

从杀毒软件的角度来讲检测文件是否为PE文件,并再进一步判断使用何种方式对文件进行操作。在病毒感染可执行文件时,也是应该有这样步骤的。那么,就来看看杀毒软件是如何检测PE文件的有效性了。

PE文件是在windows系统中任何可执行模块或者DLL的文件格式。PE的意思是Portable Executable(可移植的执行体)。它是Win32环境自身所带的执行体文件格式。PE文件格式是跨Win32平台的,就是说即使是运行在非Intel CPU上的Windows都能够被PE装载器识别和使用该文件格式。

所有常见的PE结构定义在winnt.h头文件中。我们一般关心的有:IMAGE_DOS_HEADERIMAGE_FILE_HEADERIMAGE_OPTIONAL_HEADER32IMAGE_SECTION_HEADERIMAGE_NT_HEADER……还有很多的!在这里,我们只讨论两个结构,一个是IMAGE_DOS_HEADER,另一个是IMAGE_NT_HEADERS。通过这两个结构,我们就可以完成我们检测PE有效性的功能了。好了,看看这两个结构在winnt.h中的定义吧。

typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header

    WORD   e_magic;                     // Magic number

    ……

    LONG   e_lfanew;                    // File address of new exe header

} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

typedef struct _IMAGE_NT_HEADERS {

    DWORD Signature;

    IMAGE_FILE_HEADER FileHeader;

    IMAGE_OPTIONAL_HEADER32 OptionalHeader;

} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

由于IMAGE_DOS_HEADER结构中有很多成员,因此我们只列出了我们要讨论的就可以了,其他的就用省略号代替就可以了。在_IMAGE_DOS_HEADER结构中,e_magicDOS可执行文件标记;e_lfanew是相对实际PE头标的相对偏移量,也就是IMAGE_NT_HEADERS结构的地址。在IMAGE_NT_HEADERS中,我们只使用Signature这个成员,它是PE文件的标识(PE/0/0)。为了方便编程,在winnt.h中为DOS标识和PE标识定义了宏,分别是:

#define IMAGE_DOS_SIGNATURE                 0x5A4D      // MZ

#define IMAGE_NT_SIGNATURE                  0x00004550 // PE00

好了,有了上面的PE结构的知识,我们就可以完成检测PE文件的有效性的程序了。那么来看看编写检测PE文件有效性程序的步骤好了。首先,我们需要用CreateFile打开要检测的文件,然后通过判断是否是IMAGE_DOS_SIGNATURE来检测是否是有效的DOS头,接下来用e_lfnew来定位PE头了,最后通过判断是否是IMAGE_NT_SIGNATURE来检测文件的有效性了。一共四步,不过最后记得要用CloseHandle来关闭已打开文件的句柄。好了,可以介绍的内容大概就这么多了,来看看具体的代码吧!

//这里就是我们的第一步,打开要检测的文件

hFile=CreateFile(FileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

 

//这里是第二步,检测DOS头部的有效性

ReadFile(hFile,&image_dos_header,sizeof(image_dos_header),&dwRead,NULL);

if(dwRead==sizeof(image_dos_header))

{

if(IMAGE_DOS_SIGNATURE==image_dos_header.e_magic)

{//这里是第三步,定位image_nt_headers的位置

       if(SetFilePointer(hFile,image_dos_header.e_lfanew,NULL,FILE_BEGIN))

       {

              ReadFile(hFile,&image_nt_headers,sizeof(image_nt_headers),&dwRead,NULL);

              if(dwRead==sizeof(image_nt_headers))

              {//这里就是最后一步了,检测PE头部的有效性

                     if(IMAGE_NT_SIGNATURE==image_nt_headers.Signature)

                     b=TRUE;

              }

       }

}

}

 

if(b)

MessageBox("该程序是一个有效PE文件!");

else

MessageBox("该程序不是一个有效PE文件!");

 

CloseHandle(hFile);

 

依据我开始写的程序的逻辑,得到了这样的代码,其中还有CreateFile()ReadFile()SetFilePointer()这些API函数,它们都可以在MSDN中找到,大家自己找一下吧。这里就不在给出它们的定义了。

其实这种方式并不是唯一的一种检测PE文件有效性的方式,这些也只是起到抛砖引玉的目的了。在《黑防》今年第4期中的《以“熊猫烧香”的名义,再谈Delphi编写病毒程序》文章中,这位作者判断PE文件有效性的方式是顺序读取文件前0x108字节的内容,每次读取两个字节,然后判断是否为“PE”标识。当然,除了这两种方法外,还有其他的方法。在另外的其他方式中不在使用ReadFile()SetFilePointer()这两个API函数了,而是除了使用CreateFile()函数外,还要使用一些内存映射文件方面的相关函数CreateFileMapping()MapViewOfFile()。这里就不讨论它们了,就留给大家自己去研究一下了。

 

以上就是文章的正文了。

 

引自:   http://hi.baidu.com/jester/blog/item/3e79a3865d37413a67096eb2.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值