您好,登錄后才能下訂單哦!
(一).win32下的PE文件:
PE是Portable Execute的縮寫,是可移植可執行的意思,只要文件的數據結構遵循PE結構,就屬于PE文件,windows中常見的PE文件有
*.sys驅動類文件
*.dll動態鏈接庫文件
*.exe可執行文件
*.ocx對象類別擴充組建
*.obj目標文件等.
同樣,linux中使用的是ELF格式,和windows的PE格式有一定的差別,如:
可重定位文件*.o
可執行文件如/bin/ls等
共享目標文件*.so
核心轉儲文件core
都遵循ELF數據結構. unix從system v4開始也使用ELF了,而他們的始祖都是unix system v3的中COFF.如下圖:
(二).win32中的PE文件二進制數據結構:
二進制數據結構如下圖,看起來就比較復雜,但是當你親自動手解析一波,那可能會改變你的世界觀,前提是初學者.為了全部顯示出來,看不太清,放附件里了.
(三).win32中PE的邏輯圖:
一個標準的PE文件由DOS頭,stub,NT頭(包含PE標識,標準PE頭和可選PE頭三個成員),節表,節的內容以及一些為了內存對齊而填充的0.
以上就是一個PE文件的大體邏輯圖,它里面的內容雖然是二進制,但絕不是隨意填充的數據,而是嚴格遵循一定格式生成的,比如C語言寫的一段代碼,通過預處理, 匯編, 編譯, 鏈接后生成的一個exe文件(PE文件中的一種),生成過程是由編譯器來完成的.
(四).DOS頭中的數據結構:
Visual C++ 6.0中winnt頭文件中的定義:
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header WORD e_magic; // Magic number WORD e_cblp; // Bytes on last page of file WORD e_cp; // Pages in file WORD e_crlc; // Relocations WORD e_cparhdr; // Size of header in paragraphs WORD e_minalloc; // Minimum extra paragraphs needed WORD e_maxalloc; // Maximum extra paragraphs needed WORD e_ss; // Initial (relative) SS value WORD e_sp; // Initial SP value WORD e_csum; // Checksum WORD e_ip; // Initial IP value WORD e_cs; // Initial (relative) CS value WORD e_lfarlc; // File address of relocation table WORD e_ovno; // Overlay number WORD e_res[4]; // Reserved words WORD e_oemid; // OEM identifier (for e_oeminfo) WORD e_oeminfo; // OEM information; e_oemid specific WORD e_res2[10]; // Reserved words LONG e_lfanew; // File address of new exe header } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
(五).C語言實現對win32中notepad.exe的DOS頭的簡單解析:
該代碼中只是輸出了DOS頭中兩個較為有用的數據,第一個和最后一個(e_magic和e_lfanew),代碼如下:
Dos_Header_Analyze.cpp:
// Dos_Header_Analyze.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "dos.h" //包含進自己寫的dos.h文件 #define filepath "notepad.exe" //指定好notepad.exe的位置,寫絕對路徑,或放于源代碼目錄中 int main(int argc, char* argv[]) { void* pbuff = NULL; //方便后面當參數使用 pbuff = ReadFileToBuff(filepath); Output_Dos(pbuff); //解析DOS頭 free(pbuff); //釋放空間 return 0; }
dos.h:
void* ReadFileToBuff(char* file) //將文件讀取到內存 { FILE* fp = fopen(file, "rb"); //以二進制只讀形式打開文件 void* buff = NULL; //用來指向申請的內存緩沖區 unsigned long sz = 0; //用來存放文件的大小 if(!fp) { printf("Failed to open file \"%s\"\n", file); exit(-1); } fseek(fp, 0, SEEK_END); //讓文件指針fp指向文件的末位位置,用于計算文件的大小 sz = ftell(fp); //獲取當前文件指針相對于起始位置的偏移 fseek(fp, 0, SEEK_SET); //讓文件指針fp指向文件的起始位置 printf("File \"%s\" size: %ld KB\n", file, sz / 1024); //輸出文件大小(單位KB) buff = malloc(sz); //申請一塊與文件大小相等的內存,用作文件緩沖區 if(!buff) { printf("Alloc memery failed!\n"); exit(-2) } memset(buff, 0, sz); //置零緩沖區 //將文件中的數據寫入文件緩沖區,每次讀取128字節,讀取sz/128次,正好讀取sz字節 if(!fread(buff, 128, sz/128, fp)) { printf("Read file \"%s\" error!\n", file); exit(-3); } fclose(fp); //關閉剛剛打開的文件 return buff; //返回文件緩沖的內存地址 } //輸出DOS頭的重要信息 void Output_Dos(void* buffer) { void* buf = buffer; //定義一個指向文件緩沖的DOS頭的指針 IMAGE_DOS_HEADER* pdos = (IMAGE_DOS_HEADER*)buf; printf("DOS Header:\n"); //MZ標記,用于判斷該文件是否為可執行文件(其值與MZ的ascii相對應) printf("Magic Number: %#X\n", pdos->e_magic); //PE標識相對于文件其實位置的偏移 (單位字節) printf("PE Offset: %#X\n", pdos->e_lfanew); }
stdafx.h:
#if !defined(AFX_STDAFX_H__BBCA9272_49A3_4E1E_9262_9F0211C5BA05__INCLUDED_) #define AFX_STDAFX_H__BBCA9272_49A3_4E1E_9262_9F0211C5BA05__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers //主要是把相應的頭文件包含進去 #include <stdio.h> #include <windows.h> #include <stdlib.h> #include <malloc.h>
執行結果如下圖:
如果有空會繼續更新.
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。