代码如下:
// clonefile.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#define _CRT_SECURE_NO_WARNINGS // 必须放在文件最顶部
#include <iostream>
#include <iomanip> // 包含 iomanip 头文件
/**
获取文件大小
*/
int getFileSize(const char* sourcePath) {
FILE* fp;
fp = fopen(sourcePath, "rb+");
if (fp == NULL) {
return 0;
}
// 移动文件指针到文件末尾
fseek(fp, 0, SEEK_END);
// 获取文件大小
int filesize = ftell(fp);
fclose(fp);
return filesize;
}
/**
读取文件到内存,返回文件在内存中的指针
*/
unsigned char* readFile(const char* sourcePath) {
FILE* fp;
fp = fopen(sourcePath, "rb+");
if (fp == NULL) {
return 0;
}
// 移动文件指针到文件末尾
fseek(fp, 0, SEEK_END);
// 获取文件大小
int filesize = ftell(fp);
unsigned char* newfile = (unsigned char*)malloc(filesize);
if (newfile == NULL) {
return NULL;
}
memset(newfile, 0, filesize);
/* 查找文件的开头 */
fseek(fp, 0, SEEK_SET);
/* 读取数据 */
fread(newfile, 1, filesize, fp);
fclose(fp);
return newfile;
}
/**
读取文件到内存,将读到的内存写入硬盘,要求完整复制.
1.打开文件
2.获取文件大小
3.开辟内存空间
4.写入到内存
4.将内存数据输出到新的文件
*/
void clone(const char* sourcePath, const char* targetPath) {
unsigned char* newfile = readFile(sourcePath);
int filesize = getFileSize(sourcePath);
FILE* fpw;
fpw = fopen(targetPath, "wb+");
if (fpw == NULL) {
return;
}
fwrite(newfile, 1, filesize, fpw);
fclose(fpw);
return;
}
/**
拷贝源指针位置的内容,size指定字节数,flag指定往前还是往后拷贝
往前拷贝可以把小端序换
*/
void* copyByte(void* source, int size, int flag) {
if (source == NULL) {
return NULL;
}
char* rtn = (char*)malloc(size);
if (rtn == NULL) {
return NULL;
}
if (flag == -1) {
source = (void*)((int)source + size - 1);
}
int i = 0;
while (i < size) {
rtn[i] = ((char*)source)[i * flag];
//target[i] = ((char*)source)[i * flag];
i++;
}
return rtn;
}
//没用
char* offset(char* p, int offset) {
return p + offset;
}
//各字段文件偏移和数据宽度
struct Item {
int address;
int size;
};
//节表
struct SectionTable {
Item Name;
Item VirtualSize;
Item VirtualAddress;
Item SizeOfRawData;
Item PointerToRawData;
Item PointerToRelocations;
Item PointerToLinenumbers;
Item NumberOfRelocations;
Item NumberOfLinenumbers;
Item Characteristics;
};
//放置每个字段的地址和宽度,
struct PE
{
const char* fileName;
Item e_magic;
Item e_lfanew;
Item PESigned;
int NT_BASE;
Item Machine;
Item NumberOfSections;
Item SizeOfOptionalHeader;
Item Characteristics;
Item SizeOfUninitializedData;
Item SizeOfInitializedData;
Item SizeOfCode;
Item MinorLinkerVersion;
Item MajorLinkerVersion;
Item Magic;
int OPTIONAL_HEADER_OFFSET;
Item AddressOfEntryPoint;
Item BaseOfCode;
Item ImageBase;
Item SectionAlignment;
Item FileAlignment;
Item MajorOperatingSystemVersion;
Item MinorOperatingSystemVersion;
Item SizeOfImage;
Item SizeOfHeaders;
Item CheckSum;
Item NumberOfRvaAndSizes;
Item* dataDir;
int section_offset;
SectionTable* sectionTable;
};
/**
* targetExe:目标文件地址
解析PE文件
返回结构体,其中每一个字段放的是该字段的文件偏移和宽度
*/
PE resolvePE(const char* targetExe) {
//clone("restart.exe","restartclone.exe");
struct PE pe = *(PE*)malloc(sizeof(PE));
pe.fileName = targetExe;
bool isPE32add = false;
int size = 4;
unsigned char* file = readFile(targetExe);
short f1 = *((short*)file);
short* e_magic = (short*)copyByte((void*)file, 2, -1);
pe.e_magic.address = 0;
pe.e_magic.size = 2;
int* e_lfanew = (int*)copyByte((void*)((int)file + 0x3c), 4, 1);
pe.e_lfanew.address = 0x3c;
pe.e_lfanew.size = 4;
int* PESigned = (int*)copyByte((void*)((int)file + (int)*e_lfanew), 4, 1);
pe.PESigned.address = (int)*e_lfanew;
pe.PESigned.size = 4;
int NT_BASE = (int)*e_lfanew + 0x04;
pe.NT_BASE = (int)*e_lfanew + 0x04;
short* Machine = (short*)copyByte((void*)((int)file + NT_BASE + 0x00), 2, 1);
pe.Machine.address = NT_BASE;
pe.Machine.size = 2;
short* NumberOfSections = (short*)copyByte((void*)((int)file + NT_BASE + 0x02), 2, 1);
pe.NumberOfSections.address = NT_BASE + 0x02;
pe.NumberOfSections.size = 2;
short* SizeOfOptionalHeader = (short*)copyByte((void*)((int)file + NT_BASE + 0x0F), 2, 1);
pe.SizeOfOptionalHeader.address = NT_BASE + 0x0F;
pe.SizeOfOptionalHeader.size = 2;
short* Characteristics = (short*)copyByte((void*)((int)file + NT_BASE + 0x12), 2, 1);
pe.Characteristics.address = NT_BASE + 0x12;
pe.Characteristics.size = 2;
int OPTIONAL_HEADER_OFFSET = NT_BASE + 0x14;
pe.OPTIONAL_HEADER_OFFSET = OPTIONAL_HEADER_OFFSET;
short* OPTIONAL_HEADER_Magic = (short*)copyByte((void*)((int)file + OPTIONAL_HEADER_OFFSET), 2, 1);
pe.Magic.address = OPTIONAL_HEADER_OFFSET;
pe.Magic.size = 2;
if (*OPTIONAL_HEADER_Magic == 0x020b) {
isPE32add = true;
}
unsigned char* MajorLinkerVersion = (unsigned char*)copyByte((void*)((int)file + OPTIONAL_HEADER_OFFSET + 0x02), 1, 1);
pe.MajorLinkerVersion.address = OPTIONAL_HEADER_OFFSET + 0x02;
pe.MajorLinkerVersion.size = 1;
unsigned char* MinorLinkerVersion = (unsigned char*)copyByte((void*)((int)file + OPTIONAL_HEADER_OFFSET + 0x03), 1, 1);
pe.MinorLinkerVersion.address = OPTIONAL_HEADER_OFFSET + 0x03;
pe.MinorLinkerVersion.size = 1;
int* OPTIONAL_HEADER_SizeOfCode = (int*)copyByte((void*)((int)file + OPTIONAL_HEADER_OFFSET + 0x04), 4, 1);
pe.SizeOfCode.address = OPTIONAL_HEADER_OFFSET + 0x04;
pe.SizeOfCode.size = 4;
int* OP_SizeOfInitializedData = (int*)copyByte((void*)((int)file + OPTIONAL_HEADER_OFFSET + 0x08), 4, 1);
pe.SizeOfInitializedData.address = OPTIONAL_HEADER_OFFSET + 0x08;
pe.SizeOfInitializedData.size = 4;
int* OP_SizeOfUninitializedData = (int*)copyByte((void*)((int)file + OPTIONAL_HEADER_OFFSET + 0x0C), 4, 1);
pe.SizeOfUninitializedData.address = OPTIONAL_HEADER_OFFSET + 0x0c;
pe.SizeOfUninitializedData.size = 4;
//AddressOfEntryPoint
int* OP_AddressOfEntryPoint = (int*)copyByte((void*)((int)file + OPTIONAL_HEADER_OFFSET + 0x10), 4, 1);
pe.AddressOfEntryPoint.address = OPTIONAL_HEADER_OFFSET + 0x10;
pe.AddressOfEntryPoint.size = 4;
//BaseOfCode
int* OP_BaseOfCode = (int*)copyByte((void*)((int)file + OPTIONAL_HEADER_OFFSET + 0x14), 4, 1);
pe.BaseOfCode.address = OPTIONAL_HEADER_OFFSET + 0x14;
pe.BaseOfCode.size = 4;
if (!isPE32add) {
//BaseOfData
int* OP_BaseOfData = (int*)copyByte((void*)((int)file + OPTIONAL_HEADER_OFFSET + 0x18), 4, 1);
}
int OP_Win_offset32 = OPTIONAL_HEADER_OFFSET + 0x1c;
int OP_Win_offset64 = OPTIONAL_HEADER_OFFSET + 0x18;
int* ImageBase = (int*)copyByte((void*)((int)file + OPTIONAL_HEADER_OFFSET + 28), 4 + isPE32add * 4, 1);
pe.ImageBase.address = OPTIONAL_HEADER_OFFSET + 28;
pe.ImageBase.size = 4;
int* SectionAlignment = (int*)copyByte((void*)((int)file + OPTIONAL_HEADER_OFFSET + 32), 4, 1);
pe.SectionAlignment.address = OPTIONAL_HEADER_OFFSET + 32;
pe.SectionAlignment.size = 4;
int* FileAlignment = (int*)copyByte((void*)((int)file + OPTIONAL_HEADER_OFFSET + 36), 4, 1);
pe.FileAlignment.address = OPTIONAL_HEADER_OFFSET + 36;
pe.FileAlignment.size = 4;
short* MajorOperatingSystemVersion = (short*)copyByte((void*)((int)file + OPTIONAL_HEADER_OFFSET + 40), 2, 1);
pe.MajorOperatingSystemVersion.address = OPTIONAL_HEADER_OFFSET + 40;
pe.MajorOperatingSystemVersion.size = 2;
short* MinorOperatingSystemVersion = (short*)copyByte((void*)((int)file + OPTIONAL_HEADER_OFFSET + 42), 2, 1);
pe.MinorOperatingSystemVersion.address = OPTIONAL_HEADER_OFFSET + 42;
pe.MinorOperatingSystemVersion.size = 2;
int* SizeOfImage = (int*)copyByte((void*)((int)file + OPTIONAL_HEADER_OFFSET + 56), 4, 1);
pe.SizeOfImage.address = OPTIONAL_HEADER_OFFSET + 56;
pe.SizeOfImage.size = 4;
int* SizeOfHeaders = (int*)copyByte((void*)((int)file + OPTIONAL_HEADER_OFFSET + 60), 4, 1);
pe.SizeOfHeaders.address = OPTIONAL_HEADER_OFFSET + 60;
pe.SizeOfHeaders.size = 4;
int* CheckSum = (int*)copyByte((void*)((int)file + OPTIONAL_HEADER_OFFSET + 64), 4, 1);
pe.CheckSum.address = OPTIONAL_HEADER_OFFSET + 64;
pe.CheckSum.size = 4;
int* NumberOfRvaAndSizes = (int*)copyByte((void*)((int)file + OPTIONAL_HEADER_OFFSET + 92), 4, 1);
pe.NumberOfRvaAndSizes.address = OPTIONAL_HEADER_OFFSET + 92;
pe.NumberOfRvaAndSizes.size = 4;
//数据目录
pe.dataDir = (Item*)malloc(*NumberOfRvaAndSizes * sizeof(Item));
int j = 0;
while (j < *NumberOfRvaAndSizes) {
pe.dataDir[j].address = OPTIONAL_HEADER_OFFSET + 96 + j * 8;
pe.dataDir[j].size = 8;
j++;
}
int section_offset = *NumberOfRvaAndSizes * 8 + (OPTIONAL_HEADER_OFFSET + 96);
pe.section_offset = section_offset;
pe.sectionTable = (SectionTable*)malloc(sizeof(SectionTable) * (*NumberOfSections));
int i = 0;
while (i < *NumberOfSections) {
pe.sectionTable[i].Name.address = section_offset + 40 * i;
pe.sectionTable[i].Name.size = 8;
pe.sectionTable[i].VirtualSize.address = section_offset + 8 + 40 * i;
pe.sectionTable[i].VirtualSize.size = 4;
pe.sectionTable[i].VirtualAddress.address = section_offset + 12 + 40 * i;
pe.sectionTable[i].VirtualAddress.size = 4;
pe.sectionTable[i].SizeOfRawData.address = section_offset + 16 + 40 * i;
pe.sectionTable[i].SizeOfRawData.size = 4;
pe.sectionTable[i].PointerToRawData.address = section_offset + 20 + 40 * i;
pe.sectionTable[i].PointerToRawData.size = 4;
pe.sectionTable[i].PointerToRelocations.address = section_offset + 24 + 40 * i;
pe.sectionTable[i].PointerToRelocations.size = 4;
pe.sectionTable[i].PointerToLinenumbers.address = section_offset + 28 + 40 * i;
pe.sectionTable[i].PointerToLinenumbers.size = 4;
pe.sectionTable[i].NumberOfRelocations.address = section_offset + 32 + 40 * i;
pe.sectionTable[i].NumberOfRelocations.size = 2;
pe.sectionTable[i].NumberOfLinenumbers.address = section_offset + 34 + 40 * i;
pe.sectionTable[i].NumberOfLinenumbers.size = 2;
pe.sectionTable[i].Characteristics.address = section_offset + 36 + 40 * i;
pe.sectionTable[i].Characteristics.size = 4;
i++;
}
return pe;
}
int main()
{
PE pe = resolvePE("restart.exe");
unsigned char* file = readFile("restart.exe");
int SizeOfHeaders = *(int*)((int)file + pe.SizeOfHeaders.address);
std::cout << std::hex << std::setw(8) << std::setfill('0');
std::cout << "SizeOfHeaders:" << SizeOfHeaders << std::endl;
system("pause");
}

浙公网安备 33010602011771号