本文刊登于2007年第8期的《黑客防线》,有内容部分改动。 正文如下: 从杀毒软件的角度来讲检测文件是否为PE文件,并再进一步判断使用何种方式对文件进行操作。在病毒感染可执行文件时,也是应该有这样步骤的。那么,就来看看杀毒软件是如何检测PE文件的有效性了。 PE文件是在windows系统中任何可执行模块或者DLL的文件格式。PE的意思是Portable Executable(可移植的执行体)。它是Win32环境自身所带的执行体文件格式。PE文件格式是跨Win32平台的,就是说即使是运行在非Intel CPU上的Windows都能够被PE装载器识别和使用该文件格式。 所有常见的PE结构定义在winnt.h头文件中。我们一般关心的有:IMAGE_DOS_HEADER、IMAGE_FILE_HEADER、IMAGE_OPTIONAL_HEADER32、IMAGE_SECTION_HEADER、IMAGE_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_magic为DOS可执行文件标记;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