十年網(wǎng)站開(kāi)發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專業(yè)推廣+無(wú)憂售后,網(wǎng)站問(wèn)題一站解決
(一).win32下的PE文件:
公司主營(yíng)業(yè)務(wù):成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站、移動(dòng)網(wǎng)站開(kāi)發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。創(chuàng)新互聯(lián)建站是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開(kāi)放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來(lái)的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來(lái)驚喜。創(chuàng)新互聯(lián)建站推出龍口免費(fèi)做網(wǎng)站回饋大家。
PE是Portable Execute的縮寫,是可移植可執(zhí)行的意思,只要文件的數(shù)據(jù)結(jié)構(gòu)遵循PE結(jié)構(gòu),就屬于PE文件,windows中常見(jiàn)的PE文件有
*.sys驅(qū)動(dòng)類文件
*.dll動(dòng)態(tài)鏈接庫(kù)文件
*.exe可執(zhí)行文件
*.ocx對(duì)象類別擴(kuò)充組建
*.obj目標(biāo)文件等.
同樣,linux中使用的是ELF格式,和windows的PE格式有一定的差別,如:
可重定位文件*.o
可執(zhí)行文件如/bin/ls等
共享目標(biāo)文件*.so
核心轉(zhuǎn)儲(chǔ)文件core
都遵循ELF數(shù)據(jù)結(jié)構(gòu). unix從system v4開(kāi)始也使用ELF了,而他們的始祖都是unix system v3的中COFF.如下圖:
(二).win32中的PE文件二進(jìn)制數(shù)據(jù)結(jié)構(gòu):
二進(jìn)制數(shù)據(jù)結(jié)構(gòu)如下圖,看起來(lái)就比較復(fù)雜,但是當(dāng)你親自動(dòng)手解析一波,那可能會(huì)改變你的世界觀,前提是初學(xué)者.為了全部顯示出來(lái),看不太清,放附件里了.
(三).win32中PE的邏輯圖:
一個(gè)標(biāo)準(zhǔn)的PE文件由DOS頭,stub,NT頭(包含PE標(biāo)識(shí),標(biāo)準(zhǔn)PE頭和可選PE頭三個(gè)成員),節(jié)表,節(jié)的內(nèi)容以及一些為了內(nèi)存對(duì)齊而填充的0.
以上就是一個(gè)PE文件的大體邏輯圖,它里面的內(nèi)容雖然是二進(jìn)制,但絕不是隨意填充的數(shù)據(jù),而是嚴(yán)格遵循一定格式生成的,比如C語(yǔ)言寫的一段代碼,通過(guò)預(yù)處理, 匯編, 編譯, 鏈接后生成的一個(gè)exe文件(PE文件中的一種),生成過(guò)程是由編譯器來(lái)完成的.
(四).DOS頭中的數(shù)據(jù)結(jié)構(gòu):
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語(yǔ)言實(shí)現(xiàn)對(duì)win32中notepad.exe的DOS頭的簡(jiǎn)單解析:
該代碼中只是輸出了DOS頭中兩個(gè)較為有用的數(shù)據(jù),第一個(gè)和最后一個(gè)(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" //包含進(jìn)自己寫的dos.h文件 #define filepath "notepad.exe" //指定好notepad.exe的位置,寫絕對(duì)路徑,或放于源代碼目錄中 int main(int argc, char* argv[]) { void* pbuff = NULL; //方便后面當(dāng)參數(shù)使用 pbuff = ReadFileToBuff(filepath); Output_Dos(pbuff); //解析DOS頭 free(pbuff); //釋放空間 return 0; }
dos.h:
void* ReadFileToBuff(char* file) //將文件讀取到內(nèi)存 { FILE* fp = fopen(file, "rb"); //以二進(jìn)制只讀形式打開(kāi)文件 void* buff = NULL; //用來(lái)指向申請(qǐng)的內(nèi)存緩沖區(qū) unsigned long sz = 0; //用來(lái)存放文件的大小 if(!fp) { printf("Failed to open file \"%s\"\n", file); exit(-1); } fseek(fp, 0, SEEK_END); //讓文件指針fp指向文件的末位位置,用于計(jì)算文件的大小 sz = ftell(fp); //獲取當(dāng)前文件指針相對(duì)于起始位置的偏移 fseek(fp, 0, SEEK_SET); //讓文件指針fp指向文件的起始位置 printf("File \"%s\" size: %ld KB\n", file, sz / 1024); //輸出文件大小(單位KB) buff = malloc(sz); //申請(qǐng)一塊與文件大小相等的內(nèi)存,用作文件緩沖區(qū) if(!buff) { printf("Alloc memery failed!\n"); exit(-2) } memset(buff, 0, sz); //置零緩沖區(qū) //將文件中的數(shù)據(jù)寫入文件緩沖區(qū),每次讀取128字節(jié),讀取sz/128次,正好讀取sz字節(jié) if(!fread(buff, 128, sz/128, fp)) { printf("Read file \"%s\" error!\n", file); exit(-3); } fclose(fp); //關(guān)閉剛剛打開(kāi)的文件 return buff; //返回文件緩沖的內(nèi)存地址 } //輸出DOS頭的重要信息 void Output_Dos(void* buffer) { void* buf = buffer; //定義一個(gè)指向文件緩沖的DOS頭的指針 IMAGE_DOS_HEADER* pdos = (IMAGE_DOS_HEADER*)buf; printf("DOS Header:\n"); //MZ標(biāo)記,用于判斷該文件是否為可執(zhí)行文件(其值與MZ的ascii相對(duì)應(yīng)) printf("Magic Number: %#X\n", pdos->e_magic); //PE標(biāo)識(shí)相對(duì)于文件其實(shí)位置的偏移 (單位字節(jié)) 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 //主要是把相應(yīng)的頭文件包含進(jìn)去 #include#include #include #include
執(zhí)行結(jié)果如下圖:
如果有空會(huì)繼續(xù)更新.