0%

PE文件判定

PE文件有效性验证

之前自己写了一个自己读的PE区段的小程序(当时是模仿CE写的一个内存搜索工具),当时写的是真的按照微软给的格式(什么NT头什么DOS头乱七八糟的)一个字节一个字节找的,但是后来发现居然有一个结构体居然可以直接拿来用,哎,失算失算~

IMAGE_DOS_HEADERIMAGE_NT_HEADERS

由于我的MSDN是2001年的,所以这个我是从IDE找到的,没有注释,但是大体的结构还是能看懂的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
typedef struct _IMAGE_DOS_HEADER {
WORD e_magic;
WORD e_cblp;
WORD e_cp;
WORD e_crlc;
WORD e_cparhdr;
WORD e_minalloc;
WORD e_maxalloc;
WORD e_ss;
WORD e_sp;
WORD e_csum;
WORD e_ip;
WORD e_cs;
WORD e_lfarlc;
WORD e_ovno;
WORD e_res[4];
WORD e_oemid;
WORD e_oeminfo;
WORD e_res2[10];
LONG e_lfanew;
} 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;

这个就是微软定义的一个结构,我们用这个结构就能够轻松的读取了,思路就是先打开文件,后读取文件,判断DOS头,判断NT头。
实现的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <windows.h>
using namespace std;

int main()
{
IMAGE_DOS_HEADER dosHeader;
IMAGE_NT_HEADERS ntHeaders;
char * text = new char;
cout<<"Please Input File Address:";
cin>>text;
cout<<text<<endl;
HANDLE hFile = CreateFile(text,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);//常规的打开一个文件
if(hFile == INVALID_HANDLE_VALUE)
{
cout<<"error file!";
return -1;
}
DWORD dwRead;
ReadFile(hFile,&dosHeader,sizeof(dosHeader),&dwRead,NULL);
if(dwRead == sizeof(dosHeader))
{
if(dosHeader.e_magic == IMAGE_DOS_SIGNATURE)//判断是不是MZ,就是你常见的那个
{
if(SetFilePointer(hFile,dosHeader.e_lfanew,NULL,FILE_BEGIN) != -1)
{
ReadFile(hFile,&ntHeaders,sizeof(ntHeaders),&dwRead,NULL);
if(dwRead == sizeof(ntHeaders))
{
if(ntHeaders.Signature == IMAGE_NT_SIGNATURE)//判断是不是那个PE
{
cout<<"Congrate!This is PE File!";
return 1;
}
}
}
}
}
cout<<"sorry,This is not!" ;
return -1;
}

还是比较简单的,用这两个结构体,那么具体如何读取区段之后再说!