【滴水三期】打印导出表、重定位表

注:本代码目前只实现了打印功能,且只支持32位程序。

        打印dos头、file头、option头、section头、export_Directory、Relocation_Directory。

        其中读取的:export_Directory、Relocation_Directory是通过imagebuffer读取的。

        节表插入代码、新增表功能还没有实现。

#include <stdio.h>
#include <windows.h>
#include <winnt.h>

#define FILE_PATH "C:\\ReverseTraining_1.exe"


void TextPrintfExportTable(PIMAGE_OPTIONAL_HEADER32 pOption32Header, LPVOID ImageBuffer);
void TextPrintfRelocationTable(PIMAGE_OPTIONAL_HEADER32 pOption32Header, LPVOID ImageBuffer);



//写一个rva转foa的函数
/*
* RVAToFOAfun: rva转foa
* 参数:rva 内存偏移;foa文件偏移
* 返回值:foa
* 用到的时候直接调用下这个函数就OK
*/
DWORD RVAToFOAfun(IN DWORD RVA,IN LPVOID FileBuffer) {
	//现有的地址 - imagebase + ponitertodataraw;
	//1、获取传进来一个RVA,filebuffer?
	PIMAGE_DOS_HEADER pDos_Header = NULL;
	PIMAGE_NT_HEADERS32 pNT_Header32 = NULL;
	PIMAGE_NT_HEADERS64 pNT_Header64 = NULL;
	PIMAGE_FILE_HEADER pFile_Header = NULL;
	PIMAGE_OPTIONAL_HEADER32 pOption_Header32 = NULL;
	PIMAGE_OPTIONAL_HEADER64 pOption_Header64 = NULL;
	PIMAGE_SECTION_HEADER pSection_Header = NULL;
	DWORD FOA=0;

	if (!FileBuffer)
	{
		printf("FileBuffer有误\n");
		return FOA;
	}

	pDos_Header = (PIMAGE_DOS_HEADER)FileBuffer;
	pFile_Header = PIMAGE_FILE_HEADER((DWORD)pDos_Header->e_lfanew + (DWORD)FileBuffer + 4);
	pOption_Header32 = PIMAGE_OPTIONAL_HEADER32((DWORD)pFile_Header + IMAGE_SIZEOF_FILE_HEADER);

	pSection_Header = (PIMAGE_SECTION_HEADER)(pFile_Header->SizeOfOptionalHeader + (DWORD)pOption_Header32);

	BOOL isMZ = (*((PWORD)(FileBuffer)) == IMAGE_DOS_SIGNATURE);
	if (!isMZ)
	{
		printf("不是标准PE文件:%d\n", *((PWORD)(FileBuffer)));
		return FOA;
	}

	//判断是否为有效的PE标志
	BOOL isPE = (*(PDWORD(pDos_Header->e_lfanew + (DWORD)(FileBuffer)))) == IMAGE_NT_SIGNATURE;
	if (!isPE)
	{
		printf("不是标准的PE文件:%d\n", *(PDWORD(pDos_Header->e_lfanew + (DWORD)(FileBuffer))));
		return FOA;
	}

	for (int i = 0; i < pFile_Header->NumberOfSections; i++)
	{
		if ((RVA >= pSection_Header[i].VirtualAddress )&& (RVA < pOption_Header32->SizeOfImage - pOption_Header32->SizeOfHeaders))
		{
			FOA = RVA - (pSection_Header[i].VirtualAddress) + pSection_Header[i].PointerToRawData;
			break;
		}
	}
		
	return FOA;
}


//read_file:读取文件 
// 参数:file_name 要读取的文件名
//返回读取到的文件字节大小,返回存放数据的缓冲区
DWORD read_file(IN LPCSTR file_name, OUT LPVOID* file_buffer ) {
	
	SIZE_T file_size = 0;
	//LPVOID temp_buffer = NULL;
	FILE* pfile = NULL;
	if (fopen_s(&pfile, file_name, "rb")) {
		printf("打开文件:%s失败\n",file_name);
		fclose(pfile);
		return 0;
	}

	fseek(pfile,0,SEEK_END);
	file_size=ftell(pfile);
	rewind(pfile);

	*file_buffer =calloc(1,file_size);
	
	fread_s(*file_buffer,file_size,1,file_size,pfile);

	fclose(pfile);
	return file_size;
}

//从filebuffer 拉伸到image_buffer状态
DWORD FileBufferToImageBuffer(IN LPVOID* file_buffer,OUT LPVOID* image_buffer) {
	PIMAGE_DOS_HEADER dos_header=NULL;
	PIMAGE_NT_HEADERS32 nt_header32=NULL;
	PIMAGE_NT_HEADERS64 nt_header64=NULL;
	PIMAGE_FILE_HEADER file_header=NULL;
	PIMAGE_OPTIONAL_HEADER32 option_header32=NULL;
	PIMAGE_OPTIONAL_HEADER64 option_header64=NULL;
	PIMAGE_SECTION_HEADER section_header=NULL;

	dos_header = (PIMAGE_DOS_HEADER)*file_buffer;

	if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
	{
		printf("非可执行文件:%04X\n",dos_header->e_magic);
		return 0;
	}
	if (  *((PDWORD)(dos_header->e_lfanew +(DWORD)(dos_header))) != IMAGE_NT_SIGNATURE)
	{
		printf("非可执行文件:%08X\n", *(PDWORD)(dos_header->e_lfanew + (DWORD)file_buffer));
		return 0;
	}
	
	//需要取到section_header 中的信息,去转换才可以。

	file_header =  (PIMAGE_FILE_HEADER)(dos_header->e_lfanew + (DWORD)*file_buffer+4);

	DWORD section_number =  file_header->NumberOfSections;
	DWORD size_option_header =  file_header->SizeOfOptionalHeader;

	option_header32 = (PIMAGE_OPTIONAL_HEADER32)((DWORD)file_header + IMAGE_SIZEOF_FILE_HEADER);

	DWORD header32_size = option_header32->SizeOfHeaders;
	DWORD image32_size= option_header32->SizeOfImage;

	section_header =(PIMAGE_SECTION_HEADER)((DWORD)option_header32 + size_option_header);
	LPVOID temp_buffer = calloc(image32_size,1);


	memmove_s(temp_buffer, header32_size, *file_buffer, header32_size);

	DWORD foa=0;
	DWORD size_section_data=0;
	DWORD va=0;

	while (section_number--)
	{
		foa =section_header->PointerToRawData;
		size_section_data =section_header->SizeOfRawData;
		va =section_header->VirtualAddress;
	/*	if (foa==va)
		{
			continue;
		}*/
		memmove_s(LPVOID((DWORD)temp_buffer + va) , image32_size, LPVOID((DWORD)*file_buffer + foa), size_section_data);
		section_header++;
	}
	*image_buffer =temp_buffer;
	temp_buffer = NULL;
	free(temp_buffer);
	return image32_size;
}

//新增一个节表
DWORD addSectionHeader(IN LPVOID ImageBuffer,OUT LPVOID newImageBuffer) {
	if (ImageBuffer == NULL) {
		printf("未获取到有效数据\n");
		free(ImageBuffer);
		return 0;
	}

	//得到section表头,判断剩余空间是否够插入一个表头,如果不够,那么则将NT头前移,填充覆盖STUB,修改 DOS头指向





}

//打印目录项
//获取imagebuffer中的optionheader
DWORD TestPrintDirctory(IN LPVOID ImageBuffer) {
	if (ImageBuffer == NULL) {
		printf("未获取到有效数据\n");
		free(ImageBuffer);
		return 0;
	}
	//获取option头中的IMAGE_DATA_DIRECTORY_ARRAY DataDirArray

	PIMAGE_DOS_HEADER dos_header=(PIMAGE_DOS_HEADER)ImageBuffer;
	PIMAGE_NT_HEADERS NT_header =PIMAGE_NT_HEADERS(PDWORD((DWORD)dos_header->e_lfanew + (DWORD)ImageBuffer + 4 + IMAGE_SIZEOF_FILE_HEADER));
	DWORD number_of_rva_andsize=NT_header->OptionalHeader.NumberOfRvaAndSizes;


	PIMAGE_EXPORT_DIRECTORY export_directory;
	export_directory->AddressOfFunctions;
	PIMAGE_IMPORT_DESCRIPTOR ;


	for (int i = 0; i < number_of_rva_andsize; i++)
	{
		NT_header->OptionalHeader.DataDirectory[i];
		printf("%X",NT_header->OptionalHeader.DataDirectory[i]); ;
	}
	NT_header->OptionalHeader.DataDirectory[1].VirtualAddress;

}



VOID TestPrintNTHeaders(IN LPVOID ImageBuffer) {
	DWORD size = 0;
	//LPVOID pFileBuffer = nullptr;
	PIMAGE_DOS_HEADER pDosHeader = nullptr;
	PIMAGE_NT_HEADERS64 pNT64Header = nullptr;
	PIMAGE_NT_HEADERS32 pNT32Header = nullptr;
	PIMAGE_FILE_HEADER pFileHeader = nullptr;
	PIMAGE_OPTIONAL_HEADER32 pOption32Header = nullptr;
	PIMAGE_OPTIONAL_HEADER64 pOption64Header = nullptr;
	PIMAGE_SECTION_HEADER pSectionHeader = nullptr;

	if (!ImageBuffer)
	{
		printf("文件读取失败\n");
	}
	pDosHeader = (PIMAGE_DOS_HEADER)ImageBuffer;
	if ((*(PWORD)(pDosHeader)) != (IMAGE_DOS_SIGNATURE))
	{
		printf("非标准PE文件:%d\n", (*(PWORD)(pDosHeader)));
		free(ImageBuffer);
		return;
	}

	//判断是否为有效的PE标志
	if (* ( (PDWORD((DWORD)pDosHeader + pDosHeader->e_lfanew)   )) != (IMAGE_NT_SIGNATURE))
	{
		printf("非标准PE文件:%d\n", ((DWORD((PDWORD)ImageBuffer)) + (pDosHeader->e_lfanew)));
		free(ImageBuffer);
		return;
	}

	pFileHeader = (PIMAGE_FILE_HEADER)(DWORD((DWORD)pDosHeader + pDosHeader->e_lfanew + 4));
	pOption32Header = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileHeader+IMAGE_SIZEOF_FILE_HEADER);
	pSectionHeader = PIMAGE_SECTION_HEADER((DWORD)pOption32Header+pFileHeader->SizeOfOptionalHeader);


	//打印DOC头
	printf("************************DOC头******************************\n");
	printf("MZ标志:%04X\n", pDosHeader->e_magic);
	printf("PE偏移:%04X\n", pDosHeader->e_lfanew);
	printf("************************DOC头******************************\n");

	//打印file头
	printf("************************FILE头******************************\n");
	printf("机器类型:%04X\n", pFileHeader->Machine);
	printf("节的数量:%04d\n", pFileHeader->NumberOfSections);
	printf("编译时间:%08X\n", pFileHeader->TimeDateStamp);
	//printf("符号表信息:%d\n", pFileHeader->PointerToSymbolTable);
	//printf("符号数量:%d\n", pFileHeader->NumberOfSymbols);
	printf("可选头大小(size):%04X\n", pFileHeader->SizeOfOptionalHeader);
	printf("Characteristics:%04X\n", pFileHeader->Characteristics);

	printf("************************FILE头******************************\n");

	//打印optional头
	printf("************************OPTION头******************************\n");
	printf("机器位数:%04X\n", pOption32Header->Magic);
	//printf("链接器主要版本:%d\n", pOption32Header->MajorLinkerVersion);
	//printf("链接器次要版本:%d\n", pOption32Header->MinorLinkerVersion);
	printf("代码节的总大小:%08X\n", pOption32Header->SizeOfCode);
	printf("初始化数据节大小:%08X\n", pOption32Header->SizeOfInitializedData);
	printf("未初始化数据节大小:%08X\n", pOption32Header->SizeOfUninitializedData);
	printf("入口地址:%p\n", pOption32Header->AddressOfEntryPoint);
	printf("代码节相对于映像基地址的RVA:%08X\n", pOption32Header->BaseOfCode);
	printf("数据节相对于映像基地址的RVA:%08X\n", pOption32Header->BaseOfData);
	printf("内存中的基址:%08X\n", pOption32Header->ImageBase);
	printf("内存中节对齐大小:%08X\n", pOption32Header->SectionAlignment);
	printf("文件中节对齐大小:%08X\n", pOption32Header->FileAlignment);
	//printf("目标操作系统的版本:%d\n", pOption32Header->MajorOperatingSystemVersion);
	//printf("目标操作系统的版本:%d\n", pOption32Header->MinorOperatingSystemVersion);
	//printf("映像版本:%d\n", pOption32Header->MajorImageVersion);
	//printf("映像版本:%d\n", pOption32Header->MinorImageVersion);
	//printf("子系统的版本:%d\n", pOption32Header->MajorSubsystemVersion);
	//printf("子系统的版本:%d\n", pOption32Header->MinorSubsystemVersion);
	//printf("通常保留0:%d\n", pOption32Header->Win32VersionValue);
	printf("映像在内存的大小:%08X\n", pOption32Header->SizeOfImage);
	printf("文件头的大小:%08X\n", pOption32Header->SizeOfHeaders);
	printf("校验和:%08X\n", pOption32Header->CheckSum);
	printf("子系统类型:%04X\n", pOption32Header->Subsystem);
	printf("DllCharacteristics:%04X\n", pOption32Header->DllCharacteristics);
	printf("栈的预留大小:%08X\n", pOption32Header->SizeOfStackReserve);
	printf("栈的提交大小:%08X\n", pOption32Header->SizeOfStackCommit);
	printf("堆的预留大小:%08X\n", pOption32Header->SizeOfHeapReserve);
	printf("堆的提交大小:%08X\n", pOption32Header->SizeOfHeapCommit);
	//printf("保留使用:%d\n", pOption32Header->LoaderFlags);
	printf("dataDirectory[%08X]\n", pOption32Header->NumberOfRvaAndSizes);
	printf("************************OPENTION头******************************\n");
	//打印DOC头
	while ((pFileHeader->NumberOfSections)--)
	{
		/*char szBuffer[IMAGE_SIZEOF_SHORT_NAME];
		memset(szBuffer,0,9);
		memcpy_s(szBuffer,IMAGE_SIZEOF_SHORT_NAME,pSectionHeader->Name,IMAGE_SIZEOF_SHORT_NAME);*/
		printf("************************SECTION头******************************\n");
		printf("节名称:%s\n", pSectionHeader->Name);
		printf("节在内存占用大小:%08X\n", pSectionHeader->Misc.VirtualSize);
		printf("节在虚拟空间的起始地址:%08X\n", pSectionHeader->VirtualAddress);
		printf("原始数据大小:%08X\n", pSectionHeader->SizeOfRawData);
		printf("节在文件的地址:%08X\n", pSectionHeader->PointerToRawData);
		//printf("obj重定位表起始地址:%X\n", pSectionHeader->PointerToRelocations);
		//printf("源代码行号信息:%X\n", pSectionHeader->PointerToLinenumbers);
		//printf("obj 重定位条目数量:%X\n", pSectionHeader->NumberOfRelocations);
		//printf("行号条目数量:%X\n", pSectionHeader->NumberOfLinenumbers);
		printf("节Characteristics:%08X\n", pSectionHeader->Characteristics);
		printf("************************SECTION头******************************\n");
		pSectionHeader++;
	}
	TextPrintfExportTable(pOption32Header, ImageBuffer);
	TextPrintfRelocationTable(pOption32Header, ImageBuffer);

	//最后统一释放,不然容易遗漏,或多次释放。
	//free(pFileBuffer);
	return;
}

//打印导出表
void TextPrintfExportTable(PIMAGE_OPTIONAL_HEADER32 pOption32Header,LPVOID ImageBuffer) {

	if (!pOption32Header)
	{
		printf("未获取PE头\n"); 
		return;
	}

	const char* DirectoryEntryNames[] =
	{
		"EXPORT_TABLE",
		"IMPORT_TABLE",
		"RESOURCE_TABLE",
		"EXCEPTION_TABLE",
		"CERTIFICATE_TABLE",
		"BASE_RELOCATION_TABLE",
		"DEBUG",
		"COPYRIGHT_TABLE",
		"GLOBAL_PTR",
		"TLS_TABLE",
		"LOAD_CONFIG_TABLE",
		"BOUND_IMPORT",
		"IAT",
		"DELAY_IMPORT_DESCRIPTOR",
		"CLRRUNTIMEHEADER",
		"RESERVED"
	};
	//依次读取DataDirArray 目录中的address
	int i = 0;
	while ((pOption32Header->NumberOfRvaAndSizes)--)
	{
		printf("序号:%d、TbaleNAME:【%s】\t,VirtualAddress:【%08X】,Size:【%08X】\n",i, DirectoryEntryNames[i], pOption32Header->DataDirectory[i].VirtualAddress, pOption32Header->DataDirectory[i].Size);
		i++;
	}

	//pOption32Header->DataDirectory[0].VirtualAddress;
	printf("====================================EXPORT TABLE=======================================\n");
	PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;
	pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((pOption32Header->DataDirectory[0].VirtualAddress)+ (DWORD)ImageBuffer);
	printf("Characteristics:【%08X】\n", pExportDirectory->Characteristics);
	printf("TimeDateStamp:【%08X】\n", pExportDirectory->TimeDateStamp);
	printf("MajorVersion:【%04X】\n", pExportDirectory->MajorVersion);
	printf("MinorVersion:【%04X】\n", pExportDirectory->MinorVersion);
	printf("Name:【%08X】\n", pExportDirectory->Name);
	printf("Base:【%08X】\n", pExportDirectory->Base);
	printf("NumberOfFunctions:【%08X】\n", pExportDirectory->NumberOfFunctions);
	printf("NumberOfNames:【%08X】\n", pExportDirectory->NumberOfNames);
	printf("AddressOfFunctions:【%08X】\n", pExportDirectory->AddressOfFunctions);
	printf("AddressOfNames:【%08X】\n", pExportDirectory->AddressOfNames);
	printf("AddressOfNameOrdinals:【%08X】\n", pExportDirectory->AddressOfNameOrdinals);
	
	printf("====================================EXPORT TABLE=======================================\n");
}

/*
获取重定位表
*/
void TextPrintfRelocationTable(PIMAGE_OPTIONAL_HEADER32 pOption32Header, LPVOID ImageBuffer) {
	if (!pOption32Header) {
		printf("未获取PE头\n");
		return;
	}

	printf("====================================RELOCATION TABLE=======================================\n");
	//得到当前重定位表位置
	PIMAGE_BASE_RELOCATION pRelocationDirectory = (PIMAGE_BASE_RELOCATION)((DWORD)ImageBuffer + pOption32Header->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
	DWORD i = 1;
	//循环遍历重定位表
	while (pRelocationDirectory->SizeOfBlock > 0) {
		printf("第%d项:地址:%08X, SizeOfBlock: %08X\n", i++, pRelocationDirectory->VirtualAddress, pRelocationDirectory->SizeOfBlock);

		//计算重定位条目的起始位置
		PWORD pwRelocationEntries = (PWORD)((uintptr_t)pRelocationDirectory + sizeof(IMAGE_BASE_RELOCATION));
		//计算有多少个重定位条目
		WORD NumberOfRelocationEntries = (pRelocationDirectory->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);

		//循环重定位条目,分解重定位条目
		for (DWORD j = 0; j < NumberOfRelocationEntries; j++) {
			WORD wRelocationEntry = pwRelocationEntries[j];
			//属性
			DWORD dwRelocationType = (wRelocationEntry >> 12) & 0xF;
			//地址
			DWORD dwRelocationAddress = wRelocationEntry & 0xFFF;

			printf("    地址:%04X, 属性:0x%04X\n", pRelocationDirectory->VirtualAddress + dwRelocationAddress, dwRelocationType);
		}
		//移动到下一个重定位块。
		pRelocationDirectory = (PIMAGE_BASE_RELOCATION)((uintptr_t)pRelocationDirectory + pRelocationDirectory->SizeOfBlock);
	}

	printf("====================================RELOCATION TABLE=======================================\n");
}


int  main() {
	LPVOID file_buffer = NULL;
	LPVOID image_buffer = NULL;
	read_file("C:\\Windows\\twain_32.dll", &file_buffer);

	FileBufferToImageBuffer(&file_buffer,&image_buffer);
	TestPrintNTHeaders(image_buffer);

	free(file_buffer);
	free(image_buffer);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值