移动导出表,重定位表,手动修复重定位表

要写这几个函数会频繁用到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");
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值