0%

PE解析器控制台

实现了一些基本的信息

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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
#include<stdio.h>
#include<windows.h>

//计算数据目录表起始位置到文件头的偏移
DWORD RvaToOffset(DWORD dwRva, char* buffer);
//解析导入表函数
void ImportTable(char* buffer);
//解析导出表函数
void ExportTable(char* buffer);
//解析重定位表函数
void RelocTable(char* buffer);
//解析TLS表的函数
void TLSTable(char* buffer);

int main()
{
int m;
FILE* pFile = NULL;
char* buffer;
int nFileLength = 0;
char name[100];
printf("写入文件名:\n");
gets(name);
fopen_s(&pFile,name, "rb");
fseek(pFile, 0, SEEK_END);
nFileLength = ftell(pFile);
rewind(pFile);
int imageLength = nFileLength * sizeof(char) + 1;
buffer = (char*)malloc(imageLength);
memset(buffer, 0, nFileLength * sizeof(char) + 1);
fread(buffer, 1, imageLength, pFile);

//打印DOS-Header
PIMAGE_DOS_HEADER ReadDosHeader;
ReadDosHeader = (PIMAGE_DOS_HEADER)buffer;
printf("MS-DOS Info:\n");
printf("MZ标志位:%X\n", ReadDosHeader->e_magic);
printf("PE头偏移量:%X\n", ReadDosHeader->e_lfanew);
printf("----------------------------------------------------\n");
//PE-Header
printf("NT Header Info:\n");
PIMAGE_NT_HEADERS ReadNTHeaders;
ReadNTHeaders = (PIMAGE_NT_HEADERS)(buffer + ReadDosHeader->e_lfanew);
printf("Signature:%X\n", ReadNTHeaders->Signature);
printf("\n");
printf("Machine:%X\n", ReadNTHeaders->FileHeader.Machine);
printf("NumberOfSections:%X\n", ReadNTHeaders->FileHeader.NumberOfSections);
printf("SizeOfOptionalHeader:%X\n", ReadNTHeaders->FileHeader.SizeOfOptionalHeader);
printf("Characteristics:%X\n", ReadNTHeaders->FileHeader.Characteristics);
printf("\n");
printf("Magic:%X\n", ReadNTHeaders->OptionalHeader.Magic);
printf("AddressOfEntryPoint:%X\n", ReadNTHeaders->OptionalHeader.AddressOfEntryPoint);
printf("ImageBase:%X\n", ReadNTHeaders->OptionalHeader.ImageBase);
printf("SectionAlignment:%X\n", ReadNTHeaders->OptionalHeader.SectionAlignment);
printf("FileAlignment:%X\n", ReadNTHeaders->OptionalHeader.FileAlignment);
printf("SizeOfImage:%X\n", ReadNTHeaders->OptionalHeader.SizeOfImage);
printf("SizeOfHeader:%X\n", ReadNTHeaders->OptionalHeader.SizeOfHeaders);
printf("Subsystem:%X\n", ReadNTHeaders->OptionalHeader.Subsystem);
printf("NumberOfRvaAndSizes:%X\n", ReadNTHeaders->OptionalHeader.NumberOfRvaAndSizes);
printf("Export表的地址:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[0].VirtualAddress);
printf("Export的Size:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[0].Size);
printf("Import的地址:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[1].VirtualAddress);
printf("Import的Size:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[1].Size);
printf("Resource的地址:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[2].VirtualAddress);
printf("Resource的Size:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[2].Size);
printf("Reloc表的地址:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[5].VirtualAddress);
printf("Reloc的Size:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[5].Size);
printf("TLS表的地址:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[9].VirtualAddress);
printf("TLS的Size:%X\n", ReadNTHeaders->OptionalHeader.DataDirectory[9].Size);
printf("----------------------------------------------------\n");
printf("Section Header Info:\n");
PIMAGE_SECTION_HEADER ReadSectionHeader = IMAGE_FIRST_SECTION(ReadNTHeaders);
PIMAGE_FILE_HEADER pFileHeader = &ReadNTHeaders->FileHeader;
for (int i = 0; i < pFileHeader->NumberOfSections; i++)
{
printf("Name(区段名称):%s\n", ReadSectionHeader[i].Name);
printf("VOffset(起始的内存地址):%08X\n", ReadSectionHeader[i].VirtualAddress);
printf("VSize(区段大小):%08X\n", ReadSectionHeader[i].SizeOfRawData);
printf("ROffset(文件偏移):%08X\n", ReadSectionHeader[i].PointerToRawData);
printf("RSize(文件中区段大小):%08X\n", ReadSectionHeader[i].Misc.VirtualSize);
printf("Characteristics(区段属性):%08X\n", ReadSectionHeader[i].Characteristics);
printf("-----------------------------------------------------\n");
}
printf("=====================================================================\n");
printf("查看导入表输入1,查看导出表输入2,查看重定位表输入3,查看TLs表输入4.退出请按5:\n");
while(1)
{
scanf_s("%d", &m);
if (m == 1)
ImportTable(buffer);
else if (m == 2)
ExportTable(buffer);
else if (m == 3)
RelocTable(buffer);
else if(m == 4)
TLSTable(buffer);
else
{
break;
}
}
system("pause");
free(buffer);
return 0;
}

//dwRva是某个数据目录表的VirtualAddress
//buffer是读取到的pe文件缓冲区
DWORD RvaToOffset(DWORD dwRva, char* buffer)
{
//Dos头
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)buffer;
//PE头
PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + buffer);
//区段表
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNt);
//判断是否落在头部当中
if (dwRva < pSection[0].VirtualAddress)
{
return dwRva;
}
for (int i = 0; i < pNt->FileHeader.NumberOfSections; i++)
{
if (dwRva >= pSection[i].VirtualAddress && dwRva <= pSection[i].VirtualAddress + pSection[i].Misc.VirtualSize)
{
//dwRva-pSection[i].VirtualAddress是数据目录表到区段起始地址的偏移(OFFSET)
// pSection[i].PointerToRawData区段到文件头的偏移(OFFSET)
return dwRva - pSection[i].VirtualAddress + pSection[i].PointerToRawData;
}
}
}
void ImportTable(char* buffer)
{
//Dos
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)buffer;
//PE头
PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + buffer);
//定位导入表
PIMAGE_DATA_DIRECTORY pImportDir = (PIMAGE_DATA_DIRECTORY)(pNt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_IMPORT);
//填充结构
PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)(RvaToOffset(pImportDir->VirtualAddress, buffer) + buffer);
while (pImport->Name != NULL)
{
char* szDllName = (char*)(RvaToOffset(pImport->Name, buffer) + buffer);
printf("Dll名称:%s\n", szDllName);
printf("日期时间标志:%08X\n", pImport->TimeDateStamp);
printf("ForwarderChain:%08X\n", pImport->ForwarderChain);
printf("名称OFFSET(库名称字符串地址):%08X\n", pImport->Name);
printf("FirstThunk(IAT的地址):%08X\n", pImport->FirstThunk);
printf("OriginalFirstThunk(INT的地址):%08X\n", pImport->OriginalFirstThunk);
PIMAGE_THUNK_DATA pIat = (PIMAGE_THUNK_DATA)(RvaToOffset(pImport->OriginalFirstThunk, buffer) + buffer);
DWORD index = 0;
DWORD ImprotOffset = 0;
printf("\n");
while (pIat->u1.Ordinal != 0)
{
printf("ThunkRva:%08X\n", pImport->OriginalFirstThunk + index);
ImprotOffset = RvaToOffset(pImport->OriginalFirstThunk, buffer);
printf("ThunkOffset:%08X\n", ImprotOffset + index);
index += 4;
if ((pIat->u1.Ordinal & 0x80000000) != 1)
{
PIMAGE_IMPORT_BY_NAME pName = (PIMAGE_IMPORT_BY_NAME)(RvaToOffset(pIat->u1.AddressOfData,buffer)+buffer);
printf("API名称:%s ", pName->Name);
printf("Hint:%04X ", pName->Hint);
printf("ThunkValue:%08X\n", pIat->u1.Function);
}
printf("------------------------------------\n");
pIat++;
}
printf("-----------------------------------------------------\n");
pImport++;
}
}

void ExportTable(char* buffer)
{
//Dos头
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)buffer;
//PE
PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + buffer);
//定位数据目录表中的导出表
PIMAGE_DATA_DIRECTORY pExportDir = pNt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_EXPORT;
//填充导出表结构
PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)(RvaToOffset(pExportDir->VirtualAddress, buffer) + buffer);
char* szName = (char*)(RvaToOffset(pExport->Name, buffer) + buffer);
if (pExport->AddressOfFunctions == 0)
{
printf("当前没有导出表!\n");
return;
}
printf("导出表OFFSET:%08X\n", RvaToOffset(pExportDir->VirtualAddress, buffer));
printf("特征值:%08X\n", pExport->Characteristics);
printf("基:%08X", pExport->Base);
printf("名称OFFSET:%08X", pExport->Name);
printf("名称:%s\n", szName);
printf("函数数量:%08X\n", pExport->NumberOfFunctions);
printf("函数名数量:%08X\n", pExport->NumberOfNames);
printf("函数地址:%08X\n", pExport->AddressOfFunctions);
printf("函数名地址:%08X\n", pExport->AddressOfNames);
printf("函数名称序号地址:%08X\n", pExport->AddressOfNameOrdinals);
printf("\n");
//获取函数数量
DWORD dwNumOfFUN = pExport->NumberOfFunctions;
//函数名数量
DWORD dwNumOfNames = pExport->NumberOfNames;
//基
DWORD dwBase = pExport->Base;
//导出地址表
PDWORD pEat32 = (PDWORD)(RvaToOffset(pExport->AddressOfFunctions, buffer) + buffer);
//导出名称表
PDWORD pEnt32 = (PDWORD)(RvaToOffset(pExport->AddressOfNames, buffer) + buffer);
//导出序号表
PWORD pId = (PWORD)(RvaToOffset(pExport->AddressOfNameOrdinals, buffer) + buffer);
for (int i = 0; i < dwNumOfFUN; i++)
{
if (pEat32[i] == 0)
continue;
DWORD Id = 0;
for (; Id < dwNumOfNames; Id++)
{
if (pId[Id] == i)
break;
}
if (Id == dwNumOfNames)
{
printf("Id:%X Address:0x%08X Name[NuLL]\n", i + dwBase, pEat32[i]);
}
else
{
char* szFunName = (char*)(RvaToOffset(pEnt32[Id], buffer) + buffer);
printf("Id:%X Address:0x%08X Name[%s]\n", i + dwBase, pEat32[i],szFunName);
}
printf("-------------------------------------\n");
}
printf("----------------------------------------------------------\n");
}

void RelocTable(char* buffer)
{
typedef struct _TYPE {
WORD Offset : 12;
WORD Type : 4;
}TYPE, *PTYPE;
//Dos
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)buffer;
//PE
PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + buffer);
//定位重定位表
PIMAGE_DATA_DIRECTORY pRelocDir = (pNt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_BASERELOC);
//填充重定位表的结构
PIMAGE_BASE_RELOCATION pReloc = (PIMAGE_BASE_RELOCATION)(RvaToOffset(pRelocDir->VirtualAddress, buffer) + buffer);
//定位区段
PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNt);
while (pReloc->SizeOfBlock != 0)
{
//找到本0x1000个字节的起始位置
DWORD dwCount = (pReloc->SizeOfBlock - 8) / 2;
DWORD dwRva = pReloc->VirtualAddress;
PTYPE pRelocArr = (PTYPE)(pReloc + 1);
printf("区段;%s\n", pSection->Name);
printf("RVA:%08X\n", dwRva);
printf("项目:%X H /%d D\n", pReloc->SizeOfBlock, pReloc->SizeOfBlock);
//找到下一个0x1000字节的结构体
pReloc = (PIMAGE_BASE_RELOCATION)((char*)pReloc + pReloc->SizeOfBlock);
for (int i = 0; i < dwCount; i++)
{
PDWORD pData = (PDWORD)(RvaToOffset(pRelocArr[i].Offset + dwRva, buffer) + buffer);
DWORD pDataOffset = RvaToOffset(pRelocArr[i].Offset + dwRva, buffer);
printf("RVA:%08X ", pRelocArr[i].Offset + dwRva);
printf("区段:%08X ", *pData);
printf("偏移:%08X\n ", pDataOffset);
printf("------------------------------------\n");
}
printf("\n");
}
printf("-------------------------------------------------------------------\n");
}

void TLSTable(char* buffer)
{
//Dos
PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)buffer;
//PE
PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + buffer);
//定位数据目录表中的TLS表
PIMAGE_DATA_DIRECTORY pTLSDir = (pNt->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_TLS);
//填充TLS结构
PIMAGE_TLS_DIRECTORY pTLS = (PIMAGE_TLS_DIRECTORY)(RvaToOffset(pTLSDir->VirtualAddress, buffer) + buffer);
printf("数据块开始VA:%08X\n",pTLS->StartAddressOfRawData);
printf("数据块结束VA:%08X\n",pTLS->EndAddressOfRawData);
printf("索引变量VA:%08X\n",pTLS->AddressOfIndex);
printf("回调表VA:%08X\n",pTLS->AddressOfCallBacks);
printf("填零大小VA:%08X\n",pTLS->SizeOfZeroFill);
printf("特征值VA:%08X\n",pTLS->Characteristics);
printf("------------------------------\n");
}