rgb565和rgb555的文件头区别_Windows可执行文件格式
前言
下文提及的相關數據結構,代碼片段均為64位環境,32位環境會加以標注.
? PE文件
PE(即Portable?Executable)表示可移植的可執行文件,是Windows平臺原生的可執行代碼載體(此處要區別于NET的IL,?JAVA的字節碼等),Windows平臺所有可以被加載執行的文件都遵從PE文件格式。
注:在linux平臺下的可執行文件都遵從ELF文件格式,PE與ELF文件格式都繼承于Unix的COFF文件格式,由此可見,雖然不同平臺上的可執行文件不能兼容,但是從設計思想上有很多共通之處。
PE文件格式詳解
文件數據結構布局
(網上有很多查看PE文件格式的工具,我常用010editor配合其EXE模版)
注:010editor模版所顯示的在Section Data后還有其他內容,這只是模版的顯示,相關內容其實還是在某個Section Data內部,但是由于其有特殊用途,故被模版單獨展示。
由上圖所示,一個PE文件有定長部分和不定長部分,這也體現了PE文件格式良好的可擴展性和兼容性。
定長部分:
DOS?header?+?DOS?Stub?+?NT?header
不定長部分:
Section?header[n]?+?Section?data[n]
磁盤布局與內存布局
一個PE文件,在加載運行前后的布局這里我叫做磁盤布局和內存布局,這兩種布局由于不同時期的對齊粒度不同導致有所差異:磁盤布局的對齊粒度是0x200,內存布局的對齊粒度是0x1000。
所以這里就有一個偏移地址轉換的問題,PE文件中大體上有四類地址:
虛擬內存地址(VA):RVA +?加載基地址
相對虛擬地址(RVA):內存偏移
文件偏移地址(FOA):文件偏移
特殊地址:這中地址很少見,在資源節中有使用,其計算方式類似于匯編相對跳轉的計算
相關數據結構(依次說明)
//DOS?Header結構typedef?struct?_IMAGE_DOS_HEADER
{
?????WORD?e_magic;????????//DOS文件簽名?0x4d5a
?????WORD?e_cblp;
?????WORD?e_cp;
?????WORD?e_crlc;
?????WORD?e_cparhdr;
?????WORD?e_minalloc;
?????WORD?e_maxalloc;
?????WORD?e_ss;
?????WORD?e_sp;
?????WORD?e_csum;
?????WORD?e_ip;
?????WORD?e_cs;
?????WORD?e_lfarlc;
?????WORD?e_ovno;
?????WORD?e_res[4];
?????WORD?e_oemid;
?????WORD?e_oeminfo;
?????WORD?e_res2[10];
?????LONG?e_lfanew;????????//NT頭偏移
}?IMAGE_DOS_HEADER,?*PIMAGE_DOS_HEADER;
其中最重要的是e_magic和e_lfanew字段,e_magic字段是文件頭,固定值0x4D5A,e_lfanew:NT頭的文件偏移,通常是0xE8
//DOS?Stub這是一小段Dos程序,當在Dos系統下運行時,會打印出"This?program?cannot?be?run?in?DOS?mode",現在基本不會用到。
//NT?header結構
typedef?struct?_IMAGE_NT_HEADERS64?{
??DWORD???????????????????Signature;????????//PE簽名,0x4550
??IMAGE_FILE_HEADER???????FileHeader;????????//文件頭
??IMAGE_OPTIONAL_HEADER64?OptionalHeader;????//可選頭
}?IMAGE_NT_HEADERS64,?*PIMAGE_NT_HEADERS64;
//File?Header結構
typedef?struct?_IMAGE_FILE_HEADER?{
??WORD??Machine;????????????????????????????//運行平臺
??WORD??NumberOfSections;????????????????????//Section?Header的數目
??DWORD?TimeDateStamp;????????????????????????//編譯時間戳
??DWORD?PointerToSymbolTable;????????????????//COFF符號表指針
??DWORD?NumberOfSymbols;????????????????????//符號數目
??WORD??SizeOfOptionalHeader;????????????????//可選頭大小,32位與64位大小不同
??WORD??Characteristics;????????????????????//屬性,實際上是一個bitmap
}?IMAGE_FILE_HEADER,?*PIMAGE_FILE_HEADER;
運行平臺:
| IMAGE_FILE_MACHINE_I386(0x014c) | x86 |
| IMAGE_FILE_MACHINE_IA64(0x0200) | Intel Itanium |
| IMAGE_FILE_MACHINE_AMD64(0x8664) | x64 |
//IMAGE_FILE_HEADER.Characteristics字段
struct?FILE_CHARACTERISTICS?Characteristics?{
????WORD?IMAGE_FILE_RELOCS_STRIPPED?:?1????????????????//在可執行文件中沒有使用。
????WORD?IMAGE_FILE_EXECUTABLE_IMAGE?:?1????????????//置1表示該文件為exe文件。
????WORD?IMAGE_FILE_LINE_NUMS_STRIPPED?:?1??????????//在可執行文件中沒有使用。
????WORD?IMAGE_FILE_LOCAL_SYMS_STRIPPED?:?1?????????//在可執行文件中沒有使用。
????WORD?IMAGE_FILE_AGGRESIVE_WS_TRIM?:?1???????????//在可執行文件中沒有使用。
????WORD?IMAGE_FILE_LARGE_ADDRESS_AWARE?:?1?????????//該應用程序可以處理大于2G的地址。
????WORD?IMAGE_FILE_BYTES_REVERSED_LO?:?1???????????//在可執行文件中沒有使用。
????WORD?IMAGE_FILE_32BIT_MACHINE?:?1???????????????//置1表示希望是32位平臺
????WORD?IMAGE_FILE_DEBUG_STRIPPED?:?1??????????????//在可執行文件中沒有使用。
????WORD?IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP?:?1?????//置1表示該程序不能在可移動介質中運行。
????WORD?IMAGE_FILE_NET_RUN_FROM_SWAP?:?1???????????//置1表示該程序不能在網絡中運行。
????WORD?IMAGE_FILE_SYSTEM?:?1??????????????????????//在可執行文件中沒有使用。
????WORD?IMAGE_FILE_DLL?:?1?????????????????????????//置1表示文件是一個動態鏈接庫。
????WORD?IMAGE_FILE_UP_SYSTEM_ONLY?:?1??????????????//置1該文件應僅在單處理器計算機上運行。
????WORD?IMAGE_FILE_BYTES_REVERSED_HI?:?1???????????//在可執行文件中沒有使用。
}
//IMAGE_OPTIONAL_HEADER64結構
typedef?struct?_IMAGE_OPTIONAL_HEADER64?{
??WORD?????????????????Magic;????????????????????????//判斷是32還是64位可執行映像
??BYTE?????????????????MajorLinkerVersion;????????????//鏈接器主版本號
??BYTE?????????????????MinorLinkerVersion;????????????//鏈接器此版本號
??DWORD????????????????SizeOfCode;????????????????????//多個代碼段大小
??DWORD????????????????SizeOfInitializedData;????????//多個初始化數據段大小
??DWORD????????????????SizeOfUninitializedData;????????//多個為初始化數據段大小
??DWORD????????????????AddressOfEntryPoint;????????????//代碼入口點的RVA
??DWORD????????????????BaseOfCode;????????????????????//代碼段基址
??ULONGLONG????????????ImageBase;????????????????????//加載基址
??DWORD????????????????SectionAlignment;????????????//內存對齊粒度,默認為頁面大小4k
??DWORD????????????????FileAlignment;????????????????//文件對齊粒度
??WORD?????????????????MajorOperatingSystemVersion;????//操作系統主版本號
??WORD?????????????????MinorOperatingSystemVersion;????//操作系統此次版本號
??WORD?????????????????MajorImageVersion;????????????//可執行文件主版本號
??WORD?????????????????MinorImageVersion;????????????//可執行文件次版本號
??WORD?????????????????MajorSubsystemVersion;????????//子系統主版本號
??WORD?????????????????MinorSubsystemVersion;????????//子系統此次版本號
??DWORD????????????????Win32VersionValue;????????????//保留,必須為0
??DWORD????????????????SizeOfImage;????????????????????//占用內存的大小,需對齊
??DWORD????????????????SizeOfHeaders;????????????//定長部分+SectionHeader數組的大小,需對齊
??DWORD????????????????CheckSum;????????????????????//校驗和
??WORD?????????????????Subsystem;????????????????????//所需子系統環境
??WORD?????????????????DllCharacteristics;????????????//映像屬性
??ULONGLONG????????????SizeOfStackReserve;????????????//棧保留大小
??ULONGLONG????????????SizeOfStackCommit;????????????//棧提交大小
??ULONGLONG????????????SizeOfHeapReserve;????????????//堆保留大小
??ULONGLONG????????????SizeOfHeapCommit;????????????//堆提交大小
??DWORD????????????????LoaderFlags;????????????????????//在可執行文件中沒有使用。
??DWORD????????????????NumberOfRvaAndSizes;????????????//DataDirectory表表項的數目
??IMAGE_DATA_DIRECTORY?DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];????//DataDirectory表
}?IMAGE_OPTIONAL_HEADER64,?*PIMAGE_OPTIONAL_HEADER64;
可選頭雖說名字叫可選頭,但是確是PE?件中最不可缺少的部分,其中 DataDirectory 數組尤為重要,??是系統加映像時,初始化資源的重要數據的索引,數組?共有16項,?項保留,其余15項分別對應15種資源索引,由于篇幅原因, DataDirectory 會在后?的?章中單獨詳細解讀。
以上就是PE?件中的定?結構部分,下?是不定?的Section Header數組和各個Section Data。
//Section?Header數組就是由一項一項的IMAGE_SECTION_HEADER結構構成//IMAGE_SECTION_HEADER結構
typedef?struct?_IMAGE_SECTION_HEADER?{
??BYTE??Name[IMAGE_SIZEOF_SHORT_NAME];????//char類型的八字節數組,保存section的名稱
??union?{
????DWORD?PhysicalAddress;
????DWORD?VirtualSize;
??}?Misc;????????????????????????????????//section加載到內存的大小
??DWORD?VirtualAddress;????????????????????//section起始地址的RVA
??DWORD?SizeOfRawData;????????????????????//Misc.VirtualSize內存對齊后的大小
??DWORD?PointerToRawData;????????????????//section起始地址的文件偏移
??DWORD?PointerToRelocations;????????????//指向該部分的重定位條目的文件偏移。為0則沒有重定位。
??DWORD?PointerToLinenumbers;????????????//未使用
??WORD??NumberOfRelocations;????????????//未使用
??WORD??NumberOfLinenumbers;????????????//未使用
??DWORD?Characteristics;????????????????//section屬性
}?IMAGE_SECTION_HEADER,?*PIMAGE_SECTION_HEADER;
section常?屬性:
| IMAGE_SCN_CNT_CODE(0x00000020) | 本節包含可執行代碼。 |
| IMAGE_SCN_CNT_INITIALIZED_DATA(0x00000040) | Section 含初始化數據。 |
| IMAGE_SCN_CNT_UNINITIALIZED_DATA(0x00000080) | Section 含未初始化的數據。 |
| IMAGE_SCN_GPREL(0x00008000) | 本節包含通過全局指針引用的數據。 |
| IMAGE_SCN_LNK_NRELOC_OVFL(0x01000000) | 本節包含擴展的重定位。 |
| IMAGE_SCN_MEM_SHARED(0x10000000) | 該部分可以在內存中共享。 |
| IMAGE_SCN_MEM_EXECUTE(0x20000000) | 該部分可以作為代碼執行。 |
| IMAGE_SCN_MEM_READ(0x40000000) | 可讀 |
| IMAGE_SCN_MEM_WRITE0x80000000 | 可寫 |
其他不常用標志見后面 MSDN 鏈接。
最后說明一下文件偏移和內存相對偏移的計算:FOA = RVA - VirtualAddress + PointerToRawData首先要判斷的的RVA地址所落在的section,條件是VirtualAddress <= RVA < VirtualAddress + SizeOfRawData附上我寫的轉換代碼,?個殼的代碼?段:
/*參數:RVA:內存相對偏移,pNT:指向NT頭的指針
返回:轉換后的文件偏移
*/
UINT32?RvaToOffset(UINT32?RVA,?PIMAGE_NT_HEADERS?pNT){
????UINT32?NumberOfSections?=?pNT->FileHeader.NumberOfSections;?//獲取Section數量
????UINT32?offset?=?0;
????PIMAGE_SECTION_HEADER?pSH?=?(PIMAGE_SECTION_HEADER)((UINT64)pNT?+?sizeof(IMAGE_NT_HEADERS));????//獲取Section?header數組
????for?(UINT32?i?=?0;?i?????{????????pSH->Characteristics?|=?IMAGE_SCN_MEM_WRITE;????//為每個section添加寫屬性????????if?(RVA?>=?pSH->VirtualAddress&&?RVA?VirtualAddress?+?pSH->SizeOfRawData)????????{????????????offset?=?RVA?-?pSH->VirtualAddress?+?pSH->PointerToRawData;????????}????}????return?offset;}
常?section?
這些都是VS編譯器?成的,??的數據帶有特定作?.
.bss:存放未初始化數據
.data:存放初始化數據
.edata:存放導出表
.idata:存放導?表
.pdata:存放異常信息
.rdata:存放初始化的只讀數據
.reloc:存放重定位信息
.rsrc:存放資源數據
.text:存放可執?代碼
.xdata:存放異常信息
?定義section
//在vs中可以通過以下方式自定一個section,命名為syclover#pragma?data_seg("syclover")?
char?WhoAmI[]?=?"syclover!";?
#pragma?data_seg()
注:SectionHeadr和SectionData并不是一一對應的關系,例如.bss段,占內存但是并不占文件空間,在文件中可以找到.bss段對應的SectionHeadr條目,但是并沒有對應的SectionData存在,
參考
https://blog.csdn.net/liuyez123/article/details/51281905
https://docs.microsoft.com/zh-cn/windows/win32/api/winnt/ns-winnt-image_nt_headers64
https://docs.microsoft.com/zh-cn/windows/win32/api/winnt/ns-winnt-image_section_header
長
按
關
注
三葉草小組公眾號
微信號 : 三葉草小組Syclover
新浪微博:@三葉草小組Syclover
在與你相遇的路上馬不停蹄~
總結
以上是生活随笔為你收集整理的rgb565和rgb555的文件头区别_Windows可执行文件格式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql两列数据去重_CiteSpac
- 下一篇: 一打开ie就停止工作怎么办 IE打不开怎