本次作业以notepad进行演示,如下是其在硬盘上的内存
1.手动解析节表
由标准pe头可知,一共由7个节也就是7个节表,可选pe头的大小是0X00F0,即240字节大小
根据上述我们所获取的信息,找到节表的首地址为0x01F8
.text
#define IMAGE_SIZEOF_SHORT_NAME 8 //宏定义
typedef struct _IMAGE_SECTION_HEADER{
BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; 0X000000747865742E
union{
DWORD PhysicalAddress;
DWORD VirtualSize;
}Misc; 0X00027D02
DWORD VirtualAddress; 0X00001000
DWORD SizeOfRawData; 0X00028000
DWORD PointerToRawData; 0X00001000
DWORD PointerToRelocations; 0X00000000
DWORD PointerToLinenumbers;0X00000000
WORD NumberOfRelocations; 0X0000
WORD NumberOfLinenumbers;0X0000
DWORD Characteristics; 0X60000020
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
.rdata
#define IMAGE_SIZEOF_SHORT_NAME 8
typedef struct _IMAGE_SECTION_HEADER{
BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; 0X000061746164722E
union{
DWORD PhysicalAddress;
DWORD VirtualSize;
}Misc; 0X0000A608
DWORD VirtualAddress; 0X00029000
DWORD SizeOfRawData; 0X0000B000
DWORD PointerToRawData; 0X00029000
DWORD PointerToRelocations; 0X00000000
DWORD PointerToLinenumbers; 0X00000000
WORD NumberOfRelocations; 0X0000
WORD NumberOfLinenumbers; 0X0000
DWORD Characteristics; 0X40000040
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
.data
#define IMAGE_SIZEOF_SHORT_NAME 8
typedef struct _IMAGE_SECTION_HEADER{
BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; 0X000000617464642E
union{
DWORD PhysicalAddress;
DWORD VirtualSize;
}Misc; 000026C0
DWORD VirtualAddress; 0X00034000
DWORD SizeOfRawData; 0X00001000
DWORD PointerToRawData; 0X00034000
DWORD PointerToRelocations; 0X00000000
DWORD PointerToLinenumbers; 0X00000000
WORD NumberOfRelocations; 0X0000
WORD NumberOfLinenumbers;0X0000
DWORD Characteristics; 0XC0000040
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
由于该文件所有节过多,此处不再多演示,具体操作都是一样的。
2.控制台输出解析所有节表
#include<stdio.h>
#include<Windows.h>
char* ReadPEFile(const char* lpszFile)
{
FILE* pFile = NULL;
pFile = fopen(lpszFile, "rb");
DWORD fileSize = 0;
char* pFileBuffer = NULL;
if (!pFile)
{
printf("无法打开EXE文件");
return NULL;
}
fseek(pFile, 0, SEEK_END);
fileSize = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
pFileBuffer = (char*)malloc(sizeof(char)*fileSize);
if (!pFileBuffer)
{
printf("分配空间失败");
fclose(pFile);
return NULL;
}
size_t i = fread(pFileBuffer, fileSize, 1, pFile);
if (!i)
{
printf("读取数据失败!");
free(pFileBuffer);
fclose(pFile);
return NULL;
}
fclose(pFile);
return pFileBuffer;
}
BOOL PrintNTHeaders(const char* lpszFile)
{
IMAGE_DOS_HEADER *pDosHeader;
IMAGE_NT_HEADERS *pNTHeader;
IMAGE_FILE_HEADER *pPEHeader;
IMAGE_SECTION_HEADER *pSecHeader;
int i = 0;
char* pFileBuffer = ReadPEFile(lpszFile);
pDosHeader = (IMAGE_DOS_HEADER*)pFileBuffer;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
printf("不是有效MZ标志,打印结束\n");
free(pFileBuffer);
pFileBuffer = NULL;
return FALSE;
}
pNTHeader = (IMAGE_NT_HEADERS*)((char*)pFileBuffer + pDosHeader->e_lfanew);
if (pNTHeader->Signature != IMAGE_NT_SIGNATURE)
{
printf("不是有效的PE标志,打印结束\n");
free(pFileBuffer);
pFileBuffer = NULL;
return FALSE;
}
pPEHeader = (IMAGE_FILE_HEADER*)((char*)pNTHeader + 4);
printf("NumberOfSections(节表的数量):%04X\n", pPEHeader->NumberOfSections);
printf("SizeOfOptionalHeader(可选pe头的大小):%04X\n", pPEHeader->SizeOfOptionalHeader);
printf("\n");
printf("节表信息解析开始");
pSecHeader = (IMAGE_SECTION_HEADER*)((char*)pPEHeader + sizeof(_IMAGE_FILE_HEADER) + pPEHeader->SizeOfOptionalHeader);
for (int i = 0; i < pPEHeader->NumberOfSections; i++)
{
char SecName[9] = "\0";
printf("这是第%d个节表\n", i+1);
char* Name = (char*)pSecHeader->Name;
strcpy(SecName, Name);
printf("Name:%s\n", SecName);
printf("VirtualSize:%08X\n", pSecHeader->Misc.VirtualSize);
printf("VirtualAddress:%08X\n", pSecHeader->VirtualAddress);
printf("SizeOfRawData:%08X\n", pSecHeader->SizeOfRawData);
printf("PointerToRawData:%08X\n", pSecHeader->PointerToRawData);
printf("Characteristics:%08X\n", pSecHeader->Characteristics);
printf("\n");
pSecHeader++;
}
free(pFileBuffer);
pFileBuffer = NULL;
return TRUE;
}
int main(int argc, char* argv[])
{
const char* lpszFile = "C:\\Windows\\notepad.exe";
PrintNTHeaders(lpszFile);
return 0;
}