PE檔案檢測DOS頭\NT頭

MINI__SMALL__PIG發表於2017-09-10

以下都是我個人的淺見,如有不對,多謝指出。

1、Windows2種檔案

01、可執行檔案 EXE DLL

可執行檔案 都有一個 PE 結構

PE結構:

DOS

NT

一個程式EXE= PE結構+資料

 

  1,每個PE檔案是以一個DOS程式開始的,有了它,一旦程式在DOS下執行,DOS才能識別出這是有效的執行體。
   2,PE檔案的第一個位元組起始於一個傳統的MS-DOS頭部,被稱作為IMAGE_DOS_HEADER。

 

  1. IMAGE_DOS_HEADER STRUCT  (轉載)
  2. {  
  3. +0h WORDe_magic //Magic DOS signature MZ(4Dh 5Ah)     DOS可執行檔案標記  
  4. +2h WORDe_cblp//Bytes on last page of file    
  5. +4h WORDe_cp//Pages in file  
  6. +6h WORD e_crlc//Relocations  
  7. +8h WORDe_cparhdr   //Size of header in paragraphs  
  8. +0ah WORD e_minalloc  //Minimun extra paragraphs needs  
  9. +0ch WORDe_maxalloc  //Maximun extra paragraphs needs  
  10. +0eh WORDe_ss  //intial(relative)SS value    DOS程式碼的初始化堆疊SS  
  11. +10h WORDe_sp  //intial SP value               DOS程式碼的初始化堆疊指標SP  
  12. +12h WORDe_csum  //Checksum  
  13. +14h WORDe_ip  //    intial IP value                   DOS程式碼的初始化指令入口[指標IP]  
  14. +16h WORDe_cs  //intial(relative)CS value                    DOS程式碼的初始堆疊入口  
  15. +18h WORDe_lfarlc  //File Address of relocation table  
  16. +1ah WORDe_ovno        //    Overlay number  
  17. +1ch WORDe_res[4]  //Reserved words  
  18. +24h WORDe_oemid  //    OEM identifier(for e_oeminfo)  
  19. +26h WORD      e_oeminfo   //    OEM information;e_oemid specific   
  20. +29h WORDe_res2[10]   //    Reserved words  
  21. +3ch DWORD   e_lfanew     //Offset to start of PE header             指向PE檔案頭  
  22. } IMAGE_DOS_HEADER ENDS  

02、不可執行檔案 資料檔案


2、每一個檔案都是以二進位制的方式儲存在磁碟中的;

那麼該如何區分一個檔案是不是 可執行檔案呢?

WORD e_magic  //---DOS可執行檔案標記.
DWORD e_lfanew   ///--- 指向PE檔案頭(這個是一個指標)

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);

相關文章