建议大家认认真真写一遍,收获蛮大的,是可以加深对pe结构的理解,尤其是对指针的使用,和对win32的一些宏的定义的理解和使用。
cpp
#include <windows.h>
#include <iostream>
#include <string>
using namespace std;
PIMAGE_DOS_HEADER my_dos=nullptr;//dos头结构
PIMAGE_FILE_HEADER my_file=nullptr;//file结构
PIMAGE_OPTIONAL_HEADER32 my_optional=nullptr;//可选PE头结构
PIMAGE_SECTION_HEADER* my_section=nullptr;//节表结构
void* Before_Stretch_Data = nullptr; //指向拉伸前的内容
void* Stretch_Data = nullptr; //指向拉伸后的内容
void* Shrink_data = nullptr; //指向缩小PE结构的内容
//获取
void* Readfile(char* filename)
{
unsigned int size;
FILE* datafile;
void* data;
//打开文件
if (fopen_s(&datafile, filename, "rb") != 0)
{
cout << "打开文件失败" << endl;
return nullptr;
}
else
{
//获取文件的大小
cout << "打开文件成功!" << endl;
fseek(datafile, 0, SEEK_END);
size = ftell(datafile);
fseek(datafile, 0, SEEK_SET);
if (size == -1L)
{
cout << "文件大小判断失败!" << endl;
return nullptr;
}
//申请内存空间把文件内容保存下来
data = (void*)malloc(size * sizeof(char));
if (fread_s(data, size, sizeof(char), size, datafile) == 0)
{
cout << "写入数据失败!" << endl;
return nullptr;
}
cout << "写入数据成功,成功获取Data!" << endl;
return data;
}
}
//分析PE结构
void Analyze_PE(char*& Data, PIMAGE_DOS_HEADER& my_dos, PIMAGE_FILE_HEADER& my_file, PIMAGE_OPTIONAL_HEADER32& my_optional, PIMAGE_SECTION_HEADER*& my_section)
{
DWORD* Temp_ptr = (DWORD*)Data;
my_dos = (PIMAGE_DOS_HEADER)Temp_ptr;
Temp_ptr = (DWORD*)((char*)&Data[my_dos->e_lfanew]);
Temp_ptr++;
my_file = (PIMAGE_FILE_HEADER)Temp_ptr;
Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x14);
my_optional = (PIMAGE_OPTIONAL_HEADER)Temp_ptr;
Temp_ptr = (DWORD*)((char*)my_optional+my_file->SizeOfOptionalHeader);
my_section = (PIMAGE_SECTION_HEADER*)malloc(sizeof(IMAGE_SECTION_HEADER) * my_file->NumberOfSections);
for (int i = 0; i < my_file->NumberOfSections; i++)
{
my_section[i] = (PIMAGE_SECTION_HEADER)Temp_ptr;
Temp_ptr = (DWORD*)((char*)Temp_ptr + 0x28);
}
}
//复制节表的内容
//void Copy_Section_Content()
//{
// void* temp_ptr=nullptr;
// for (int i = 0; i < my_file->NumberOfSections; i++)
// {
// temp_ptr = (void*)((char*)Before_Stretch_Data + my_section[i]->PointerToRawData);
//
// }
//}
//拉伸PE结构 注意看PIMAGE_XXX_HEADER的定义,它们本就是指向结构体的指针
void Stretch_PE()
{
unsigned Memory_Size = 0;
Memory_Size = my_optional->SizeOfImage;
Stretch_Data = (void*)malloc(sizeof(char) * Memory_Size);
memset(Stretch_Data, 0, Memory_Size);
void* temp_before_stretch_data_ptr = Before_Stretch_Data;
int size_of_dos = 0x40;
int size_of_junk = 0x40;
int size_of_file = 0x18;
unsigned Size_Of_Optional = my_file->SizeOfOptionalHeader;
unsigned Size_Of_Section = 0x28;
unsigned Size_Of_Header = size_of_dos + size_of_file + size_of_junk + Size_Of_Optional + Size_Of_Section * my_file->NumberOfSections;//还未对齐
memcpy_s(Stretch_Data, Memory_Size, Before_Stretch_Data, Size_Of_Header);
void* temp_stretch_data = Stretch_Data;
//现在计算head头对齐后的大小
int Size = Size_Of_Header % my_optional->SectionAlignment;
Size_Of_Header = my_optional->SectionAlignment * Size;
for (int i = 0; i < my_file->NumberOfSections; i++)
{
temp_stretch_data = (void*)((char*)Stretch_Data+my_section[i]->VirtualAddress);
temp_before_stretch_data_ptr = (void*)((char*)Before_Stretch_Data+my_section[i]->PointerToRawData);
memcpy_s(temp_stretch_data, my_section[i]->SizeOfRawData, temp_before_stretch_data_ptr, my_section[i]->SizeOfRawData);
}
cout << "拉伸成功" << endl;
}
void Shrink_PE()
{
unsigned int Size = 0;
Size = my_section[my_file->NumberOfSections - 1]->PointerToRawData + my_section[my_file->NumberOfSections - 1]->SizeOfRawData;
Shrink_data = (void*)malloc(Size);
//从Stretch_Data缩小
//复制Heads
memcpy_s(Shrink_data, my_optional->SizeOfHeaders, Stretch_Data, my_optional->SizeOfHeaders);
//复制节
void* temp_shrink_data_ptr = Shrink_data;
void* temp_stretch_data_ptr = Stretch_Data;
for (int i = 0; i < my_file->NumberOfSections; i++)
{
temp_shrink_data_ptr = (void*)((char*)Shrink_data + my_section[i]->PointerToRawData);
temp_stretch_data_ptr= (void*)((char*)Stretch_Data + my_section[i]->VirtualAddress);
memcpy_s(temp_shrink_data_ptr, my_section[i]->SizeOfRawData, temp_stretch_data_ptr, my_section[i]->SizeOfRawData);
}
cout << "缩小成功" << endl;
return;
}
int main()
{
char filename[100]= "ceshi.exe";
Before_Stretch_Data =Readfile(filename);
Analyze_PE((char*&)Before_Stretch_Data, my_dos, my_file, my_optional, my_section);
cout << my_dos->e_lfanew << endl;
cout << my_file->Characteristics << endl;
cout << my_optional->ImageBase << endl;
cout << my_section[1]->Name<< endl;
Stretch_PE();
cout << my_section[3]->Name << endl;
Shrink_PE();
Analyze_PE((char*&)Shrink_data, my_dos, my_file, my_optional, my_section);
cout << my_dos->e_lfanew << endl;
cout << my_file->Characteristics << endl;
cout << my_optional->ImageBase << endl;
cout << my_section[1]->Name << endl;
return 0;
}