0%

PE节表说明

上一篇文章解析了PE结构的几个头,这次把节表的结构也写了进来。

节表储存着所有节的相关信息,节表就相当于是目录,告诉你某一个节在哪块,它的相关信息什么。

节表的结构及意义

先直接给出节表的结构体方便后面的学习

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#define IMAGE_SIZEOF_SHORT_NAME              8

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;
  • Name,可以看到第一个数组为名字,长度为8个字节,这里需要注意的是它并不是必须遵循 \0 结尾的规定,如果不以 \0 结尾,系统会自动截取8位进行处理。
  • Misc,这是一个联合体,因为它们都是DWORD的长度,所以不需要过于区分,我们常用的都是VirtualSize,它是在没有对齐前的真实长度。
  • VirtualAddress,它是在内存中的偏移地址。
  • SizeOfRawData,在文件中对其后的长度。
  • PointerToRawData,在文件中的偏移地址。
  • PointerToRelocations、PointerToLinenumbers、NumberOfRelocations、NumberOfLinenumbers 这四个主要是在调试的时候去使用的,这里暂时先忽略掉。
  • Characteristics,节的属性,由于节的名字是可以随便修改的,并不是说它叫.date,它就是数据段,我们需要通过属性来对其内容进行一个简要的判断。

通过上面的结构可以很清楚的得到节表的长度为40个字节。

节表解析代码

这里没有单独将节表的解析拉出来写,而是在上一篇的基础上增加的,所以这里将是PE头和节表的整体代码

代码:GitHub

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include <stdio.h>
#include <windows.h>

int filesize(FILE* file) {
fseek(file, 0, SEEK_END);
int size = ftell(file);
fseek(file, 0, SEEK_SET);
return size;
}

int DOS_Header(LPSTR pFileBuffer) {
printf("----------DOSHeader----------\n");
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;

// *(PWORD)pDosHeader != IMAGE_DOS_SIGNATURE
if ((WORD)pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
printf("DOSHeader failed:MZ");
return 0;
}
printf("* e_magic:%x\n", (WORD)pDosHeader->e_magic);
printf("* e_lfanew:%08x\n", (DWORD)pDosHeader->e_lfanew);

return pDosHeader->e_lfanew;
}

int NT_Header(LPSTR pFileBuffer, int NT_addr) {
printf("----------NTHeader----------\n");
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(pFileBuffer + NT_addr);
if ((WORD)pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
printf("NTHeader failed:NT");
return 0;
}
printf("Signature:%08x\n", (DWORD)pNtHeader->Signature);

printf("----------FileHeader----------\n");
PIMAGE_FILE_HEADER FileHeader = (PIMAGE_FILE_HEADER)((DWORD)pNtHeader + 4);
printf("* Machine:%04x\n", FileHeader->Machine);
printf("* NumberOfSections:%04x\n", FileHeader->NumberOfSections);
printf("TimeDateStamp:%08x\n", FileHeader->TimeDateStamp);
printf("* SizeOfOptionalHeader:%04x\n", FileHeader->SizeOfOptionalHeader);
printf("Characteristics:%04x\n", FileHeader->Characteristics);

printf("----------OptionalHeader----------\n");
PIMAGE_OPTIONAL_HEADER32 OptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pNtHeader + 4 + sizeof(_IMAGE_FILE_HEADER));
printf("* Magic:%04x\n", OptionalHeader->Magic);
printf("- SizeOfCode:%08x\n", OptionalHeader->SizeOfCode);
printf("- SizeOfInitializedData:%08x\n", OptionalHeader->SizeOfInitializedData);
printf("- SizeOfUninitializedData:%08x\n", OptionalHeader->SizeOfUninitializedData);
printf("* AddressOfEntryPoint:%08x\n", OptionalHeader->AddressOfEntryPoint);
printf("- BaseOfCode:%08x\n", OptionalHeader->BaseOfCode);
printf("- BaseOfData:%08x\n", OptionalHeader->BaseOfData);
printf("* ImageBase:%08x\n", OptionalHeader->ImageBase);
printf("* SectionAlignment:%08x\n", OptionalHeader->SectionAlignment);
printf("* FileAlignment:%08x\n", OptionalHeader->FileAlignment);
printf("* SizeOfImage:%08x\n", OptionalHeader->SizeOfImage);
printf("* SizeOfHeaders:%08x\n", OptionalHeader->SizeOfHeaders);
printf("CheckSum:%08x\n", OptionalHeader->CheckSum);
printf("SizeOfStackReserve:%08x\n", OptionalHeader->SizeOfStackReserve);
printf("SizeOfStackCommit:%08x\n", OptionalHeader->SizeOfStackCommit);
printf("SizeOfHeapReserve:%08x\n", OptionalHeader->SizeOfHeapReserve);
printf("SizeOfHeapCommit:%08x\n", OptionalHeader->SizeOfHeapCommit);
printf("NumberOfRvaAndSizes:%08x\n", OptionalHeader->NumberOfRvaAndSizes);

return FileHeader->SizeOfOptionalHeader;
}

int Section_Header(LPSTR pFileBuffer, int NT_addr, int SizeOfOptionalHeader) {
PIMAGE_FILE_HEADER FileHeader = (PIMAGE_FILE_HEADER)(pFileBuffer + NT_addr + 4);
int NumberOfSections = FileHeader->NumberOfSections;
printf("----------SectionHeader----------\n");
printf("SectionNum:%x\n", NumberOfSections);
printf("---------------------------------\n");
PIMAGE_SECTION_HEADER SectionHeader = (PIMAGE_SECTION_HEADER)(pFileBuffer + NT_addr + 4 + sizeof(_IMAGE_FILE_HEADER) + SizeOfOptionalHeader);
for (int i = 0; i < NumberOfSections; i++) {
//Name最多只有8个字节,需要手动解析来判断结尾
char SectionName[9] = { 0 };
memcpy(SectionName, SectionHeader->Name, 8 * sizeof(char));
printf("* Name:%s\n", SectionName);
printf("* Misc:%08x\n", SectionHeader->Misc.VirtualSize);
printf("* VirtualAddress:%08x\n", SectionHeader->VirtualAddress);
printf("* SizeOfRawData:%08x\n", SectionHeader->SizeOfRawData);
printf("* PointerToRawData:%08x\n", SectionHeader->PointerToRawData);
printf("PointerToRelocations:%08x\n", SectionHeader->PointerToRelocations);
printf("PointerToLinenumbers:%08x\n", SectionHeader->PointerToLinenumbers);
printf("NumberOfRelocations:%04x\n", SectionHeader->NumberOfRelocations);
printf("NumberOfLinenumbers:%04x\n", SectionHeader->NumberOfLinenumbers);
printf("* Characteristics:%08x\n", SectionHeader->Characteristics);
printf("---------------------------------\n");
SectionHeader = SectionHeader + 1;
}

return 0;
}

int main(int argc, char* argv[]) {
FILE* tFile = fopen("C:\\Users\\veselwuxin\\Desktop\\wtest.exe", "rb");
if (tFile == NULL) {
printf("file open failed\n");
return 0;
}
int size = filesize(tFile);
char* FileBuffer = (char*)malloc(sizeof(char) * size);
if (!FileBuffer) {
printf("Alloc FileBuffer Failed\n");
return 0;
}
memset(FileBuffer, 0, sizeof(char) * size);

int freadsize = fread(FileBuffer, 1, sizeof(char) * size, tFile);
if (freadsize != sizeof(char) * size) {
printf("FileBuffer Write Failed\n");
return 0;
}

printf("FileBuffer address:%p\n", FileBuffer);

//_IMAGE_DOS_HEADER
//_IMAGE_NT_HEADERS
//_IMAGE_FILE_HEADER
//_IMAGE_OPTIONAL_HEADER
//_IMAGE_SECTION_HEADER

int NT_addr = DOS_Header(FileBuffer);
int SizeOfOptionalHeader = NT_Header(FileBuffer, NT_addr);
Section_Header(FileBuffer, NT_addr, SizeOfOptionalHeader);


free(FileBuffer);
FileBuffer = NULL;
tFile = NULL;

return 0;
}

程序运行部分截图