void FixBaseRelocTable(PVOID pNewImage)
{
ULONG uIndex;
ULONG uRelocTableSize;
ULONG_PTR OriginalImageBase;
ULONG Type;
ULONG_PTR *uRelocAddress;
PIMAGE_DOS_HEADER pImageDosHeader;
PIMAGE_NT_HEADERS64 pImageNtHeader;
IMAGE_DATA_DIRECTORY ImageDataDirectory;
IMAGE_BASE_RELOCATION *pImageBaseRelocation;
//
将新内核地址作为一个PE文件头,依次向下,目的是寻找重定位表结构
pImageDosHeader=(PIMAGE_DOS_HEADER)pNewImage;
//
定位到IMAGE_NT_HEADER
pImageNtHeader=(PIMAGE_NT_HEADERS64)((ULONG_PTR)pNewImage+pImageDosHeader->e_lfanew);
//
获取内核文件的imagebase,以便后面做偏移修改。
OriginalImageBase=pImageNtHeader->OptionalHeader.ImageBase;
//
定位到数据目录
ImageDataDirectory = pImageNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
//
定位到重定位表结构
pImageBaseRelocation = (PIMAGE_BASE_RELOCATION)(ImageDataDirectory.VirtualAddress + (ULONG_PTR)pNewImage);
if
(pImageBaseRelocation==NULL)
{
return
;
}
while
(pImageBaseRelocation->SizeOfBlock)
{
//
计算需要修改的地址的个数
uRelocTableSize=(pImageBaseRelocation->SizeOfBlock-8)
/2
;
//
循环遍历
for
(uIndex=0;uIndex<uRelocTableSize;uIndex++)
{
//
判断高4位是否等于3
Type=pImageBaseRelocation->TypeOffset[uIndex]>>12;
if
(Type==IMAGE_REL_BASED_DIR64)
{
//
修改地址,相对地址加上一个新内核地址,使其成为一个实际地址
uRelocAddress=(ULONG64 *)((ULONG64)(pImageBaseRelocation->TypeOffset[uIndex]&0x0fff)+pImageBaseRelocation->VirtualAddress+(ULONG64)pNewImage);
//
再加上内核首地址到imagebase的偏移
*uRelocAddress=*uRelocAddress+(OrigImage-OriginalImageBase);
}
}
//
进行下一个重定位表的修改
pImageBaseRelocation=(IMAGE_BASE_RELOCATION *)((ULONG64)pImageBaseRelocation+pImageBaseRelocation->SizeOfBlock);
}
}