滴水PE作业(3月16日)

 目标如上图: 将文件放入内存后拉伸再拉回去存盘

代码如下, 写的比较乱, 没怎么整理, 大佬勿怪

发现一些问题, 节的数据没有存盘, 所以导出来的文件无法运行( ̄▽  ̄)

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<Windows.h>
//存入内存
//开始拉伸
//拉回来
//存回硬盘

//存入内存
//1. 打开文件
//2. 开辟空间
// 2.1获取开辟空间的大小
//3. 载入
FILE* OpenFile() {
	//打开文件
	FILE* file_point;
	int return1 = fopen_s(&file_point, "C:\\Windows\\System32\\notepad.exe","rb");
	if (return1 != 0) {
		printf("获取文件指针错误\n");
	}
	return file_point;
}
char* GetMemory(FILE* file_point) {
	//开辟空间
	fseek(file_point, 0, SEEK_END);
	int file_size = ftell(file_point);
	fseek(file_point, 0, SEEK_SET);
	char* enter_memory = (char*)malloc(sizeof(char) * file_size);
	fread(enter_memory, file_size, 1, file_point);
	return enter_memory;
}
void FreeMemory(FILE* file_point, char* memory_point[], int memory_size) {
	for (int i = 0; i < memory_size; i++) {
		free(memory_point[i]);
	}
	fclose(file_point);
}

//将16进制转成字符, 检测用, 一般没什么用
void conversion(int data) {
	char* point = (char*)&data;
	for (int i = 0; i < 4; i++) {
		printf("%c", *point);
		point++;
	}
}
//开始拉伸
// 1.根据可选PE头里sizofImage的大小申请空间, 将空间全部用0覆盖
// 2. 申请完后根据sizeofHeaders的值将headers的数据加入新的空间
// 3. 根据标准pe头里的numberofSection遍历节表, 
// 4.根据节表中的PointertoRawData与SizeOfRawData将数据填入VisualAddress所指向的内存
char* BeginStretch(char* memory) {
	PIMAGE_DOS_HEADER dos_header = NULL;
	dos_header = (PIMAGE_DOS_HEADER)memory;

	//创建nt头并根据dos头的数据设置nt头的起始地址
	PIMAGE_NT_HEADERS nt_header = NULL;
	nt_header = (PIMAGE_NT_HEADERS)((DWORD)dos_header + dos_header->e_lfanew);

	//创建PE标准头并从中获得NumberOfSections
	PIMAGE_FILE_HEADER file_header = NULL;
	file_header = &(nt_header->FileHeader);
	int section_num = file_header->NumberOfSections;

	//从标准PE头转到可选PE头并获取SizeOfImage
	PIMAGE_OPTIONAL_HEADER optional_header = NULL;
	optional_header = (PIMAGE_OPTIONAL_HEADER)((DWORD)file_header + IMAGE_SIZEOF_FILE_HEADER);
	int stretch_size = optional_header->SizeOfImage;

	//创建新的空间清零并复制headers至新的空间
	char* new_memory = (char*)malloc(sizeof(char)*stretch_size);
	memset(new_memory, 0, stretch_size);
	memcpy(new_memory, memory, optional_header->SizeOfHeaders);
	//获取memory的节表
	PIMAGE_SECTION_HEADER section_header = NULL;
	section_header = (PIMAGE_SECTION_HEADER)((DWORD)optional_header + file_header->SizeOfOptionalHeader);

	//创建新的dos头并根据dos头的e_lfanew创建nt头
	PIMAGE_DOS_HEADER new_dos = NULL;
	new_dos = (PIMAGE_DOS_HEADER)new_memory;
	PIMAGE_NT_HEADERS new_nt_header = NULL;
	new_nt_header = (PIMAGE_NT_HEADERS)((DWORD)new_dos + new_dos->e_lfanew);

	//获取new_memory的节表, 寻找到了速度较快的写法
	PIMAGE_SECTION_HEADER new_section = NULL;
	new_section = (PIMAGE_SECTION_HEADER)((DWORD)(new_nt_header + 1));

	//遍历节表, 根据memory节表中的PointertoRawData与SizeOfRawData将数据填入new_memory的VisualAddress所指向的内存
	//偏移需要加上memory才是正确的地址
	for (int i = 0; i < section_num; i++) {
		memcpy((char*)(new_memory+new_section->VirtualAddress), (char*)(memory+section_header->PointerToRawData), section_header->SizeOfRawData);
		section_header++;
		new_section++;
	}
	return new_memory;
}
//拉回来
//先确定需要申请多大的空间后申请空间后清零
// 1.根据file_header中的number_of_section确定节表的数量
// 2. 根据节表中最后一个节的pointer_to_raw_data+Visual_size的起始地址确定需要的大小
//根据optional_header中的size_of_headers将headers加入新的内存
//根据节表中的visual_address+memory起始地址确定节的位置
//根据节表中的visual_size确定每个节要复制的大小
//将上面的节根据新节表中的PointeToRawData复制到last_memory
char* Back_Origin(char* new_memory){
	//新建nt头
	PIMAGE_DOS_HEADER new2_dos = NULL;
	new2_dos = (PIMAGE_DOS_HEADER)new_memory;
	PIMAGE_NT_HEADERS new2_nt = NULL;
	new2_nt = (PIMAGE_NT_HEADERS)((DWORD)new2_dos + new2_dos->e_lfanew);

	//根据file_header中的number_of_section确定节表的数量
	PIMAGE_FILE_HEADER new2_file = (PIMAGE_FILE_HEADER)((DWORD)new2_nt+4);
	int new2_section_num = new2_file->NumberOfSections;
	
	//找到第一个节表的位置
	PIMAGE_SECTION_HEADER new2_section = NULL;
	new2_section = (PIMAGE_SECTION_HEADER)((DWORD)(new2_nt + 1));

	//定位到最后一个节
	for (int i = 0; i < new2_section_num-1; i++) {
		new2_section++;
	}
	//根据节表中最后一个节的pointer_to_raw_data+Visual_size确定需要的大小
	DWORD size = (DWORD)(new2_section->PointerToRawData + new2_section->Misc.VirtualSize);
	
	//申请空间
	char* last_memory = (char*)malloc(sizeof(char) * size);
	memset(last_memory, 0, size);

	//获取headers的大小并复制到last_memory
	PIMAGE_OPTIONAL_HEADER new2_optional = (PIMAGE_OPTIONAL_HEADER)((DWORD)new2_file + 20);
	DWORD last_headers_size = new2_optional->SizeOfHeaders;
	memcpy(last_memory, new_memory, last_headers_size);

	//定位到last_memory的起始节表
	PIMAGE_DOS_HEADER last_dos = NULL;
	last_dos = (PIMAGE_DOS_HEADER)last_memory;
	PIMAGE_NT_HEADERS last_nt = NULL;
	last_nt = (PIMAGE_NT_HEADERS)((DWORD)last_dos + last_dos->e_lfanew);
	PIMAGE_SECTION_HEADER last_section = NULL;
	last_section = (PIMAGE_SECTION_HEADER)((DWORD)(last_nt + 1));
	
	for (int i = 0; i < new2_section_num; i++) {
		memcpy((char*)(last_memory + last_section->PointerToRawData), (char*)(new_memory + new2_section->VirtualAddress), new2_section->Misc.VirtualSize);
		last_section++;
		new2_section++;
	}
	return last_memory;
}
// 存回硬盘
//确定last_memory的容量
//使用fwrite函数
void Back_Rom(char* last_memory) {
	//新建nt头
	PIMAGE_DOS_HEADER new2_dos = NULL;
	new2_dos = (PIMAGE_DOS_HEADER)last_memory;
	PIMAGE_NT_HEADERS new2_nt = NULL;
	new2_nt = (PIMAGE_NT_HEADERS)((DWORD)new2_dos + new2_dos->e_lfanew);

	//根据file_header中的number_of_section确定节表的数量
	PIMAGE_FILE_HEADER new2_file = (PIMAGE_FILE_HEADER)((DWORD)new2_nt + 4);
	int new2_section_num = new2_file->NumberOfSections;

	//找到第一个节表的位置
	PIMAGE_SECTION_HEADER new2_section = NULL;
	new2_section = (PIMAGE_SECTION_HEADER)((DWORD)(new2_nt + 1));

	//定位到最后一个节
	for (int i = 0; i < new2_section_num - 1; i++) {
		new2_section++;
	}
	//根据节表中最后一个节的pointer_to_raw_data+Visual_size确定需要的大小
	DWORD size = (DWORD)(new2_section->PointerToRawData + new2_section->Misc.VirtualSize);
	FILE* last_one_file = NULL;
	fopen_s(&last_one_file, "D:\\Ddisk\\last_memory.exe", "wb");
	fwrite(last_memory, 1, size, last_one_file);
	fclose(last_one_file);
}
void main() {
	FILE* file_point = OpenFile();
	char* memory_point = GetMemory(file_point);
	char* new_memory = BeginStretch(memory_point);
	char* last_memory = Back_Origin(new_memory);
	Back_Rom(last_memory);
	//conversion(0x7865742e);
	char* memory[] = { memory_point,new_memory, last_memory};
	int num = (sizeof(memory)) / 4;
	FreeMemory(file_point, memory, num);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值