我们知道,重定位表是由于在代码中写入的绝对地址,而 DLL 不能按照设想的 ImageBase?作起始加载位置去了别的地方占坑,那么需要根据重定位表记录的这些绝对地址在内存中的位置(RVA),逐一去到这些位置修复绝对地址,而产生的表。
表中记录的是代码中 绝对地址 所在的RVA,需要根据偏移去到这个RVA修改掉这四字节的绝对地址
所以我们修改 DLL 的 ImageBase?来模拟这个过程,?相当于模拟?DLL?加载时?占不住原来的 ImageBase?的情况,所以只能在操作系统安排的其他位置加载,这个被安排的位置就相当于我们修改的 ImageBase
然后根据这个新占坑位置和原来 ImageBase?之间的增量来进行重定位表修正,然后存盘.看DLL是否可以使用.
注意 块中的数据项前4位为 0x3 ,才可以修改。?并且 这些绝对地址所在的 RVA?是在?数据项前4位为 0x3?的前提下,取后12位 +?块头部的 VirtualAddress?得到真正的 RVA?的
上述过程理解不透彻没关系,看代码可以彻底纠正理解。代码中也有更详细的说明
#include "Currency.h"
#include "windows.h"
#include "stdio.h"
VOID h3263() //修改ImageBase值,再修改重定位表,使得修改后的文件仍然好使
{
char FilePath[] = "CRACKME.EXE"; //CRACKME.EXE CrackHead.exe Dll1.dll R.DLL LoadDll.dll
char CopyFilePath[] = "CRACKMEcopy.EXE"; //CRACKMEcopy.EXE CrackHeadcopy.exe
LPVOID pFileBuffer = NULL; //会被函数改变的 函数输出之一
LPVOID* ppFileBuffer = &pFileBuffer; //传进函数的形参
int SizeOfFileBuffer;
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
PIMAGE_BASE_RELOCATION pRelocationTable = NULL;
DWORD nameFOA = NULL;
DWORD AddressOfNamesFOA = NULL;
//增量
int increment = 0x100000;
SizeOfFileBuffer = ReadPEFile(FilePath, ppFileBuffer); //pFileBuffer即指向已装载到内存中的exe首部
/*pFileBuffer = *ppFileBuffer;*/
if (!SizeOfFileBuffer)
{
printf("文件读取失败\n");
return;
}
//Dos头
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer; // 强转 DOS_HEADER 结构体指针
//可选PE头 简化后的处理
pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileBuffer + pDosHeader->e_lfanew + 4 + IMAGE_SIZEOF_FILE_HEADER);
//ImageBase
printf("ImageBase:%x", pOptionalHeader->ImageBase);
//重定向表
pRelocationTable = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer + RVA2FOA(pFileBuffer, pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress));
printf("RelocationTable VirtualAddress:%x\n", pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
if (!pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)
{
printf("该文件没有重定向表!\n");
return;
}
int i = 1;
while (pRelocationTable->VirtualAddress && pRelocationTable->SizeOfBlock)
{
printf("第%d个块VirtualAddress:%x\n", i, pRelocationTable->VirtualAddress);
printf("第%d个块SizeOfBlock:%x\n", i, pRelocationTable->SizeOfBlock);
printf("第%d个块项数:%d\n", i, (pRelocationTable->SizeOfBlock - 8) / 2);
pRelocationTable = (PIMAGE_BASE_RELOCATION)(pRelocationTable->SizeOfBlock + (DWORD)pRelocationTable);
i++;
}
//修改ImageBase
pOptionalHeader->ImageBase = pOptionalHeader->ImageBase + increment;
printf("ImageBase:%x", pOptionalHeader->ImageBase);
//修改重定位表中的值并输出
i = 1;
PWORD pItem; //重定向表块中的项指针,2字节不断移动
int NumberOfItems; //重定向表一块中的项数
int ItemAdd; //重定向表一项中表示的地址变量,后续会不断变换为Rva FOA
//这里pRelocationTable已经是当前绝对地址了
pRelocationTable = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer + RVA2FOA(pFileBuffer, pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress));
printf("RelocationTable VirtualAddress:%x\n", pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
while (pRelocationTable->VirtualAddress && pRelocationTable->SizeOfBlock)
{
//pRelocationTable->VirtualAddress += increment;
printf("第%d个块VirtualAddress:%x\n", i, pRelocationTable->VirtualAddress);
printf("第%d个块SizeOfBlock:%x\n", i, pRelocationTable->SizeOfBlock);
NumberOfItems = (pRelocationTable->SizeOfBlock - 8) / 2;
pItem = (PWORD)((DWORD)pRelocationTable + 8); //这里取出来的是还没加上重定向块中的VirtualAddress的Rva
printf("第%d个块项数:%d\n", i, NumberOfItems);
for (int j = 0; j < NumberOfItems; j++)
{
//按位与 1234123456789012 //1234123456789012
//if (((*pItem) & 0b1111000000000000) == 0b0011000000000000)
if (((*pItem) & 0xF000) == 0x3000) //这里的3可以用IMAGE_REL_BASED_HIGHLOW代替,不过需要移位而不是与
{ //F000 3000
printf("项:%x ", *pItem);
ItemAdd = (*pItem) & 0x0FFF; //这里取出来的是还没加上重定向块中的VirtualAddress的Rva
ItemAdd = pRelocationTable->VirtualAddress + ItemAdd; //到这里才是真正的Rva
printf("项Rva:%x\n", ItemAdd);
ItemAdd = (DWORD)pFileBuffer + RVA2FOA(pFileBuffer, ItemAdd); //变为FOA再变为绝对地址才能找到真正的值
*((PDWORD)ItemAdd) += increment; //修复这个值
}
pItem++;
}
pRelocationTable = (PIMAGE_BASE_RELOCATION)(pRelocationTable->SizeOfBlock + (DWORD)pRelocationTable);
i++;
}
//保存文件
MemeryToFile(pFileBuffer, SizeOfFileBuffer , CopyFilePath);
free(pFileBuffer);
}
以下是程序输出结果:
ImageBase:400000RelocationTable VirtualAddress:5000 第1个块VirtualAddress:1000 第1个块SizeOfBlock:dc 第1个块项数:106 ImageBase:500000RelocationTable VirtualAddress:5000 第1个块VirtualAddress:1000 第1个块SizeOfBlock:dc 第1个块项数:106 项:3008 ? 项Rva:1008 项:300f ? 项Rva:100f 项:301f ? 项Rva:101f 项:3033 ? 项Rva:1033 项:303d ? 项Rva:103d 项:3046 ? 项Rva:1046 项:304b ? 项Rva:104b 项:3058 ? 项Rva:1058 项:3069 ? 项Rva:1069 项:306f ? 项Rva:106f 项:3079 ? 项Rva:1079 项:307d ? 项Rva:107d 项:3083 ? 项Rva:1083 项:3087 ? 项Rva:1087 项:308c ? 项Rva:108c 项:3099 ? 项Rva:1099 项:30b8 ? 项Rva:10b8 项:30bd ? 项Rva:10bd 项:30c9 ? 项Rva:10c9 项:30d1 ? 项Rva:10d1 项:30dc ? 项Rva:10dc 项:30f8 ? 项Rva:10f8 项:3108 ? 项Rva:1108 项:3112 ? 项Rva:1112 项:311f ? 项Rva:111f 项:3029 ? 项Rva:1029 项:302d ? 项Rva:102d 项:31f0 ? 项Rva:11f0 项:320c ? 项Rva:120c 项:31f8 ? 项Rva:11f8 项:31fe ? 项Rva:11fe 项:3214 ? 项Rva:1214 项:321a ? 项Rva:121a 项:3229 ? 项Rva:1229 项:3234 ? 项Rva:1234 项:32b8 ? 项Rva:12b8 项:32d8 ? 项Rva:12d8 项:3350 ? 项Rva:1350 项:3355 ? 项Rva:1355 项:336c ? 项Rva:136c 项:3371 ? 项Rva:1371 项:33b0 ? 项Rva:13b0 项:33b5 ? 项Rva:13b5 项:3400 ? 项Rva:1400 项:3406 ? 项Rva:1406 项:340c ? 项Rva:140c 项:3412 ? 项Rva:1412 项:3418 ? 项Rva:1418 项:341e ? 项Rva:141e 项:3424 ? 项Rva:1424 项:342a ? 项Rva:142a 项:3430 ? 项Rva:1430 项:3436 ? 项Rva:1436 项:343c ? 项Rva:143c 项:3442 ? 项Rva:1442 项:3448 ? 项Rva:1448 项:344e ? 项Rva:144e 项:3454 ? 项Rva:1454 项:345a ? 项Rva:145a 项:3460 ? 项Rva:1460 项:3466 ? 项Rva:1466 项:346c ? 项Rva:146c 项:3472 ? 项Rva:1472 项:3478 ? 项Rva:1478 项:347e ? 项Rva:147e 项:3484 ? 项Rva:1484 项:348a ? 项Rva:148a 项:3490 ? 项Rva:1490 项:3496 ? 项Rva:1496 项:349c ? 项Rva:149c 项:34a2 ? 项Rva:14a2 项:34a8 ? 项Rva:14a8 项:34ae ? 项Rva:14ae 项:34b4 ? 项Rva:14b4 项:34ba ? 项Rva:14ba 项:34c0 ? 项Rva:14c0 项:34c6 ? 项Rva:14c6 项:34cc ? 项Rva:14cc 项:34d2 ? 项Rva:14d2 项:34d8 ? 项Rva:14d8 项:34de ? 项Rva:14de 项:34e4 ? 项Rva:14e4 项:34ea ? 项Rva:14ea 项:34f0 ? 项Rva:14f0 项:34f6 ? 项Rva:14f6 项:34fc ? 项Rva:14fc 项:3502 ? 项Rva:1502 项:3508 ? 项Rva:1508 项:350e ? 项Rva:150e 项:3514 ? 项Rva:1514 项:351a ? 项Rva:151a 项:3520 ? 项Rva:1520 项:3526 ? 项Rva:1526 项:352c ? 项Rva:152c 项:3532 ? 项Rva:1532 项:3538 ? 项Rva:1538 项:353e ? 项Rva:153e 项:3544 ? 项Rva:1544 项:354a ? 项Rva:154a 项:3550 ? 项Rva:1550 项:3556 ? 项Rva:1556 项:355c ? 项Rva:155c 项:3562 ? 项Rva:1562 项:3568 ? 项Rva:1568 项:356e ? 项Rva:156e success
如果用的是 dll,把新生成的 dll?用另一个工程调用一次,验证是否正确
这里用的是exe,跑完程序后点击下新exe是否正常运行就可以了
|