以下都是我个人的浅见,如有不对,多谢指出。
1、Windows的2种文件
01、可执行文件 EXE DLL
可执行文件 都有一个 PE 结构
PE结构:
DOS头
NT头
一个程序EXE= PE结构+数据
- IMAGE_DOS_HEADER STRUCT (转载)
- {
- +0h WORDe_magic //Magic DOS signature MZ(4Dh 5Ah) DOS可执行文件标记
- +2h WORDe_cblp//Bytes on last page of file
- +4h WORDe_cp//Pages in file
- +6h WORD e_crlc//Relocations
- +8h WORDe_cparhdr //Size of header in paragraphs
- +0ah WORD e_minalloc //Minimun extra paragraphs needs
- +0ch WORDe_maxalloc //Maximun extra paragraphs needs
- +0eh WORDe_ss //intial(relative)SS value DOS代码的初始化堆栈SS
- +10h WORDe_sp //intial SP value DOS代码的初始化堆栈指针SP
- +12h WORDe_csum //Checksum
- +14h WORDe_ip // intial IP value DOS代码的初始化指令入口[指针IP]
- +16h WORDe_cs //intial(relative)CS value DOS代码的初始堆栈入口
- +18h WORDe_lfarlc //File Address of relocation table
- +1ah WORDe_ovno // Overlay number
- +1ch WORDe_res[4] //Reserved words
- +24h WORDe_oemid // OEM identifier(for e_oeminfo)
- +26h WORD e_oeminfo // OEM information;e_oemid specific
- +29h WORDe_res2[10] // Reserved words
- +3ch DWORD e_lfanew //Offset to start of PE header 指向PE文件头
- } IMAGE_DOS_HEADER ENDS
02、不可执行文件 数据文件
2、每一个文件都是以二进制的方式存储在磁盘中的;
那么该如何区分一个文件是不是 可执行文件呢?
00、打开一个文件
CFile cFile(m_strFilePath, CFile::modeReadWrite);
01、先获取该文件的DOS头 IMAG_DOS_HEADER, 这是用来兼容DOS程序的;DOS头中包含了NT头的偏移位置。
IMAGE_DOS_HEADER dosHeader = { 0 };
DWORD dosSize = 0;
dosSize = cFile.Read(&dosHeader, sizeof(dosHeader));
if (dosSize != sizeof(dosHeader))
{
break;
}
02、通过DOS头中偏移位获取NT头的位置;
IMAGE_NT_HEADERS32 ntHeader = { 0 };
DWORD dntSize = 0;
cFile.Seek(dosHeader.e_lfanew, CFile::begin);
dntSize=cFile.Read(&ntHeader, sizeof(IMAGE_NT_HEADERS32));
if (dntSize != sizeof(IMAGE_NT_HEADERS32))
{
break;
}
03、判断ntHeader.Signature == IMAGE_NT_SIGNATURE
以下是我的代码:
CString strCheckPE = L"Not PE!!";
if (m_strFilePath.IsEmpty())
{
OnClickedButton1();
}
do
{
CFile cFile(m_strFilePath, CFile::modeReadWrite);
if (cFile.m_hFile != CFile::hFileNull)
{
IMAGE_DOS_HEADER dosHeader = { 0 };
DWORD dosSize = 0;
dosSize = cFile.Read(&dosHeader, sizeof(dosHeader));
if (dosSize != sizeof(dosHeader))
{
break;
}
if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE)
{
break;
}
IMAGE_NT_HEADERS32 ntHeader = { 0 };
DWORD dntSize = 0;
cFile.Seek(dosHeader.e_lfanew, CFile::begin);
dntSize=cFile.Read(&ntHeader, sizeof(IMAGE_NT_HEADERS32));
if (dntSize != sizeof(IMAGE_NT_HEADERS32))
{
break;
}
if (ntHeader.Signature == IMAGE_NT_SIGNATURE)
{
strCheckPE = L"Is PE!!";
}
}
} while (FALSE);
MessageBox(strCheckPE);