要写这几个函数会频繁用到FOA转VA
//文件里的偏移转化为内存偏移
DWORD FOAToVA(DWORD FOA, PVOID pFileBuffer) {
PIMAGE_DOS_HEADER pDosHeader = pFileBuffer;
PIMAGE_NT_HEADERS pNTHeader = (DWORD)pDosHeader + pDosHeader->e_lfanew;
if (pNTHeader->Signature != IMAGE_NT_SIGNATURE) {
printf("File is not PE\n");
free(pFileBuffer);
return FALSE;
}
PIMAGE_FILE_HEADER pFileHeader = &pNTHeader->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptHeader = (DWORD)pFileHeader + sizeof(IMAGE_FILE_HEADER);
PIMAGE_SECTION_HEADER pSecHeader = (DWORD)pOptHeader + pFileHeader->SizeOfOptionalHeader;
if (FOA < pSecHeader->PointerToRawData) {
return FOA + (DWORD)pFileBuffer;
}
for (size_t i = 0; i < pFileHeader->NumberOfSections; i++) {
if (FOA >= pSecHeader->PointerToRawData && FOA < (pSecHeader->PointerToRawData + pSecHeader->SizeOfRawData)) {
return pSecHeader->VirtualAddress + (FOA - pSecHeader->PointerToRawData);
}
pSecHeader++;
}
return 0;
}
//移动导出表
BOOL MoveExportTable(PVOID fileName,PVOID newFileName) {
if (!IncreaseSection(fileName)) {
printf("Increase section failed\n");
return FALSE;
}
PVOID pFileBuffer = FileToFileBuffer(newFileName);
//定位导出表
PIMAGE_DOS_HEADER pDosHeader = pFileBuffer;
PIMAGE_NT_HEADERS pNTHeader = (DWORD)pDosHeader + pDosHeader->e_lfanew;
if (pNTHeader->Signature != IMAGE_NT_SIGNATURE) {
printf("File is not PE\n");
free(pFileBuffer);
return FALSE;
}
PIMAGE_FILE_HEADER pFileHeader = &pNTHeader->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptHeader = (DWORD)pFileHeader + sizeof(IMAGE_FILE_HEADER);
PIMAGE_SECTION_HEADER pSecHeader = (DWORD)pOptHeader + pFileHeader->SizeOfOptionalHeader;
PIMAGE_SECTION_HEADER pLastSecHeader = pSecHeader + pFileHeader->NumberOfSections - 1;
if (pOptHeader->DataDirectory[0].VirtualAddress == 0) {
printf("No export directory\n");
return TRUE;
}
PIMAGE_EXPORT_DIRECTORY pExportTable = VAToFOA(pOptHeader->DataDirectory[0].VirtualAddress, pFileBuffer);
//写入整张导出函数
DWORD sizeOfFunctions = pExportTable->NumberOfFunctions * 4;
PVOID pExporFunctionsAddr = VAToFOA(pExportTable->AddressOfFunctions, pFileBuffer);
PBYTE pWritePosition = VAToFOA(pLastSecHeader->VirtualAddress, pFileBuffer);
memcpy(pWritePosition, pExporFunctionsAddr, sizeOfFunctions);
memset(pExporFunctionsAddr, 0, sizeOfFunctions);
pExporFunctionsAddr = pWritePosition;
pWritePosition += sizeOfFunctions;
//写入序号表
DWORD sizeOfOrdinals = pExportTable->NumberOfNames * 2;
PVOID pExportOrdinalsAddr = VAToFOA(pExportTable->AddressOfNameOrdinals, pFileBuffer);
memcpy(pWritePosition, pExportOrdinalsAddr, sizeOfOrdinals);
memset(pExportOrdinalsAddr, 0, sizeOfOrdinals);
pExportOrdinalsAddr = pWritePosition;
pWritePosition += sizeOfOrdinals;
//写入名字表
DWORD sizeOfNames = pExportTable->NumberOfNames * 4;
PDWORD pExportNamesAddr = VAToFOA(pExportTable->AddressOfNames, pFileBuffer);
memcpy(pWritePosition, pExportNamesAddr, sizeOfNames);
memset(pExportNamesAddr, 0, sizeOfNames);
pExportNamesAddr = pWritePosition;
pWritePosition += sizeOfNames;
//写入所有名字,并且顺带修复名字表
for (size_t i = 0; i < pExportTable->NumberOfNames; i++) {
PBYTE pFunctionName = VAToFOA(*(pExportNamesAddr + i), pFileBuffer);
DWORD sizeOfName = strlen(pFunctionName) + 1;
memcpy(pWritePosition, pFunctionName, sizeOfName);
memset(pFunctionName, 0, sizeOfName);
*(pExportNamesAddr + i) = FOAToVA((DWORD)pWritePosition - (DWORD)pFileBuffer, pFileBuffer);
pWritePosition += sizeOfName;
}
//修复导出表,修复目录项,并且移动导出表
pExportTable->AddressOfFunctions = FOAToVA((DWORD)pExporFunctionsAddr -
(DWORD)pFileBuffer, pFileBuffer);
pExportTable->AddressOfNames = FOAToVA((DWORD)pExportNamesAddr -
(DWORD)pFileBuffer, pFileBuffer);
pExportTable->AddressOfNameOrdinals = FOAToVA((DWORD)pExportOrdinalsAddr -
(DWORD)pFileBuffer, pFileBuffer);
pOptHeader->DataDirectory[0].VirtualAddress = FOAToVA((DWORD)pWritePosition -
(DWORD)pFileBuffer, pFileBuffer);
memcpy(pWritePosition, pExportTable, sizeof(IMAGE_EXPORT_DIRECTORY));
memset(pExportTable, 0, sizeof(IMAGE_EXPORT_DIRECTORY));
//存盘
if (!FileBufferToFile(newFileName,pFileBuffer,pLastSecHeader->PointerToRawData
+ pLastSecHeader->SizeOfRawData)) {
printf("write file failed\n");
return FALSE;
}
free(pFileBuffer);
return TRUE;
}
//移动重定位表
BOOL MoveBaseRelocation(PVOID fileName, PVOID newFileName) {
if (!IncreaseSection(fileName)) {
printf("Increase section failed\n");
return FALSE;
}
PVOID pFileBuffer = FileToFileBuffer(newFileName);
//定位重定位表
PIMAGE_DOS_HEADER pDosHeader = pFileBuffer;
PIMAGE_NT_HEADERS pNTHeader = (DWORD)pDosHeader + pDosHeader->e_lfanew;
if (pNTHeader->Signature != IMAGE_NT_SIGNATURE) {
printf("File is not PE\n");
free(pFileBuffer);
return FALSE;
}
PIMAGE_FILE_HEADER pFileHeader = &pNTHeader->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptHeader = (DWORD)pFileHeader + sizeof(IMAGE_FILE_HEADER);
PIMAGE_SECTION_HEADER pSecHeader = (DWORD)pOptHeader + pFileHeader->SizeOfOptionalHeader;
PIMAGE_SECTION_HEADER pLastSecHeader = pSecHeader + pFileHeader->NumberOfSections - 1;
if (pOptHeader->DataDirectory[0].VirtualAddress == 0) {
printf("No export directory\n");
return TRUE;
}
PIMAGE_BASE_RELOCATION pReloctionTable = VAToFOA(
pOptHeader->DataDirectory[5].VirtualAddress, pFileBuffer);
//把数据全部写入新增加的节里
DWORD sizeOfRelocationTable = 0;
PVOID pReloctionTableHead = pReloctionTable;
while (pReloctionTable->VirtualAddress && pReloctionTable->SizeOfBlock) {
sizeOfRelocationTable += pReloctionTable->SizeOfBlock;
pReloctionTable = (DWORD)pReloctionTable + pReloctionTable->SizeOfBlock;
}
PBYTE pWritePosition = VAToFOA(pLastSecHeader->VirtualAddress, pFileBuffer);
memcpy(pWritePosition, pReloctionTableHead, sizeOfRelocationTable);
memset(pReloctionTableHead, 0, sizeOfRelocationTable);
//改变目录表里的项
pOptHeader->DataDirectory[5].VirtualAddress = FOAToVA((DWORD)pWritePosition -
(DWORD)pFileBuffer, pFileBuffer);
//存盘
if (!FileBufferToFile(newFileName, pFileBuffer,
pLastSecHeader->PointerToRawData + pLastSecHeader->SizeOfRawData)) {
printf("write file failed\n");
return FALSE;
}
free(pFileBuffer);
return TRUE;
}
//测试修改imageBase修改过后,完成修复重定位表能否运行
VOID ReoairRelocationTable(PVOID fileName,DWORD newImageBase) {
PVOID pFileBuffer = FileToFileBuffer(fileName);
//定位重定位表
PIMAGE_DOS_HEADER pDosHeader = pFileBuffer;
PIMAGE_NT_HEADERS pNTHeader = (DWORD)pDosHeader + pDosHeader->e_lfanew;
if (pNTHeader->Signature != IMAGE_NT_SIGNATURE) {
printf("File is not PE\n");
free(pFileBuffer);
return FALSE;
}
PIMAGE_FILE_HEADER pFileHeader = &pNTHeader->FileHeader;
PIMAGE_OPTIONAL_HEADER pOptHeader = (DWORD)pFileHeader + sizeof(IMAGE_FILE_HEADER);
PIMAGE_SECTION_HEADER pSecHeader = (DWORD)pOptHeader + pFileHeader->SizeOfOptionalHeader;
PIMAGE_SECTION_HEADER pLastSecHeader = pSecHeader + pFileHeader->NumberOfSections - 1;
PIMAGE_BASE_RELOCATION pReloctionTable = VAToFOA(pOptHeader->DataDirectory[5].VirtualAddress,
pFileBuffer);
//修改ImageBase
DWORD diffOfImageBase = newImageBase - pOptHeader->ImageBase;
pOptHeader->ImageBase = newImageBase;
//修复重定位表
while (pReloctionTable->SizeOfBlock && pReloctionTable->VirtualAddress) {
DWORD items = (pReloctionTable->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / 2;
PWORD pBlock = pReloctionTable + 1;
for (size_t i = 0; i < items; i++) {
if (!(*(pBlock) & 0xf000)) {
continue;
}
DWORD VA = (*(pBlock) & 0x0fff) + pReloctionTable->VirtualAddress;
*(PDWORD)(VAToFOA(VA, pFileBuffer)) += diffOfImageBase;
pBlock++;
}
pReloctionTable = (DWORD)pReloctionTable + pReloctionTable->SizeOfBlock;
}
//存盘
if (!FileBufferToFile(fileName, pFileBuffer, pLastSecHeader->PointerToRawData +
pLastSecHeader->SizeOfRawData)) {
printf("write file failed\n");
}
}