日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 人文社科 > 生活经验 >内容正文

生活经验

PE文件和COFF文件格式分析——签名、COFF文件头和可选文件头2

發(fā)布時(shí)間:2023/11/27 生活经验 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PE文件和COFF文件格式分析——签名、COFF文件头和可选文件头2 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? ? ? ? 之前的博文中介紹了IMAGE_FILE_HEADER結(jié)構(gòu),現(xiàn)在來(lái)討論比較復(fù)雜的“可選文件頭”結(jié)構(gòu)體。(轉(zhuǎn)載請(qǐng)指明來(lái)自breaksoftware的csdn博客)先看下其聲明

typedef struct _IMAGE_OPTIONAL_HEADER {//// Standard fields.//WORD    Magic;...DWORD   BaseOfData;    // not exist in PE32+//// NT additional fields.//DWORD   ImageBase;...IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

? ? ? ? 看一下64位版本該結(jié)構(gòu)體

typedef struct _IMAGE_OPTIONAL_HEADER64 {WORD        Magic;...DWORD       BaseOfCode;ULONGLONG   ImageBase;...IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;

? ? ? ? ?我們觀察這個(gè)32位版本結(jié)構(gòu)體,可以看到該結(jié)構(gòu)體包含兩塊數(shù)據(jù):Standard fields和NT additional fields。我們可以猜想到,該結(jié)構(gòu)體應(yīng)該在第一個(gè)NT操作系統(tǒng)之前就存在了,只是當(dāng)時(shí)其內(nèi)容只有Standard fields(以后稱為標(biāo)準(zhǔn)域)下的內(nèi)容,后來(lái)NT系統(tǒng)增加了NT additional fields(以后稱為擴(kuò)展域)下元素。

? ? ? ? 此處需要特別注意一點(diǎn),我們看兩個(gè)在WinNT.h中定義的結(jié)構(gòu)體

typedef struct _IMAGE_NT_HEADERS64 {DWORD Signature;IMAGE_FILE_HEADER FileHeader;IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;typedef struct _IMAGE_NT_HEADERS {DWORD Signature;IMAGE_FILE_HEADER FileHeader;IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

? ? ? ? 該結(jié)構(gòu)給出了PE文件頭的結(jié)構(gòu)體布局,但是切記,這僅僅是布局。我們千萬(wàn)不要想當(dāng)然的認(rèn)為直接從PE頭部開(kāi)始將IMAGE_NT_HEADERS32(64)結(jié)構(gòu)體大小的數(shù)據(jù)拷貝到該結(jié)構(gòu)體對(duì)象中。

memcpy( &ImageNTHeader32,lpPEStart,sizeof(IMAGE_NT_HEADERS32 );// 這是錯(cuò)誤的!!

? ? ? ? 為什么?因?yàn)橐粋€(gè)文件中不一定有完整的IMAGE_OPTIONAL_HEADER32(64)結(jié)構(gòu)體對(duì)象信息。原因在《可選文件頭1》做了介紹,IMAGE_FILE_HEADER中字段SizeOfOptionalHeader指定了該文件中保存的“可選文件頭”真實(shí)長(zhǎng)度,我們應(yīng)該根據(jù)該元素來(lái)給IMAGE_OPTIONAL_HEADER32(64)對(duì)象賦值。

? ? ? ? 我們的文件是使用IMAGE_OPTIONAL_HEADER32還是IMAGE_OPTIONAL_HEADER64結(jié)構(gòu)體呢?可能有人會(huì)記起,我們?cè)凇犊蛇x文件頭1》中介紹了判斷文件是32位還是64位的方法,我們是否可以通過(guò)該判斷的結(jié)果來(lái)判斷是哪種結(jié)構(gòu)體呢?最開(kāi)始我也是這么想的,后來(lái)我發(fā)現(xiàn)我電腦上Microsoft Visual Studio 10.0\VC\lib\amd64\Microsoft.VisualC.STLCLR.dll文件是個(gè)64位文件但是使用了IMAGE_OPTIONAL_HEADER32結(jié)構(gòu)體!!!是不是很驚訝!我不知道微軟這么設(shè)計(jì)的原因,但是我知道了通過(guò)之前判斷是否為64位文件來(lái)決定可選文件頭結(jié)構(gòu)體類型是錯(cuò)誤的。那如何判斷呢?

? ? ? ? 其實(shí)是有標(biāo)記的。緊跟著IMAGE_FILE_HEADER結(jié)構(gòu)體的肯定是IMAGE_OPTIONAL_HEADER32(64)的Magic字段。如果該字段是0x010B,則是使用了IMAGE_OPTIONAL_HEADER32(稱為PE32);如果是0x020B,則使用了IMAGE_OPTIONAL_HEADER64(稱為PE32+)。切記PE32和PE32+和這個(gè)文件是32位文件還是64位文件是沒(méi)有關(guān)系的!它們是兩種不同的概念!切記要分清。

BOOL CGetPEInfo::GetOptionalHeader(){CHECKOPHEADER();GETFILETYPE();size_t unDwordSize = sizeof(DWORD);size_t unImgFileHeaderSize = sizeof(IMAGE_FILE_HEADER);size_t unImgOpHeaderSize = 0;LPBYTE lpImgOpHeaderAddr = m_lpPEStart + unDwordSize + unImgFileHeaderSize;LPVOID lpOpHeaderStart= NULL;WORD dwOptionHeader = 0;if ( FALSE == SafeCopy( &dwOptionHeader, lpImgOpHeaderAddr, sizeof(WORD) ) ) {return FALSE;}if ( E64Bit == m_eFileType && PE32MAGICNUM == dwOptionHeader ) {// D:\Microsoft Visual Studio 10.0\VC\lib\amd64\Microsoft.VisualC.STLCLR.dll//_ASSERT(FALSE);}if ( IMAGE_NT_OPTIONAL_HDR32_MAGIC == dwOptionHeader ) {// 64位系統(tǒng)文件也存在該格式可選頭m_eFileOpType  = EOp32;unImgOpHeaderSize = sizeof(IMAGE_OPTIONAL_HEADER32);lpOpHeaderStart = &m_OptionalHeader32;}else if ( IMAGE_NT_OPTIONAL_HDR64_MAGIC== dwOptionHeader ) {m_eFileOpType = EOp32Plus;unImgOpHeaderSize = sizeof(IMAGE_OPTIONAL_HEADER64);lpOpHeaderStart = &m_OptionalHeader64;}else {_ASSERT(FALSE);return FALSE;}memset( lpOpHeaderStart, 0 , unImgOpHeaderSize);// 根據(jù)鏡像文件頭中可選文件頭大小拷貝數(shù)據(jù)BOOL bSuc = SafeCopy( lpOpHeaderStart, lpImgOpHeaderAddr, m_FileHeader.SizeOfOptionalHeader );if ( bSuc ) {m_dwInfoMask |= OPHEADER;}else {_ASSERT(FALSE);}if ( EOp32 == m_eFileOpType ) {m_dwFileAlignment = m_OptionalHeader32.FileAlignment;}else {m_dwFileAlignment = m_OptionalHeader64.FileAlignment;}return bSuc;
}

? ? ? ? 現(xiàn)在我們將重心放到IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];這個(gè)數(shù)組元素,我在《可選文件頭1》中對(duì)此有了點(diǎn)描述,而且我還說(shuō)可選文件頭大小要看這個(gè)數(shù)組元素的“位置”(而不是個(gè)數(shù))來(lái)決定的?,F(xiàn)在我來(lái)細(xì)說(shuō)下。先看下微軟的聲明

typedef struct _IMAGE_DATA_DIRECTORY {DWORD   VirtualAddress;DWORD   Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES    16#define IMAGE_DIRECTORY_ENTRY_EXPORT ? ? ? ? ?0 ? // Export Directory
#define IMAGE_DIRECTORY_ENTRY_IMPORT ? ? ? ? ?1 ? // Import Directory
#define IMAGE_DIRECTORY_ENTRY_RESOURCE ? ? ? ?2 ? // Resource Directory
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION ? ? ? 3 ? // Exception Directory
#define IMAGE_DIRECTORY_ENTRY_SECURITY ? ? ? ?4 ? // Security Directory
#define IMAGE_DIRECTORY_ENTRY_BASERELOC ? ? ? 5 ? // Base Relocation Table
#define IMAGE_DIRECTORY_ENTRY_DEBUG ? ? ? ? ? 6 ? // Debug Directory
// ? ? ?IMAGE_DIRECTORY_ENTRY_COPYRIGHT ? ? ? 7 ? // (X86 usage)
#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE ? ?7 ? // Architecture Specific Data
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR ? ? ? 8 ? // RVA of GP
#define IMAGE_DIRECTORY_ENTRY_TLS ? ? ? ? ? ? 9 ? // TLS Directory
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG ? ?10 ? // Load Configuration Directory
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT ? 11 ? // Bound Import Directory in headers
#define IMAGE_DIRECTORY_ENTRY_IAT ? ? ? ? ? ?12 ? // Import Address Table
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT ? 13 ? // Delay Load Import Descriptors
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 ? // COM Runtime descriptor

? ? ? ??DataDirectory保存了指向“塊信息”的目錄信息,其中包括偏移(除了IMAGE_DIRECTORY_ENTRY_SECURITY元素是相對(duì)文件偏移RA,其他都是相對(duì)虛擬首地址偏移RVA)和大小。如果某文件只包含IMAGE_DIRECTORY_ENTRY_EXPORT(0) 、IMAGE_DIRECTORY_ENTRY_IMPORT(1) 和IMAGE_DIRECTORY_ENTRY_BASERELOC(5)等三個(gè)目錄,則IMAGE_DIRECTORY_ENTRY_EXCEPTION(2)、IMAGE_DIRECTORY_ENTRY_SECURITY(3)和IMAGE_DIRECTORY_ENTRY_SECURITY(4)的信息都要被填充0。于是IMAGE_FILE_HEADER::SizeOfOptionalHeader所指定的可選文件頭大小為DataDirectory之前的元素總大小加上6(最后一個(gè)目錄IMAGE_DIRECTORY_ENTRY_BASERELOC所在的位置5+1)*sizeof(IMAGE_DATA_DIRECTORY)。這就說(shuō)明了為什么可選文件頭大小是根據(jù)目錄的位置而不是數(shù)量來(lái)決定的。

? ? ? ? 下篇博文我們將詳細(xì)說(shuō)一下IMAGE_OPTIONAL_HEADER32和IMAGE_OPTIONAL_HEADER64中其他元素的意義。

總結(jié)

以上是生活随笔為你收集整理的PE文件和COFF文件格式分析——签名、COFF文件头和可选文件头2的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。