在Dump PE File的section table時候,一開始選用RVA來計算section的地址,以期望能取到Section信息,后來發(fā)現(xiàn)不完全正確,應(yīng)該用PointerToRawData的值。
如果根據(jù)自己定義的內(nèi)存對齊的值,將FileAlignment和SectionAlignment設(shè)為相同的對齊方式,這個時候生成的PE文件,RVA和PointerToRawData的值指向同一個地址,此時要取到Section的信息,用RVA也可以,因為值是一樣的。但是從意義上來說不完全正確。
一般生成的PE文件,假設(shè)FileAlignment = 200 Byte; SectionAlignment = 1000 Byte,此時RVA的值不等于PointerToRawData的值。如果不是由OS的loader裝載,也就是說,我要自己dump一個PE File,在自己的code中用的是fopen(),fread()這樣的函數(shù)將文件讀進內(nèi)存,而他們的作用僅僅是copy,并不像OS的loader將文件載入內(nèi)存,因此自己要要取Section的信息,應(yīng)該以后者的值來計算。因為如果是OS的loader載入文件,就會將文件按照Section Alignment的預(yù)設(shè)值將文件的各個部分放置內(nèi)存的各個memory page中。
以下附上Section Header的定義。
Section Header在WinNT.h中的結(jié)構(gòu)定義:
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union {
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
1.VirtualAddress:本Section的RVA(相對虛擬地址)。PE裝載器將本section映射至內(nèi)存時會讀取本值,因此如果域值是1000h,而PE文件裝在地址400000h處,那么本節(jié)就被載到401000h。微軟把第一個Section 的此域值設(shè)為0x1000h。對于OBJ文檔,此域沒意義,總為0。
2.SizeOfRawData:經(jīng)過文件對齊處理后Section尺寸,PE裝載器提取本域值了解需映射入內(nèi)存的節(jié)字節(jié)數(shù)。 假設(shè)一個文件的文件對齊尺寸是0x200,如果前面的 VirtualSize 域指示本Section的長度是0x388字節(jié),則本域值為0x400,表示本節(jié)是0x400字節(jié)長。在obj中,這個與表示有編譯器指定的真正的section 大小。
3.PointerToRawData:這是本Section基于文件的偏移量,PE裝載器通過本域值找到Section數(shù)據(jù)在文件中的位置。 如果是你自己以內(nèi)存映射的方式應(yīng)設(shè)了一個PE程序(而不是由操作系統(tǒng)的裝載器載入),那么這個域比VirtualAddress更重要。在這種情況下你有一個完全線性的文件映射,那么你就必須根據(jù)此值找到本Section的信息,而不是根據(jù)VirtualAddress 中的RVA值。