滴水PE作业2

这段代码主要实现了对PE文件的解析,包括打开文件、读取内存、释放内存等操作。它详细处理了PE文件的DOS头、NT头、可选头、节表,以及重定位表、导出表和导入表的信息。通过对内存地址的转换,代码能够打印出各种表的详细内容,如节名、虚拟地址、文件偏移等,并能将导出表的内容写入新的文件。

 打印上图所示的导出表, 导入表, 重定位表以及所有的头部的信息

代码如下

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<Windows.h>
FILE* OpenFile(char path[]);
char* GetMemory(FILE* file_point);
void FreeMemory(FILE* file_point, char* memory_point[], int memory_size);
void conversion(PIMAGE_SECTION_HEADER section);
PIMAGE_DOS_HEADER dos_ptr(char* memory);
PIMAGE_NT_HEADERS nt_ptr(char* memory);
PIMAGE_FILE_HEADER file_ptr(char* memory);
PIMAGE_OPTIONAL_HEADER optional_ptr(char* memory);
PIMAGE_SECTION_HEADER section_ptr(char* memory);
PIMAGE_SECTION_HEADER last_section_ptr(char* memory);
void export_file(char* memory);
char* transform_to_file(char* memory, char* first);
char* transform_to_memory(char* memory, char* first);
DWORD get_largest_size(DWORD virtual_size, DWORD file_size);
DWORD* data_directory(char* memory);

void analysize(char path[]);
void print(char* memory);
void print_reloc(char* memory);
void print_export(char* memory);
void print_import(char* memory);
void conversion2(PIMAGE_SECTION_HEADER section);

FILE* OpenFile(char path[]) {
	//打开文件
	FILE* file_point;
	int return1 = fopen_s(&file_point, path, "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);
	DWORD needed_size = sizeof(char) * file_size;
	char* enter_memory = (char*)malloc(needed_size);
	memset(enter_memory, 0, needed_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);
}

void conversion(PIMAGE_SECTION_HEADER section) {
	char* point = (char*)section;
	printf("节表: ");
	for (int i = 0; i < 8; i++) {
		printf("%c", *point);
		point++;
	}
}

PIMAGE_DOS_HEADER dos_ptr(char* memory) {
	return (PIMAGE_DOS_HEADER)(memory);
}
PIMAGE_NT_HEADERS nt_ptr(char* memory) {
	return (PIMAGE_NT_HEADERS)((DWORD)dos_ptr(memory) + dos_ptr(memory)->e_lfanew);
}
PIMAGE_FILE_HEADER file_ptr(char* memory) {
	return (PIMAGE_FILE_HEADER)((DWORD)nt_ptr(memory) + 4);
}
PIMAGE_OPTIONAL_HEADER optional_ptr(char* memory) {
	return (PIMAGE_OPTIONAL_HEADER)((DWORD)file_ptr(memory) + 20);
}
PIMAGE_SECTION_HEADER section_ptr(char* memory) {
	return (PIMAGE_SECTION_HEADER)(optional_ptr(memory) + 1);
}
PIMAGE_SECTION_HEADER last_section_ptr(char* memory) {
	PIMAGE_SECTION_HEADER section = section_ptr(memory);
	PIMAGE_FILE_HEADER file = file_ptr(memory);
	int circle_num = file->NumberOfSections;
	for (int i = 0; i < circle_num - 1; i++) {
		section++;
	}
	return section;
}

void export_file(char* memory) {
	FILE* win_file = NULL;
	fopen_s(&win_file, "D:\\Ddisk\\last_memory.exe", "wb");
	fseek(win_file, 0, SEEK_SET);
	PIMAGE_OPTIONAL_HEADER optional = optional_ptr(memory);
	//先导出头部数据
	int sizeofHeaders = optional->SizeOfHeaders;
	int fileAlignment = optional->FileAlignment;
	if ((sizeofHeaders % fileAlignment) > 0) {
		DWORD header_data = fileAlignment * ((sizeofHeaders / fileAlignment) + 1);
		fwrite(memory, 1, header_data, win_file);
	}
	else if ((sizeofHeaders % fileAlignment) == 0) {
		DWORD header_data2 = fileAlignment * (sizeofHeaders / fileAlignment);
		fwrite(memory, 1, header_data2, win_file);
	}
	//导出各个
	int section_num = file_ptr(memory)->NumberOfSections;
	PIMAGE_SECTION_HEADER section = section_ptr(memory);
	for (int i = 0; i < section_num; i++) {
		fseek(win_file, section->PointerToRawData, SEEK_SET);
		fwrite((char*)(section->PointerToRawData + (DWORD)memory), 1, section->SizeOfRawData, win_file);
		section++;
	}
	fclose(win_file);
}
//转换rva到foa
//first代表文件开始地址, 根据开始地址找到内存基址和alignment, 节表个数
// if(memory-first>=内存基址){memory=memory-内存基址}
// if(memory<alignment){memory存在于header中, return memory}
// 定位到节表
//遍历节表信息, 依次比较if(VirtualAddress+VirtualSize>=memory>=VirtualAddress){
//	锁定节表序号, offset: memory-virtualAddress;
// 根据节表序号找到文件中的偏移, 文件偏移加offset为foa
char* transform_to_file(char* memory, char* first) {
	//定位file并获取节表数量
	PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)first;
	PIMAGE_FILE_HEADER file = (PIMAGE_FILE_HEADER)((DWORD)dos + dos->e_lfanew + 4);
	int table_num = file->NumberOfSections;
	//定位optional并获取内存基址与对齐
	PIMAGE_OPTIONAL_HEADER optional = (PIMAGE_OPTIONAL_HEADER)(DWORD(file) + 20);
	DWORD image_base = optional->ImageBase;
	DWORD align = optional->SectionAlignment;
	if ((int)(memory - first) >= (int)image_base) { memory = memory - image_base; }
	if ((int)memory < (int)align) { return memory; }
	PIMAGE_SECTION_HEADER section = NULL;
	section = (PIMAGE_SECTION_HEADER)(optional + 1);
	for (int i = 0; i < table_num; i++) {
		if ((section->VirtualAddress + get_largest_size(section->Misc.VirtualSize, section->SizeOfRawData)) >= (DWORD)memory && (DWORD)memory >= section->VirtualAddress) {
			return (char*)((DWORD)section->PointerToRawData + ((DWORD)memory - (DWORD)section->VirtualAddress));
			break;
		}
		section++;
	}
	return (char*)-1;
}
char* transform_to_memory(char* memory, char* first) {
	//定位file并获取节表数量
	PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)first;
	PIMAGE_FILE_HEADER file = (PIMAGE_FILE_HEADER)((DWORD)dos + dos->e_lfanew + 4);
	int table_num = file->NumberOfSections;
	//定位optional并获取内存基址与对齐
	PIMAGE_OPTIONAL_HEADER optional = (PIMAGE_OPTIONAL_HEADER)(DWORD(file) + 20);
	DWORD image_base = optional->ImageBase;
	DWORD align = optional->SectionAlignment;
	if ((int)(memory - first) >= (int)image_base) { memory = memory - image_base; }
	if ((int)memory < (int)align) { return memory; }
	PIMAGE_SECTION_HEADER section = NULL;
	section = (PIMAGE_SECTION_HEADER)(optional + 1);
	for (int i = 0; i < table_num; i++) {
		if (section->PointerToRawData + get_largest_size(section->Misc.VirtualSize, section->SizeOfRawData) >= (DWORD)memory && (DWORD)memory >= section->PointerToRawData) {
			return (char*)((DWORD)section->VirtualAddress + ((DWORD)memory - (DWORD)section->PointerToRawData));
			break;
		}
		section++;
	}
	return (char*)-1;
}
DWORD get_largest_size(DWORD virtual_size, DWORD file_size) {
	if (virtual_size > file_size) {
		return virtual_size;
	}
	else {
		return file_size;
	}
	return 0;
}
//得到数据目录表存储的各个表的数据
DWORD* data_directory(char* memory) {
	PIMAGE_OPTIONAL_HEADER optional = optional_ptr(memory);
	DWORD* data_directory = (DWORD*)&optional->DataDirectory;
	int directory_circle = optional->NumberOfRvaAndSizes;
	DWORD sum_arr[32] = { 0 };
	for (int i = 0; i < directory_circle; i++) {
		sum_arr[i + 16] = *data_directory;
		sum_arr[i] = (DWORD)(transform_to_file((char*)*data_directory, memory));
		data_directory = data_directory + 2;
	}
	return sum_arr;
}
//翻译字符串
void conversion2(PIMAGE_SECTION_HEADER section) {
	char* point = (char*)section;
	printf("===================开始查找节表");
	for (int i = 0; i < 8; i++) {
		printf("%c", *point);
		point++;
	}printf("中信息=========================\n");
}
//打印重定位表
void print_reloc(char* memory) {
	//打印重定位表
	// 1.根据table_address[5]的的地址找到重定位表
	DWORD* first_data = data_directory(memory);
	DWORD table_address[32] = { 0 };
	for (int i = 0; i < 32; i++) {
		table_address[i] = *first_data;
		first_data++;
	}
	printf("===================开始查找数据目录->重定位表中信息=========================\n");
	if (table_address[5] == 0) { printf("不存在重定位表\n"); }
	else {
		printf("%x\n", table_address[5]);
		printf("%x\n", memory);
		printf("%x\n", (DWORD)memory + table_address[5]);
		PIMAGE_BASE_RELOCATION reloc = (PIMAGE_BASE_RELOCATION)((DWORD)memory + table_address[5]);
		int sign = 1;
		WORD shift_pos = 0;
		WORD judge = 0;
		while (reloc->VirtualAddress != 0 && reloc->SizeOfBlock != 0) {
			printf("%-2d: VirtualAddress:%-8x", sign, reloc->VirtualAddress);
			printf("FOA:%-8x", ((DWORD)(reloc)-(DWORD)(memory)));
			printf("SizeOfBlock:%x\n", reloc->SizeOfBlock);
			printf("具体项数据为: \n");
			DWORD times = (reloc->SizeOfBlock - 8) / 2;
			short* position = (short*)((DWORD)reloc + 8);
			for (int i = 1; i <= times; i++) {
				shift_pos = *position;
				judge = shift_pos;
				shift_pos = shift_pos << 4;
				shift_pos = shift_pos >> 4;
				judge = judge >> 12;
				if (judge == 3) {
					printf("(%-3d)%-6x ", i, reloc->VirtualAddress + shift_pos);
				}
				position++;
			}
			printf("\n");
			printf("废弃项数据为: \n");
			short* position2 = (short*)((DWORD)reloc + 8);
			for (int i = 1; i <= times; i++) {
				shift_pos = *position2;
				judge = shift_pos;
				shift_pos = shift_pos << 4;
				shift_pos = shift_pos >> 4;
				judge = judge >> 12;
				if (judge != 3) {
					printf("(%-3d)%x ", i, reloc->VirtualAddress + shift_pos);
				}
				position2++;
			}
			printf("\n");
			reloc = (PIMAGE_BASE_RELOCATION)((DWORD)reloc + reloc->SizeOfBlock);
			sign++;
		}
	}
}
//打印导出表
void print_export(char* memory) {
	// 1.根据table_address中的地址找到导出表的地址
	// 2. 打印导出表的信息
	DWORD* first_data = data_directory(memory);
	DWORD table_address[32] = { 0 };
	for (int i = 0; i < 32; i++) {
		table_address[i] = *first_data;
		first_data++;
	}
	printf("===================开始查找数据目录->导出表中信息=========================\n");
	if (table_address[0] == 0) { printf("不存在导出表\n"); }
	else {
		PIMAGE_EXPORT_DIRECTORY export_table = (PIMAGE_EXPORT_DIRECTORY)((DWORD)table_address[0] + (DWORD)memory);
		printf("Name(存储导出表文件名字符串的地址): %x\n", (DWORD)transform_to_file((char*)(export_table->Name), memory));
		printf("Base(导出函数起始序号): %x\n", export_table->Base);
		printf("NumberOfFunction(所有导出函数个数): %x\n", export_table->NumberOfFunctions);
		printf("NumberOfNames(以函数名字导出的函数的个数): %x\n", export_table->NumberOfNames); printf("\n");
		//打印导出表->地址表
		printf("AddressOfFunction(导出函数地址表(FOA))地址: %x\n", (DWORD)transform_to_file((char*)(export_table->AddressOfFunctions), memory));
		printf("AddressOfFunction(导出函数地址表(FOA))数据\n");
		DWORD* export_address_data = (DWORD*)((DWORD)memory + (DWORD)transform_to_file((char*)export_table->AddressOfFunctions, memory));
		int num = export_table->NumberOfFunctions;
		for (int i = 0; i < num; i++) {
			printf("RVA: %-8x", *export_address_data);
			printf("FOA: %x\n", (DWORD)transform_to_file((char*)*export_address_data, memory));
			export_address_data++;
		}
		printf("\n");
		//打印导出表->名称表
		printf("AddressOfNames(导出函数名称表(FOA)): %x\n", (DWORD)transform_to_file((char*)(export_table->AddressOfNames), memory));
		printf("AddressOfFunction(导出函数名称表(FOA))数据\n");
		DWORD* export_name_data = (DWORD*)((DWORD)memory + (DWORD)transform_to_file((char*)export_table->AddressOfNames, memory));
		int num2 = export_table->NumberOfNames;
		for (int i = 0; i < num2; i++) {
			printf("RVA: %-8x", *export_name_data);
			DWORD name_foa = (DWORD)transform_to_file((char*)*export_name_data, memory);
			printf("FOA: %-8x", name_foa);
			printf("FOA对应函数名称:");
			char* new_name_foa = (memory + name_foa);
			while (*new_name_foa != 0) {
				printf("%c", *new_name_foa);
				new_name_foa++;
			}
			export_name_data++;
			printf("\n");
		}
		printf("\n");
		//打印导出表->序号表
		printf("AddressOfNameOrdinals(导出函数序号表RVA: %x, FOA: %x\n", export_table->AddressOfNameOrdinals, (DWORD)transform_to_file((char*)(export_table->AddressOfNameOrdinals), memory));
		printf("AddressOfFunction(导出函数序号数据\n");
		WORD* export_order_data = (WORD*)((DWORD)memory + (DWORD)transform_to_file((char*)export_table->AddressOfNameOrdinals, memory));
		int num3 = export_table->NumberOfNames;
		for (int i = 0; i < num3; i++) {
			printf("%d: ", i);
			printf("序号: %d ", *export_order_data);
			printf("导出序号=序号+Base=%d+%d=%d\n", *export_order_data, export_table->Base, *export_order_data + export_table->Base);
			printf("\n");
			export_order_data++;
		}
	}
}
void print_import(char* memory) {
	DWORD* first_data = data_directory(memory);
	DWORD table_address[32] = { 0 };
	for (int i = 0; i < 32; i++) {
		table_address[i] = *first_data;
		first_data++;
	}
	//打印导入表
	printf("===================开始查找数据目录->导入表中信息=========================\n");
	if (table_address[1] == 0) {
		printf("不存在导入表\n");
	}
	else {
		PIMAGE_IMPORT_DESCRIPTOR pimport = (PIMAGE_IMPORT_DESCRIPTOR)(table_address[1] + (DWORD)memory);
		int i = 1;
		while (pimport->Name != 0) {
			//打印dll名字
			printf("导入表%d所在FOA:%x\n", i, ((DWORD)pimport - (DWORD)memory));
			printf("%-2d:", i);
			char* name = (char*)(transform_to_file((char*)pimport->Name, memory) + (DWORD)memory);
			printf("----------------------");
			while (*name != 0) {
				printf("%c", *name);
				name++;
			}
			printf("---");
			printf("TimeDateStamp: %x ", pimport->TimeDateStamp);
			printf("----------------------");
			printf("\n");

			//打印OriginalFirstThunk
			DWORD* oring_thunk = (DWORD*)transform_to_file((char*)pimport->OriginalFirstThunk, memory);
			printf("OriginalFirstThunk所在: RVA:%-8xRVA->FOA:%-8x\n", pimport->OriginalFirstThunk, oring_thunk);
			int j = 1;
			printf("OrinGinalFirstThunk→ INT(导入名称表)\n");
			DWORD* file_oring_thunk = (DWORD*)((DWORD)oring_thunk + (DWORD)memory);
			while (*file_oring_thunk != 0) {
				if ((*file_oring_thunk & 0x80000000) == 0x80000000) {
					printf("(%-2d):%-4x\n", j, 0x7FFFFFFF & *file_oring_thunk);
				}
				else {
					char* real_file_oring_thunk = (char*)((DWORD)(transform_to_file((char*)*file_oring_thunk, memory) + (DWORD)memory));
					printf("(%-2d):RVA:%x, FOA:%x: ", j, *file_oring_thunk, transform_to_file((char*)*file_oring_thunk, memory));
					PIMAGE_IMPORT_BY_NAME import_byname = (PIMAGE_IMPORT_BY_NAME)(real_file_oring_thunk);
					printf("%x,%s\n", import_byname->Hint, import_byname->Name);
				}
				j++;
				file_oring_thunk++;
			}
			printf("\n");
			//打印FirstThunk
			DWORD* firstThunk = (DWORD*)transform_to_file((char*)pimport->FirstThunk, memory);
			printf("FirstThunk: RVA:%-8xRVA->FOA:%-8x\n", pimport->FirstThunk, firstThunk);
			DWORD* file_firstThunk = (DWORD*)((DWORD)firstThunk + (DWORD)memory);
			int k = 1;
			printf("FirstThunk→ IAT(导入地址表)\n");
			while (*file_firstThunk != 0) {
				if ((*file_firstThunk & 0x80000000) == 0x80000000) {
					printf("(%-2d):%-4x ", k, 0x7FFFFFFF & *file_firstThunk);
				}
				else {
					printf("(%-2d):%x: ", k, transform_to_file((char*)*file_firstThunk, memory));
					PIMAGE_IMPORT_BY_NAME import_byname = (PIMAGE_IMPORT_BY_NAME)(file_firstThunk);
					printf("%x,%s\n", import_byname->Hint, import_byname->Name);
				}
				k++;
				file_firstThunk++;
			}
			printf("\n");
			printf("\n");
			pimport++;
			i++;
		}
	}
}
void print(char* memory) {
	//打印dos头
	PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)memory;
	printf("===================开始查找DOS头中信息=========================\n");
	printf("Dos->e_magic: %x\n", dos->e_magic);
	printf("Dos->e_lfanew: %x\n", dos->e_lfanew);
	printf("\n");
	//打印NT->PE标记头
	PIMAGE_NT_HEADERS nt = (PIMAGE_NT_HEADERS)((DWORD)dos + dos->e_lfanew);
	printf("===================开始查找NT->PE标记头中信息=========================\n");
	printf("NT->PE标记: %x\n", *nt);
	//打印NT->标准PE头
	PIMAGE_FILE_HEADER file = (PIMAGE_FILE_HEADER)((DWORD)(nt)+4);
	printf("\n");
	printf("===================开始查找NT->标准PE头中信息=========================\n");
	printf("Machine: %x\n", file->Machine);
	printf("NumberOfSections(节表个数): %x\n", file->NumberOfSections);
	printf("SizeOfOptionalHeader(可选PE头大小): %x\n", file->SizeOfOptionalHeader);
	printf("\n");
	//打印NT->可选PE头
	PIMAGE_OPTIONAL_HEADER optional = (PIMAGE_OPTIONAL_HEADER)(DWORD(file) + 20);
	printf("===================开始查找NT->可选PE头中信息=========================\n");
	printf("PE->magic: %x\n", optional->Magic);
	printf("Address Of EntryPoint(程序入口地址偏移): %x\n", optional->AddressOfEntryPoint);
	printf("Image Base(内存基址): %x\n", optional->ImageBase);
	printf("Section Alighment(内存对齐): %x\n", optional->SectionAlignment);
	printf("File Alignment(文件对齐): %x\n", optional->FileAlignment);
	printf("Size Of Image(内存大小): %x\n", optional->SizeOfImage);
	printf("Size Of Headers(头文件大小): %x\n", optional->SizeOfHeaders);
	printf("Number Of Rva And Sizes: %x\n", optional->NumberOfRvaAndSizes);
	printf("\n");
	//打印数据目录的偏移
	DWORD* directory = (DWORD*)&optional->DataDirectory;
	printf("===================开始查找NT->数据目录中信息=========================\n");
	//打印各个数据目录的信息,创建table_address=table_p存储各个数据目录的地址(foa), table_before=table_p2存储rva
	DWORD table_address[16] = { 0 };
	DWORD table_before[16] = { 0 };
	DWORD* table_p = table_address;
	DWORD* table_p2 = table_before;
	//数据目录终1
	for (int i = 0; i < 16; i++) {
		printf("内存偏移: %-8x ", *directory);
		*table_p2 = (DWORD)*directory;
		*table_p = (DWORD)transform_to_file((char*)*directory, memory);
		printf("RVA->FOA: %-12x", *table_p);
		table_p++;
		table_p2++;
		directory++;
		printf("大小: %x\n", *directory++);
	}printf("\n");
	
	//打印节表
	printf("\n");
	PIMAGE_SECTION_HEADER section = (PIMAGE_SECTION_HEADER)(DWORD(optional) + file->SizeOfOptionalHeader);
	for (int i = 0; i < file->NumberOfSections; i++) {
		conversion(section);
		printf("VirtualSize(对齐前所占大小(内存)): %x\n", section->Misc.VirtualSize);
		printf("SizeOfRawData(对齐后所占大小(文件)): %x\n", section->SizeOfRawData);
		printf("VirtualAddress(在内存中偏移(RVA)): %x\n", section->VirtualAddress);
		printf("PointerToRawData(在文件中偏移(FOA)): %x\n", section->PointerToRawData);
		printf("Characteristics(标志(块属性)): %x\n", section->Characteristics);
		section++;
		printf("\n");
	}
}


void analysize(char path[]) {
	FILE* file_point = OpenFile(path);
	char* memory_point = GetMemory(file_point);
	print(memory_point);
	print_export(memory_point);
	print_import(memory_point);
	print_reloc(memory_point);
	char* memory[] = { memory_point };
	int num = (sizeof(memory)) / 4;
	FreeMemory(file_point, memory, num);
}
int main() {
    char dll[] = "D:\\Ddisk\\逆向\\AutoUpdateUtil.dll";
    char last_memory[] = "D:\\Ddisk\\last_memory.exe";
    char notepad[] = "C:\\Windows\\System32\\notepad.exe";
    char crack[] = "D:\\Ddisk\\逆向\\CrackMe.exe";
    analysize(notepad);
}

部分运行结果如下

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值