滴水逆向——PE导出表

Ⅰ.知识点:

1.如何定位导出表:    
    数据目录项的第一个结构,就是导出表.   
    typedef struct _IMAGE_DATA_DIRECTORY {  
    DWORD   VirtualAddress;   
    DWORD   Size;     
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;  
    VirtualAddress  导出表的RVA   
    Size 导出表大小      

2.导出表结构     
    上面的结构,只是说明导出表在哪里,有多大,并不是真正的导出表.
    如何在FileBuffer中找到这个结构呢?在VirtualAddress中存储的是RVA,如果想在FileBuffer中定位
    必须要先将该RVA转换成FOA.    
    真正的导出表结构如下:    

3.AddressOfFunctions说明:   
    该表中元素宽度为4个字节    
    该表中存储所有导出函数的地址   
    该表中个数由NumberOfFunctions决定   
    该表项中的值是RVA, 加上ImageBase才是函数真正的地址  
    定位:      
    IMAGE_EXPORT_DIRECTORY->AddressOfFunctions 中存储的是该表的RVA 需要先转换成FOA

4.AddressOfNames说明:    
    该表中元素宽度为4个字节    
    该表中存储所有以名字导出函数的名字的RVA  
    该表项中的值是RVA, 指向函数真正的名称  

5.AddressOfNameOrdinals

Ⅱ.关键点:       
       为什么要分成3张表?     
       1、函数导出的个数与函数名的个数未必一样.所以要将函数地址表和函数名称表分开.
       2、函数地址表是不是一定大于函数名称表?   
       未必,一个相同的函数地址,可能有多个不同的名字.  
       3、如何根据函数的名字获取一个函数的地址?   

扫描二维码关注公众号,回复: 10777606 查看本文章

Ⅲ.问题描述:

  打印导出表

  根据函数的导出序号获取一个函数的地址

Ⅳ.代码实现:

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#define size_shellcode 0x12
#define size_surplus_sizeofheader 0x50
#define messagebox_add 0x76EE2030  

#define test 1

DWORD ToLeaderPE(LPSTR file_path, PVOID* pFileBuffer);
VOID ReadPEFile(IN LPVOID pFileBuffer);
DWORD CopyFileBufferToImageBuffer(PVOID pFileBuffer, PVOID* pImageBuffer);
DWORD CopyImageBufferToNewBuffer(PVOID pImageBuffer, PVOID* pNewBuffer);
BOOL MemeryTOFile(IN LPVOID pMemBuffer, IN size_t size, OUT LPSTR lpszFile);
DWORD TestAddCodeInDataSec(PVOID pImageBuffer, PVOID* pNewFileBuffer, DWORD FileSize);
DWORD TestAddCodeInXXXSec(PVOID pImageBuffer, PVOID* pNewFileBuffer, DWORD SecNumb, DWORD FileSize);
DWORD RvaToFileOffset(IN LPVOID pBuffer, IN DWORD dwRva);
DWORD FoaToImageOffset(IN LPVOID pBuffer, IN DWORD dwFoa);
DWORD TestAddSection(IN LPVOID file_path, IN LPVOID* pFileBuffer, IN LPVOID* pAddSectionBuffer);
DWORD TestEnlargeSection(IN LPVOID* pFileBuffer, IN LPVOID* pEnlargerSection);
DWORD TestMergeSection(IN LPVOID* pFileBuffer, IN LPVOID* pEnlargerSection);
DWORD Alignment(DWORD alignment_value, DWORD addend, DWORD address);
DWORD GetFunctionAddrByName(PVOID pFileBuffer, LPSTR fun_name);
DWORD GetFunctionAddrByOrdinals(PVOID pFileBuffer, DWORD fun_order);

BYTE shellcode[] = {
	0x6A,00,0x6A,00,0x6A,00,0x6A,00,
	0XE8,00,00,00,00,
	0XE9,00,00,00,00
};

char fun_name[] = "??4CInitGdiplus@wui@@QAEAAV01@ABV01@@Z";
char file_path[] = "d:\\vmware\\vmware.exe";
char write_file_path[] = "D:\\Lib\\cp_XX.exe";
char write_adddata_file_path[] = "D:\\Lib\\cp_adddata_XX.exe";
char write_addXXXsec_file_path[] = "D:\\Lib\\cp_addXXXsec_XX.exe";
char write_addsec_file_path[] = "D:\\Lib\\cp_addsec_XX.exe";
char write_enlargersec_file_path[] = "D:\\Lib\\cp_enlargersec_XX.exe";
char write_mergesec_file_path[] = "D:\\Lib\\cp_mergesec_XX.exe";

DWORD ToLeaderPE(LPSTR file_path, PVOID* pFileBuffer)
{
	FILE *pFile = NULL;
	DWORD fileSize = 0;
	LPVOID pFileBufferTemp = NULL;

	pFile = fopen(file_path, "rb");

	if (!pFile)
	{
		printf("can't open file1\n");
		return 0;
	}

	fseek(pFile, 0, SEEK_END);
	fileSize = ftell(pFile);
	printf("FileBuffer: %x\n", fileSize);
	fseek(pFile, 0, SEEK_SET);
	pFileBufferTemp = malloc(fileSize);

	if (!pFileBufferTemp)
	{
		printf("apply memory failed\n");
		fclose(pFile);
		return 0;
	}

	size_t n = fread(pFileBufferTemp, fileSize, 1, pFile);

	if (!n)
	{
		printf("read data filed\n");
		free(pFileBufferTemp);
		fclose(pFile);
		return 0;
	}
	*pFileBuffer = pFileBufferTemp;
	pFileBufferTemp = NULL;
	fclose(pFile);
	return fileSize;
}

VOID ReadPEFile(IN LPVOID pFileBuffer)
{
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNTHeader = NULL;
	PIMAGE_FILE_HEADER pPEHeader = NULL;
	PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader = NULL;

	if (!pFileBuffer)
	{
		printf("文件读取失败\n");
		return;
	}

	//判断是否是有效的MZ标志	
	if (*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE)
	{
		printf("不是有效的MZ标志\n");
		free(pFileBuffer);
		return;
	}
	pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
	//打印DOC头	
	printf("\n********************DOS头********************\n");
	printf("MZ标志:%x\n", pDosHeader->e_magic);
	printf("PE偏移:%x\n", pDosHeader->e_lfanew);
	//判断是否是有效的PE标志	
	if (*((PDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
	{
		printf("不是有效的PE标志\n");
		free(pFileBuffer);
		return;
	}
	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
	//打印NT头	
	printf("********************NT头********************\n");
	printf("NT:%x\n", pNTHeader->Signature);
	pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader) + 4);

	//int NumberOfSections = pPEHeader->NumberOfSections;
	//int SizeOfOptionalHeader = pPEHeader->SizeOfOptionalHeader;

	printf("********************PE头********************\n");
	printf("PE:%x\n", pPEHeader->Machine);
	printf("节的数量:%x\n", pPEHeader->NumberOfSections);
	printf("SizeOfOptionalHeader:%x\n", pPEHeader->SizeOfOptionalHeader);
	//可选PE头	
	pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
	printf("********************OPTIOIN_PE头********************\n");
	printf("OPTION_PE:%x\n", pOptionHeader->Magic);

	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);

	for (int n = 0; n < pPEHeader->NumberOfSections; n++)
	{
		printf("********************SECTION %d********************\n", n + 1);
		char name[9] = { 0 };
		memcpy(name, pSectionHeader->Name, 8);
		printf("SECTION NAME: %s\n", name);
		printf("VirtualAddress: %x\n", pSectionHeader->VirtualAddress);
		printf("SizeOfRawData: %x\n", pSectionHeader->SizeOfRawData);
		printf("PointerToRawData: %x\n", pSectionHeader->PointerToRawData);
		printf("Characteristics: %x\n", pSectionHeader->Characteristics);
		pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader + IMAGE_SIZEOF_SECTION_HEADER);
	}
}





BOOL MemeryTOFile(IN LPVOID pMemBuffer, IN size_t size, OUT LPSTR lpszFile)
{
	FILE *fp;
	fp = fopen(lpszFile, "wb");
	if (fp != NULL)
	{
		fwrite(pMemBuffer, size, 1, fp);
	}
	fclose(fp);
	return 1;
}

DWORD RvaToFileOffset(IN LPVOID pBuffer, IN DWORD dwRva)
{
	// 初始化PE头部结构体
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNTHeader = NULL;
	PIMAGE_FILE_HEADER pPEHeader = NULL;
	PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader = NULL;

	// 判断pImageBuffer是否有效
	if (!pBuffer)
	{
		printf("(RVA转换成FOA阶段)读取到内存的ImageBuffer无效!\n");
		return 0;
	}
	//判断是不是exe文件
	if (*((PWORD)pBuffer) != IMAGE_DOS_SIGNATURE)
	{
		printf("(RVA转换成FOA阶段)不含MZ标志,不是exe文件!\n");
		return 0;
	}
	// 强制结构体类型转换
	pDosHeader = (PIMAGE_DOS_HEADER)pBuffer;
	if (*((PDWORD)((DWORD)pBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
	{
		printf("(RVA转换成FOA阶段)不是有效的PE标志!\n");
		return 0;
	}

	//printf("The Rva to convert is: %x\n", dwRva);
	// 强制结构体类型转换
	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pBuffer + pDosHeader->e_lfanew);
	pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4); // 这里必须强制类型转换
	pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);

	PIMAGE_SECTION_HEADER pSectionTemp = pSectionHeader;

	if (dwRva <= pOptionHeader->SizeOfHeaders)
		return (DWORD)dwRva;
	else
	{
		for (int n = 0; n < pPEHeader->NumberOfSections; n++, pSectionTemp++)
		{	//判断 :   文件对齐+文件偏移>file_panyi>文件偏移  (即是在文件的哪个节中)
			if ((dwRva >= pSectionTemp->VirtualAddress) && (dwRva < pSectionTemp->VirtualAddress + pSectionTemp->Misc.VirtualSize))
			{
				return dwRva - pSectionTemp->VirtualAddress + pSectionTemp->PointerToRawData;
			}
		}
	}
	printf("地址转换失败!\n");
	return 0;
}

DWORD FoaToImageOffset(IN LPVOID pBuffer, IN DWORD dwFoa)
{
	// 初始化PE头部结构体
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNTHeader = NULL;
	PIMAGE_FILE_HEADER pPEHeader = NULL;
	PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader = NULL;

	// 判断pImageBuffer是否有效
	if (!pBuffer)
	{
		printf("(FOA转换RVA成阶段)读取到内存的ImageBuffer无效!\n");
		return 0;
	}
	//判断是不是exe文件
	if (*((PWORD)pBuffer) != IMAGE_DOS_SIGNATURE)
	{
		printf("(FOA转换RVA成阶段)不含MZ标志,不是exe文件!\n");
		return 0;
	}
	// 强制结构体类型转换
	pDosHeader = (PIMAGE_DOS_HEADER)pBuffer;
	if (*((PDWORD)((DWORD)pBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
	{
		printf("(FOA转换RVA成阶段)不是有效的PE标志!\n");
		return 0;
	}
	printf("FileOffset: %x\n", dwFoa);

	// 强制结构体类型转换
	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pBuffer + pDosHeader->e_lfanew);
	pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4); // 这里必须强制类型转换
	pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);

	PIMAGE_SECTION_HEADER pSectionTemp = pSectionHeader;

	if (dwFoa <= pOptionHeader->SizeOfHeaders)
		return (DWORD)dwFoa;
	else
	{
		for (int n = 0; n < pPEHeader->NumberOfSections; n++, pSectionTemp++)
		{	//判断 :   文件对齐+文件偏移>file_panyi>文件偏移  (即是在文件的哪个节中)
			if ((dwFoa >= pSectionTemp->PointerToRawData) && (dwFoa < pSectionTemp->PointerToRawData + pSectionTemp->SizeOfRawData))
			{
				return dwFoa - pSectionTemp->PointerToRawData + pSectionTemp->VirtualAddress;
			}
		}
	}
	printf("地址转换失败!\n");
	return 0;
}


DWORD Alignment(DWORD alignment_value, DWORD addend, DWORD address)
{
	int n = 0;
	if (addend / alignment_value)
	{
		if (addend%alignment_value)
		{
			n = addend / alignment_value + 1;
		}
		else
		{
			n = addend / alignment_value;
		}
	}
	else
	{
		if (addend)
			n = 0;
		else
			n = 1;
	}
	address += n * alignment_value;
	return address;
}


VOID LogExportDirectory(IN LPVOID pFileBuffer)
{
	// 初始化PE头部结构体
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNTHeader = NULL;
	PIMAGE_FILE_HEADER pPEHeader = NULL;
	PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader = NULL;
	PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;


	// 判断pImageBuffer是否有效
	if (!pFileBuffer)
	{
		printf("(LogExportDirectory)读取到内存的ImageBuffer无效!\n");
		return 0;
	}
	//判断是不是exe文件
	if (*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE)
	{
		printf("(LogExportDirectory)不含MZ标志,不是exe文件!\n");
		return 0;
	}
	// 强制结构体类型转换
	pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
	if (*((PDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
	{
		printf("(LogExportDirectory)不是有效的PE标志!\n");
		return 0;
	}

	// 强制结构体类型转换
	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
	pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4); // 这里必须强制类型转换
	pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);

	if (!pOptionHeader->DataDirectory->VirtualAddress)
	{
		printf("This program has no export table.\n");
		return 0;
	}

	printf("Export Table Rva: %x\n", pOptionHeader->DataDirectory->VirtualAddress);

	DWORD Foa_ExportTable = RvaToFileOffset(pFileBuffer, pOptionHeader->DataDirectory->VirtualAddress);

	printf("Export Table Foa: %x\n", Foa_ExportTable);

	pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pFileBuffer+Foa_ExportTable);

	printf("Characteristics: %x\n", pExportDirectory->Characteristics);
	printf("TimeDateStamp: %x\n", pExportDirectory->TimeDateStamp);
	printf("MajorVersion: %x\n", pExportDirectory->MajorVersion);
	printf("MinorVersion: %x\n", pExportDirectory->MinorVersion);
	printf("Name: %x\n", pExportDirectory->Name);
	printf("Base: %x\n", pExportDirectory->Base);
	printf("NumberOfFunctions: %x\n", pExportDirectory->NumberOfFunctions);
	printf("NumberOfNames: %x\n", pExportDirectory->NumberOfNames);
	printf("AddressOfFunctions: %x\n", pExportDirectory->AddressOfFunctions);
	printf("AddressOfNames: %x\n", pExportDirectory->AddressOfNames);
	printf("AddressOfNameOrdinals: %x\n", pExportDirectory->AddressOfNameOrdinals);
}

DWORD GetFunctionAddrByOrdinals(PVOID pFileBuffer, DWORD fun_order)
{
	printf("Function Order: %x\n", fun_order);
	// 初始化PE头部结构体
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNTHeader = NULL;
	PIMAGE_FILE_HEADER pPEHeader = NULL;
	PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader = NULL;
	PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
	PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;

	// 判断pImageBuffer是否有效
	if (!pFileBuffer)
	{
		printf("(LogExportDirectory)读取到内存的ImageBuffer无效!\n");
		return 0;
	}
	//判断是不是exe文件
	if (*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE)
	{
		printf("(LogExportDirectory)不含MZ标志,不是exe文件!\n");
		return 0;
	}
	// 强制结构体类型转换
	pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
	if (*((PDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
	{
		printf("(LogExportDirectory)不是有效的PE标志!\n");
		return 0;
	}

	// 强制结构体类型转换
	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
	pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4); // 这里必须强制类型转换
	pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
	pDataDirectory = (PIMAGE_DATA_DIRECTORY)pOptionHeader->DataDirectory;

	if (!pDataDirectory->VirtualAddress)
	{
		printf("This program has no export table.\n");
		return 0;
	}

	printf("Export Table Rva: %x\n", pDataDirectory->VirtualAddress);

	DWORD Foa_ExportTable = RvaToFileOffset(pFileBuffer, pDataDirectory->VirtualAddress);

	printf("Export Table Foa: %x\n", Foa_ExportTable);

	pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pFileBuffer + Foa_ExportTable);

	if (!test)
	{
		printf("Characteristics: %x\n", pExportDirectory->Characteristics);
		printf("TimeDateStamp: %x\n", pExportDirectory->TimeDateStamp);
		printf("MajorVersion: %x\n", pExportDirectory->MajorVersion);
		printf("MinorVersion: %x\n", pExportDirectory->MinorVersion);
		printf("Name: %x\n", pExportDirectory->Name);
		printf("Base: %x\n", pExportDirectory->Base);
		printf("NumberOfFunctions: %x\n", pExportDirectory->NumberOfFunctions);
		printf("NumberOfNames: %x\n", pExportDirectory->NumberOfNames);
		printf("AddressOfFunctions: %x\n", pExportDirectory->AddressOfFunctions);
		printf("AddressOfNames: %x\n", pExportDirectory->AddressOfNames);
		printf("AddressOfNameOrdinals: %x\n", pExportDirectory->AddressOfNameOrdinals);
	}	

	DWORD Sequence = fun_order - pExportDirectory->Base;
	DWORD Foa_AddressOfFunctions = RvaToFileOffset(pFileBuffer, pExportDirectory->AddressOfFunctions);

	if (!test)
	{
		DWORD test1 = Foa_AddressOfFunctions + (DWORD)pFileBuffer;
		printf("AddressOfFunctions in this moment: %x\n", test1);
		printf("Foa_AddressOfFunctions: %x\n", Foa_AddressOfFunctions);
	}

	PDWORD pFoa_AddressOfFunctions = (PBYTE)(Foa_AddressOfFunctions + (DWORD)pFileBuffer);

	for (DWORD n = 0; n < Sequence; n++)
	{
		pFoa_AddressOfFunctions++;
	}
	DWORD Foa_AddrFun = RvaToFileOffset(pFileBuffer, *pFoa_AddressOfFunctions);

	return Foa_AddrFun;
}

DWORD GetFunctionAddrByName(PVOID pFileBuffer, LPSTR fun_name)
{
	printf("Function Name: %s\n", fun_name);
	// 初始化PE头部结构体
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNTHeader = NULL;
	PIMAGE_FILE_HEADER pPEHeader = NULL;
	PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader = NULL;
	PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
	PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;

	// 判断pImageBuffer是否有效
	if (!pFileBuffer)
	{
		printf("(LogExportDirectory)读取到内存的ImageBuffer无效!\n");
		return 0;
	}
	//判断是不是exe文件
	if (*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE)
	{
		printf("(LogExportDirectory)不含MZ标志,不是exe文件!\n");
		return 0;
	}
	// 强制结构体类型转换
	pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
	if (*((PDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
	{
		printf("(LogExportDirectory)不是有效的PE标志!\n");
		return 0;
	}

	// 强制结构体类型转换
	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
	pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4); // 这里必须强制类型转换
	pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
	pDataDirectory = (PIMAGE_DATA_DIRECTORY)pOptionHeader->DataDirectory;

	if (!pDataDirectory->VirtualAddress)
	{
		printf("This program has no export table.\n");
		return 0;
	}

	printf("Export Table Rva: %x\n", pDataDirectory->VirtualAddress);

	DWORD Foa_ExportTable = RvaToFileOffset(pFileBuffer, pDataDirectory->VirtualAddress);

	printf("Export Table Foa: %x\n", Foa_ExportTable);

	pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pFileBuffer + Foa_ExportTable);

	if (!test)
	{
		printf("Characteristics: %x\n", pExportDirectory->Characteristics);
		printf("TimeDateStamp: %x\n", pExportDirectory->TimeDateStamp);
		printf("MajorVersion: %x\n", pExportDirectory->MajorVersion);
		printf("MinorVersion: %x\n", pExportDirectory->MinorVersion);
		printf("Name: %x\n", pExportDirectory->Name);
		printf("Base: %x\n", pExportDirectory->Base);
		printf("NumberOfFunctions: %x\n", pExportDirectory->NumberOfFunctions);
		printf("NumberOfNames: %x\n", pExportDirectory->NumberOfNames);
		printf("AddressOfFunctions: %x\n", pExportDirectory->AddressOfFunctions);
		printf("AddressOfNames: %x\n", pExportDirectory->AddressOfNames);
		printf("AddressOfNameOrdinals: %x\n", pExportDirectory->AddressOfNameOrdinals);
	}

	DWORD Foa_AddressOfNames = RvaToFileOffset(pFileBuffer, pExportDirectory->AddressOfNames);
	DWORD Foa_AddressOfNameOrdinals = RvaToFileOffset(pFileBuffer, pExportDirectory->AddressOfNameOrdinals);
	DWORD Foa_AddressOfFunctions = RvaToFileOffset(pFileBuffer, pExportDirectory->AddressOfFunctions);


	if (!test)
	{
		DWORD test1 = Foa_AddressOfNames + (DWORD)pFileBuffer;
		printf("AddressOfNames in this moment: %x\n", test1);
		printf("Foa__AddressOfNames: %x\n", Foa_AddressOfNames);
	}

	//1.循环从名字表中找与目标函数名相同的;如有有返回该名字在表中的索引
	DWORD ordIndex = -1;
	for (DWORD i = 0; i < pExportDirectory->NumberOfNames; i++)
	{
		DWORD nameOffset = *(PDWORD)((DWORD)pFileBuffer + (DWORD)((LPDWORD)Foa_AddressOfNames + i));
		LPSTR nameAddr = (LPSTR)((DWORD)pFileBuffer + RvaToFileOffset(pFileBuffer, nameOffset));
		if (!strcmp(nameAddr, fun_name))
		{
			ordIndex = i;
			break;
		}
	}
	if (ordIndex == -1)
	{
		printf("The export table does not have this function name.\n");
		return 0;
	}
	
	//2.用获得的索引从序号表中找函数的序号
	WORD ord = *(PWORD)((DWORD)pFileBuffer + (DWORD)((LPWORD)Foa_AddressOfNameOrdinals + ordIndex));

	if (!test)
	{
		DWORD test1 = Foa_AddressOfNameOrdinals + (DWORD)pFileBuffer;
		printf("AddressOfNameOrdinals in this moment: %x\n", test1);
		printf("Foa__AddressOfNameOrdinals: %x\n", Foa_AddressOfNameOrdinals);
		printf("ordInex in AddressOfNames: %x\n", ordIndex);
		printf("ordInex in AddressOfNameOrdinals: %x\n", ord);
	}

	//3.以序号表中查出来的序号为索引从函数地址表中找函数地址
	DWORD addr = *(PDWORD)((DWORD)pFileBuffer + (DWORD)((LPDWORD)Foa_AddressOfFunctions + ord));
	DWORD Foa_AddrFun = RvaToFileOffset(pFileBuffer, addr);

	return Foa_AddrFun;
}

int main()
{

	LPVOID pFileBuffer = NULL;
	LPVOID pNewFileBuffer = NULL;
	LPVOID pImageBuffer = NULL;
	LPVOID pAddSectionBuffer = NULL;
	LPVOID pEnlargerSection = NULL;
	LPVOID pMergeSection = NULL;
	size_t pRVA = 0x0003123;
	size_t pFOA = 0x00020450;

	size_t ret1 = ToLeaderPE(file_path, &pFileBuffer);  // &pFileBuffer(void**类型) 传递地址对其值可以进行修改
	printf("exe->filebuffer  返回值为计算所得文件大小:%#x\n", ret1);
	
	//LogExportDirectory(pFileBuffer);
	//size_t ret8 = GetFunctionAddrByOrdinals(pFileBuffer, 1);
	//printf("GetFunctionAddr is %x\n", ret8);

	size_t ret9 = GetFunctionAddrByName(pFileBuffer, fun_name);
	printf("GetFunctionAddr is %x\n", ret9);

	free(pFileBuffer);
	free(pNewFileBuffer);
	free(pImageBuffer);

	return 0;
}

Ⅴ.结果展示:

发布了13 篇原创文章 · 获赞 2 · 访问量 402

猜你喜欢

转载自blog.csdn.net/z17805008775/article/details/105442416