记录文件结构试验
前言:使用的模拟程序是notepad.exe,主要记录其中的思路和遇到其中的困难。
实验目的:模拟内存加载PE文件的过程,将每个区段模拟加载到内存之中。
根据文件结构中头表中的信息,读取并sekk指针到Segment头。然后循环遍历Segment头将内容加载到Virtual Address中,主要目的是为了熟悉PE头的结构,同时也练习自己的代码能力。
贴出来最后的代码如下,只支持部分PE文件的模拟加载。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define QWORD unsigned long long
#define DWORD unsigned int
#define WORD unsigned short
void show_memory(unsigned char* s, int len) {
printf("Addres: 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF");
for (int i = 0; i < (len / 0x10) + 1; ++i) {
printf("\n%06X: ", i * 0x10);
for (int j = 0; j < 0x10; ++j) {
printf("%02X", s[i * 0x10 + j]);
if (j == 3 || j == 7 || j == 0xb)
putchar('|');
else
putchar(' ');
}
putchar(' ');
putchar(' ');
putchar(' ');
putchar(' ');
for (int j = 0; j < 0x10; ++j) {
if (s[i * 0x10 + j] >= 'A' && s[i * 0x10 + j] <= 'z')
printf("%c", s[i * 0x10 + j]);
else
putchar('.');
}
}
}
int main() {
const char* filename = "C:\\Users\\LENOVO\\Desktop\\Practice\\316Buffer\\notepad_xp.exe";
FILE* fp = fopen(filename, "rb");
unsigned char* VirtualBuffer;
DWORD SizeOfImage;
DWORD AddressOfNewEXEHeader;
char SectionHeaderName[9] = { 0 };
DWORD Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD Characteristics;
WORD NumberOfSection;
WORD SizeOfOptionalHeader;
WORD SizeOfHeaders;
if (fp == NULL) {
printf("Failed to open the file");
exit(1);
}
fseek(fp, 0x3C, SEEK_SET);
fread(&AddressOfNewEXEHeader, 4, 1, fp);
fseek(fp, AddressOfNewEXEHeader + 0x6, SEEK_SET); // seek for new NT header and NumberOfSection
fread(&NumberOfSection, 2, 1, fp); // get NumberOfSection
fseek(fp, 0xC, SEEK_CUR); // seek for opt size
fread(&SizeOfOptionalHeader, 2, 1, fp);
fseek(fp, AddressOfNewEXEHeader + 0x50, SEEK_SET);
fread(&SizeOfImage, 4, 1, fp); // get img size
fread(&SizeOfHeaders, 2, 1, fp); // get headers size
VirtualBuffer = (unsigned char*)malloc(SizeOfImage); // //get vadr
if (VirtualBuffer == NULL) {
printf("Failed to malloc the size %X", SizeOfImage);
exit(1);
}
memset(VirtualBuffer, 0, SizeOfImage);
fseek(fp, 0, SEEK_SET);
fread(&VirtualBuffer[i], 0x400, 1, fp);
for (int i = 0; i < NumberOfSection; ++i) {
fseek(fp, AddressOfNewEXEHeader + 0x18 + SizeOfOptionalHeader + i * 0x28, SEEK_SET);
fread(&SectionHeaderName, 1, 8, fp);
printf("段名称: %s\n", SectionHeaderName);
fread(&Misc, 4, 1, fp);
printf("Misc(实际大小): %X\n", Misc);
fread(&VirtualAddress, 4, 1, fp);
printf("虚拟地址: %X\n", VirtualAddress);
fread(&SizeOfRawData, 4, 1, fp);
printf("区段大小: %X\n", SizeOfRawData);
fread(&PointerToRawData, 4, 1, fp);
printf("文件中偏移: %X\n", PointerToRawData);
fseek(fp, 0xC, SEEK_CUR);
fread(&Characteristics, 4, 1, fp);
printf("属性值: %8X\n\n", Characteristics);
fseek(fp, PointerToRawData, SEEK_SET);
fread(&VirtualBuffer[VirtualAddress], Misc, 1, fp);
}
show_memory(VirtualBuffer, 0x1000);
free(VirtualBuffer);
}
中途遇到了一个问题:是文件偏移为 75h 的 0d 0d 0a 读出来只有 0d 0a,莫名其妙少了一个 0d ,但是从此往后的内容又都是正确的,本人为此甚至尝试了多个编译器,均失败告终。最后查找到原因是因为打开方式为"r",fread检测到 0d 0a 时认为这是文件结束标识,于是结束了读取内容。导致此处丢失了一个 0d 。在网络上找到原因后,将"r"改为"rb",最后成功读取了文件内容。
标签:文件,putchar,0x10,0d,PE,加载 From: https://www.cnblogs.com/F145H/p/17688351.html