// 在重定位数据中查找所有引用 SymAddr 的地址
// ex: mov eax, [g_hModule] ; SymAddr 即 [] 中的数字,而要查找的是 [] 所在的“位置”
// 如果进行查找是个地址表或是函数地址,那进行 hook 操作将会更隐秘一些(一般都是和GetImageImpSym顺序使用 )
// BOOLEAN NTAPI LookupXRefCallback(PULONG RefAddr)
// {
// // 返回 True 继续寻找,返回 False 停止寻找
// printf("%08X --> %08X", RefAddr, RefAddr[0]);
//
// return TRUE;
// }
ULONG NTAPI // 返回找到的引用个数
pLookupImageXRef(
IN ULONG ImageBase, // 参考地址
IN PIMAGE_DATA_DIRECTORY pBrDir,
IN PIMAGE_BASE_RELOCATION pBr,
IN ULONG SymAddr,
IN LOOPUPXREF_CALLBACK LookupXRefCallback // 回调
)
{
ULONG nRefCount = 0;
__try
{
ULONG Size = 0;
while ( pBr->SizeOfBlock != 0 && Size < pBrDir->Size )
{
PWORD pRelItem = (PWORD)(pBr + 1);
PIMAGE_BASE_RELOCATION pNextBr = (PIMAGE_BASE_RELOCATION)((ULONG)pBr + pBr->SizeOfBlock);
while ( (ULONG)pRelItem < (ULONG)pNextBr )
{
if ( (pRelItem[0] >> 12) == 3 )
{
PULONG RefAddr = (PULONG)(ImageBase + pBr->VirtualAddress + (pRelItem[0] & 0x0FFF));
if (
MmIsAddressValid(RefAddr) && // 验证内存是否有效
*RefAddr == SymAddr &&
LookupXRefCallback(RefAddr)
)
{
nRefCount++;
}
}
pRelItem++;
}
Size += pBr->SizeOfBlock;
pBr = pNextBr;
}
}
__except ( EXCEPTION_EXECUTE_HANDLER )
{
DbgPrint("pLookupImageXRef: Found a Exception!/n");
}
return nRefCount;
}
ULONG NTAPI
LookupImageXRef(
IN ULONG ImageBase, // 有效地址
IN ULONG SymAddr,
IN LOOPUPXREF_CALLBACK LookupXRefCallback // 回调
)
{
if ( LookupXRefCallback != NULL )
{
PIMAGE_DATA_DIRECTORY pBrDir;
PIMAGE_BASE_RELOCATION pBr;
pBr = GetImageDirEntry(ImageBase, IMAGE_DIRECTORY_ENTRY_BASERELOC, NULL, &pBrDir);
if ( pBr != NULL )
{
return pLookupImageXRef(ImageBase, pBrDir, pBr, SymAddr, LookupXRefCallback);
}
}
return 0;
}
ULONG NTAPI
LookupFileXRef(
IN PCWSTR pszFileName,
IN ULONG ImageBase, // 参考基址
IN ULONG SymAddr,
IN LOOPUPXREF_CALLBACK LookupXRefCallback // 回调
)
{
NTSTATUS Status;
HANDLE FileHandle;
OBJECT_ATTRIBUTES ObAttr;
UNICODE_STRING usFileName;
IO_STATUS_BLOCK IoStatus;
LARGE_INTEGER FilePos;
IMAGE_DOS_HEADER DosHeader;
IMAGE_NT_HEADERS NtHeader;
IMAGE_SECTION_HEADER SectHeader;
IMAGE_DATA_DIRECTORY BrDir;
PIMAGE_BASE_RELOCATION pBr;
ULONG nSection, nRefCount;
RtlInitUnicodeString(&usFileName, pszFileName);
InitializeObjectAttributes(
&ObAttr,
&usFileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status = ZwOpenFile(
&FileHandle,
GENERIC_READ,
&ObAttr,
&IoStatus,
FILE_SHARE_READ,
0
);
if ( !NT_SUCCESS(Status) )
{
return 0;
}
//
// 读出 Dos header
FilePos.QuadPart = 0;
Status = ZwReadFile(
FileHandle,
NULL,
NULL,
NULL,
&IoStatus,
&DosHeader,
sizeof (DosHeader),
&FilePos,
NULL
);
if ( !NT_SUCCESS(Status) || DosHeader.e_magic != IMAGE_DOS_SIGNATURE )
{
ZwClose(FileHandle);
return 0;
}
// 读出 nt header
FilePos.LowPart = DosHeader.e_lfanew;
Status = ZwReadFile(
FileHandle,
NULL,
NULL,
NULL,
&IoStatus,
&NtHeader,
sizeof (NtHeader),
&FilePos,
NULL
);
if ( !NT_SUCCESS(Status) || NtHeader.Signature != IMAGE_NT_SIGNATURE )
{
ZwClose(FileHandle);
return 0;
}
//
// 验证重定位信息
BrDir = NtHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
if ( BrDir.VirtualAddress == 0 || BrDir.Size == 0 )
{
ZwClose(FileHandle);
return 0;
}
//
// 获取 重定位信息 的 raw
FilePos.LowPart = DosHeader.e_lfanew + sizeof (NtHeader);
FilePos.LowPart += NtHeader.FileHeader.SizeOfOptionalHeader - sizeof (IMAGE_OPTIONAL_HEADER);
for ( nSection = 0; nSection < NtHeader.FileHeader.NumberOfSections; nSection++ )
{
const ULONG PointerSectionHeader = FilePos.LowPart;
Status = ZwReadFile(
FileHandle,
NULL,
NULL,
NULL,
&IoStatus,
&SectHeader,
sizeof (SectHeader),
&FilePos,
NULL
);
if ( !NT_SUCCESS(Status) )
{
ZwClose(FileHandle);
return 0;
}
// DbgPrint("Section Name: %s/n", SectHeader.Name);
#if 0
if (
BrDir.VirtualAddress >= SectHeader.VirtualAddress &&
BrDir.VirtualAddress < (SectHeader.VirtualAddress + SectHeader.SizeOfRawData)
)
#else
if ( _stricmp(SectHeader.Name, ".reloc") == 0 )
#endif
{
FilePos.LowPart = BrDir.VirtualAddress - SectHeader.VirtualAddress + SectHeader.PointerToRawData;
break;
}
FilePos.LowPart = PointerSectionHeader + sizeof (SectHeader);
}
//
// 无效的陈定位数据
if ( nSection == NtHeader.FileHeader.NumberOfSections )
{
ZwClose(FileHandle);
return 0;
}
//
// 分配内存,存放从文件中读出的重定位信息
pBr = ExAllocatePool(NonPagedPool, BrDir.Size);
if ( NULL == pBr )
{
ZwClose(FileHandle);
return 0;
}
//
// 读取重定位信息到内存中
Status = ZwReadFile(
FileHandle,
NULL,
NULL,
NULL,
&IoStatus,
pBr,
BrDir.Size,
&FilePos,
NULL
);
ZwClose(FileHandle);
if ( !NT_SUCCESS(Status) )
{
ExFreePool(pBr);
return 0;
}
//
// 开始进行查找
nRefCount = pLookupImageXRef(ImageBase, &BrDir, pBr, SymAddr, LookupXRefCallback);
ExFreePool(pBr);
return nRefCount;
}