_______________________________
| IMAGE_DOS_HEADER | <-- Dos部首
-------------------------------
| PE,0,0 | <-- PE文件標(biāo)志
-------------------------------
| IMAGE_FILE_HEADER | <-- 映像文件頭
-------------------------------
| IMAGE_OPTIONAL_HEADER32 | <-- 映像可選頭
-------------------------------
| Section Table | <-- 節(jié)表
-------------------------------
| .text | <-- 代碼區(qū)段
-------------------------------
| .data | <-- 數(shù)據(jù)區(qū)段
-------------------------------
| .idata | <-- 輸入表
-------------------------------
| .edata | <-- 輸出表
-------------------------------
| .reloc | <-- 重定位表區(qū)段
-------------------------------
|
. |
-------------------------------
| 調(diào)試信息 |
-------------------------------
根據(jù)這個(gè)結(jié)構(gòu)表IMAGE_OPTIONAL_HEADER下面緊接著就是區(qū)塊表和各種區(qū)塊,也可以叫做節(jié)表和節(jié)英文是SECTION。
節(jié)表是由一大堆的IMAGE_SECTION_HEADER排列成的一個(gè)數(shù)據(jù)結(jié)構(gòu)。其數(shù)量由IMAGE_NT_HEADERS結(jié)構(gòu)中的FileHeader.NumberOfSections成員來(lái)決
定。
IMAGE_SECTION_HEADER的結(jié)構(gòu)如下
typedef struct _IMAGE_SECTION_HEADER


{
BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; // 節(jié)表名稱,如“.text”
//IMAGE_SIZEOF_SHORT_NAME=8
union

{
DWORD PhysicalAddress; // 物理地址
DWORD VirtualSize; // 真實(shí)長(zhǎng)度,這兩個(gè)值是一個(gè)聯(lián)合結(jié)構(gòu),可以使用其中的任何一個(gè),一
// 般是取后一個(gè)
} Misc;
DWORD VirtualAddress; // 節(jié)區(qū)的 RVA 地址
DWORD SizeOfRawData; // 在文件中對(duì)齊后的尺寸
DWORD PointerToRawData; // 在文件中的偏移量
DWORD PointerToRelocations; // 在OBJ文件中使用,重定位的偏移
DWORD PointerToLinenumbers; // 行號(hào)表的偏移(供調(diào)試使用地)
WORD NumberOfRelocations; // 在OBJ文件中使用,重定位項(xiàng)數(shù)目
WORD NumberOfLinenumbers; // 行號(hào)表中行號(hào)的數(shù)目
DWORD Characteristics; // 節(jié)屬性如可讀,可寫,可執(zhí)行等 } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
Name 里面存的是區(qū)塊的名字
.text code 什么的就是放代碼用的
.data 就是放數(shù)據(jù),已經(jīng)初始化好的
.idata 就是輸入表 ,很多加殼程序會(huì)修改輸入表,hook api 在程序運(yùn)行api時(shí),讓殼取得一定時(shí)間的權(quán)限來(lái)反跟蹤,脫殼的一大步驟就是還原輸入表。
.edata 輸出表
.bbs 未初始化的數(shù)據(jù)
VirtualSizes是一個(gè)非常牛逼的成員,其中的值是區(qū)塊沒(méi)有按FileAlignment對(duì)其前的大小,通過(guò)它可以推算出區(qū)塊中還有多少?zèng)]有被使用,很多病毒會(huì)在未被是用的空間里
插入自己的代碼。
Characteristics 表示該區(qū)塊的屬性 可讀啊 可寫啊什么的
// IMAGE_SCN_TYPE_REG 0x00000000 // Reserved.
// IMAGE_SCN_TYPE_DSECT 0x00000001 // Reserved.
// IMAGE_SCN_TYPE_NOLOAD 0x00000002 // Reserved.
// IMAGE_SCN_TYPE_GROUP 0x00000004 // Reserved.
#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved.
// IMAGE_SCN_TYPE_COPY 0x00000010 // Reserved.

#define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code.
//區(qū)段包含代碼
#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // Section contains initialized data.
//區(qū)段包含已初始化數(shù)據(jù)
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // Section contains uninitialized data.
//區(qū)段包含未初始化數(shù)據(jù)
#define IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved.
#define IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments
// or some other type of information.
// IMAGE_SCN_TYPE_OVER 0x00000400 // Reserved.
#define IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image.
#define IMAGE_SCN_LNK_COMDAT 0x00001000 // Section contents comdat.
// 0x00002000 // Reserved.
// IMAGE_SCN_MEM_PROTECTED - Obsolete 0x00004000
#define IMAGE_SCN_NO_DEFER_SPEC_EXC 0x00004000 // Reset speculative exceptions handling bits
// in the TLB entries for this section.
#define IMAGE_SCN_GPREL 0x00008000 // Section content can be accessed relative to GP
#define IMAGE_SCN_MEM_FARDATA 0x00008000
// IMAGE_SCN_MEM_SYSHEAP - Obsolete 0x00010000
#define IMAGE_SCN_MEM_PURGEABLE 0x00020000
#define IMAGE_SCN_MEM_16BIT 0x00020000
#define IMAGE_SCN_MEM_LOCKED 0x00040000
#define IMAGE_SCN_MEM_PRELOAD 0x00080000

#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 //
#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 //
#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 //
#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 //
#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 // Default alignment if no others are specified.
#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 //
#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 //
#define IMAGE_SCN_ALIGN_128BYTES 0x00800000 //
#define IMAGE_SCN_ALIGN_256BYTES 0x00900000 //
#define IMAGE_SCN_ALIGN_512BYTES 0x00A00000 //
#define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000 //
#define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000 //
#define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000 //
#define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000 //
// Unused 0x00F00000

#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 // Section contains extended relocations.
#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // Section can be discarded.
//該區(qū)段可丟棄
#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 // Section is not cachable.
#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 // Section is not pageable.
#define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable.
//該區(qū)段可共享
#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable.
//該區(qū)段可執(zhí)行
#define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable.
//該區(qū)段可讀
#define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writeable.
//該區(qū)段可寫最后寫個(gè)程序把這個(gè)結(jié)構(gòu)讀出來(lái)
由于我比較懶就只讀了Name這個(gè)成員,有些加殼軟件會(huì)修改Name這個(gè)字段使讀出來(lái)的東西亂七八糟,比如UPX的壓縮殼,會(huì)把Name字段改成UPX0,UPX1這樣
#include "windows.h"
#include "stdio.h"

int main(int argc, char* argv[])


{
FILE *p;
int i;
unsigned long Signature;
IMAGE_FILE_HEADER myfileheader;
IMAGE_DOS_HEADER mydosheader;
IMAGE_OPTIONAL_HEADER myoptionalheader;
IMAGE_SECTION_HEADER mysectionheader;

p = fopen("test.exe","r+b");
if(p == NULL)return -1;

fread(&mydosheader,sizeof(mydosheader),1,p);
fseek(p,mydosheader.e_lfanew,SEEK_SET);
fread(&Signature,sizeof(Signature),1,p);

fseek(p,mydosheader.e_lfanew+sizeof(Signature),SEEK_SET);//指向IMAGE_FILE_HEADER結(jié)構(gòu)的偏移
fread(&myfileheader,sizeof(myfileheader),1,p);

fseek(p,mydosheader.e_lfanew+sizeof(Signature)+sizeof(myfileheader)+sizeof(myoptionalheader),SEEK_SET);
printf("Signature : %04X\n",Signature);
printf("IMAGE_SECTION_HEADER 結(jié)構(gòu):\n");

for(i=0;i<myfileheader.NumberOfSections;i++)
{
fread(&mysectionheader,sizeof(mysectionheader),1,p);
printf("Name : %s\n",mysectionheader.Name);
}
fclose(p);
return 0;
}