1.程序加载过程:
2.重定位表:
3.代码实现:
#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);
VOID LogExportDirectory(IN LPVOID pFileBuffer);
DWORD GetFunctionAddrByName(PVOID pFileBuffer, LPSTR fun_name);
DWORD GetFunctionAddrByOrdinals(PVOID pFileBuffer, DWORD fun_order);
VOID LogBaseRelocationTable(IN LPVOID pFileBuffer);
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:\\tim\\bin\\qqsclauncher.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_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);
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;
}
VOID LogBaseRelocationTable(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_DATA_DIRECTORY pDataDirectory = NULL;
PIMAGE_BASE_RELOCATION pRelocationTable = NULL;
// 判断pImageBuffer是否有效
if (!pFileBuffer)
{
printf("(LogBaseRelocationTable)读取到内存的ImageBuffer无效!\n");
return 0;
}
//判断是不是exe文件
if (*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE)
{
printf("LogBaseRelocationTable)不含MZ标志,不是exe文件!\n");
return 0;
}
// 强制结构体类型转换
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
if (*((PDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
{
printf("(LogBaseRelocationTable)不是有效的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;
PIMAGE_DATA_DIRECTORY pDataDirectory_RelocTable = pDataDirectory + 5;
if (!pDataDirectory_RelocTable->VirtualAddress)
{
printf("This program has no relocation table.\n");
return 0;
}
DWORD Foa_RelocationTable = RvaToFileOffset(pFileBuffer, pDataDirectory_RelocTable->VirtualAddress);
if (!test)
{
printf("Relocation Table Rva: %x\n", pDataDirectory_RelocTable->VirtualAddress);
printf("Relocation Table Foa: %x\n", Foa_RelocationTable);
printf("pFileBuffer: %x\n", (DWORD)pFileBuffer);
printf("Relocation Table in this moment: %x\n", (DWORD)pFileBuffer + Foa_RelocationTable);
}
pRelocationTable = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pFileBuffer + Foa_RelocationTable);
printf("pRelocationTable: %x\n", (DWORD)pRelocationTable);
for (DWORD n = 0; pRelocationTable->VirtualAddress != IMAGE_REL_BASED_ABSOLUTE; n++)
{
printf(".....................RelocationTable %5xth.................................\n", n+1);
DWORD arrNumber = (pRelocationTable->SizeOfBlock - 8) / 2;
printf("TypeOffset Number: %x\n", arrNumber);
PDWORD pTypeOffsetOrg = ((PDWORD)pRelocationTable + 2);
PWORD pTypeOffset = (PWORD)pTypeOffsetOrg;
for (DWORD i = 0; i < arrNumber; i++)
{
printf("pTypeOffset: %-10x", (WORD)pTypeOffset);
WORD TypeOffset = *pTypeOffset;
if (!test)
{
printf("TypeOffset(011) = %x\n", TypeOffset);
}
BYTE attribute = (TypeOffset & 0b11000000000000) >> 12;
TypeOffset = (TypeOffset&0b111111111111);
if (!test)
{
printf("TypeOffset(000) = %x\n", TypeOffset);
}
printf("Attribute: %-5x", attribute);
DWORD Offset = pRelocationTable->VirtualAddress + (DWORD)TypeOffset;
printf("Rva_BaseRelocation: %-10x", Offset);
printf("Foa_BaseRelocation: %-10x\n", RvaToFileOffset(pFileBuffer, Offset));
pTypeOffset++;
}
pRelocationTable = (PDWORD)((DWORD)pRelocationTable + pRelocationTable->SizeOfBlock);
}
}
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);
LogBaseRelocationTable(pFileBuffer);
free(pFileBuffer);
free(pNewFileBuffer);
free(pImageBuffer);
return 0;
}
4.结果展示: