DWORD copyBaseRelocation2NewSection(IN PVOID pFileBuffer,OUT PVOID* pNewFileBuffer)
{
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("FileBuffer无效!\n");
free(pFileBuffer);
return;
}
if(*(PWORD)pFileBuffer != IMAGE_DOS_SIGNATURE)
{
printf("不是有效的PE文件\n");
free(pFileBuffer);
return;
}
//新增节表
PVOID pTemOfNewFileBuffer = NULL;
DWORD sizeOfNewBuffer = AddNewSection(pFileBuffer, &pTemOfNewFileBuffer);
free(pFileBuffer);
if(!pTemOfNewFileBuffer)
{
printf("新节表添加失败!\n");
return;
}
if(*(PWORD)pTemOfNewFileBuffer != IMAGE_DOS_SIGNATURE)
{
printf("不是有效的PE文件\n");
free(pTemOfNewFileBuffer);
return;
}
pDosHeader = (PIMAGE_DOS_HEADER)pTemOfNewFileBuffer;
pNTHeader = (PIMAGE_NT_HEADERS)(pDosHeader + pDosHeader->e_lfanew);
pPEHeader = (PIMAGE_FILE_HEADER)(pNTHeader + 4);
pOptionHeader = (PIMAGE_OPTIONAL_HEADER)(pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader = (PIMAGE_SECTION_HEADER)(pOptionHeader + pPEHeader->SizeOfOptionalHeader);
//定位数据目录
PIMAGE_DATA_DIRECTORY pDataDirectory = pOptionHeader->DataDirectory;
//获取数据目录数组中的第6个结构,重定位表,记录重定位数据块的RVA和Size(没用)
DWORD RVAOfBaseRelocationDataDirectory = pDataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
//RVA转FOA找到第一个重定位数据块
DWORD FOAOfBaseRelocation = RVA2FOA(pTemOfNewFileBuffer,RVAOfBaseRelocationDataDirectory);
PIMAGE_BASE_RELOCATION pBASERELOCATION = (PIMAGE_BASE_RELOCATION)FOAOfBaseRelocation;
//复制
//定义pLastSection--新节在拉伸后的内存(pTemOfNewFileBuffer)中的地址
PDWORD pLastSection = (PDWORD)((DWORD)pTemOfNewFileBuffer + (pSectionHeader + pPEHeader->NumberOfSections)->PointerToRawData);
//循环复制重定位数据块到新节,结束条件是最后一个结构的VirtualAddress与SizeOfBlock都为0
PIMAGE_BASE_RELOCATION pTemOfBASERELOCATION = pBASERELOCATION;
while(*(pTemOfBASERELOCATION)->VirtualAddress != 0 && *(pTemOfBASERELOCATION)->SizeOfBlock != 0)
{
memcpy(pLastSection,pBASERELOCATION,pTemOfBASERELOCATION->SizeOfBlock);
pLastSection = (PDWORD)((DWORD)pLastSection + pTemOfBASERELOCATION->SizeOfBlock);
pTemOfBASERELOCATION = (PIMAGE_BASE_RELOCATION)((DWORD)pTemOfBASERELOCATION + pTemOfBASERELOCATION->SizeOfBlock) ;
}
//修复,使重定位表指向的重定位数据块的新RVA,也就是新节的RVA,要把FOA转为RVA
pDataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = pOptionHeader->ImageBase + (pSectionHeader + pPEHeader->NumberOfSections)->PointerToRawData;
//结束返回pNewFileBuffer,sizeOfNewBuffer
pNewFileBuffer = pTemOfNewFileBuffer;
pTemOfNewFileBuffer = NULL;
free(pFileBuffer);
return sizeOfNewBuffer;
}
