如何在不使用硬编码值的情况下使用基地址计算函数的地址

How to calculate a address of a function using base address without using hard coded values

所以我尝试使用 C 代码计算位于 ntoskrnl.exe 中的函数的 64 位虚拟地址。我已经使用 C 代码确定了这个可执行文件的基址。该地址与 Windbg 报告的一致。

目前我有代码确定指向IMAGE_OPTIONAL_HEADER64结构的指针。现在我想知道的是,给定一个指向该结构的指针,是否可以使用与该结构关联的成员(例如以下成员(见下文))来确定确切的 64 位地址?如果是,请提供一个计算该地址的公式。目标 OS 是 Windows 8.1 64 位。

如果这不可能实现,请纠正我的理解。

extern IMAGE_DOS_HEADER* NtBase; // calculated in another file
dosHeader = (PIMAGE_DOS_HEADER)NtBase;

if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE)
{
    PIMAGE_NT_HEADERS NtHeader = (PIMAGE_NT_HEADERS)((UCHAR*)dosHeader + dosHeader->e_lfanew);

    if (NtHeader->Signature == IMAGE_NT_SIGNATURE)
    {
        //int NumSections = NtHeader->FileHeader.NumberOfSections;
        sectionHeader = IMAGE_FIRST_SECTION(NtHeader);
        nSectionCount = NtHeader->FileHeader.NumberOfSections;
        
        PIMAGE_OPTIONAL_HEADER64 pOptionalHeader64 = (PIMAGE_OPTIONAL_HEADER64) & (NtHeader->OptionalHeader); 

        // how to calculate 64 bit address of a function using these members
        //pOptionalHeader64->BaseOfCode
        //pOptionalHeader64->AddressOfEntryPoint
        //pOptionalHeader64->ImageBase;  
    }
}

对我有用的解决方案是首先找到 Ntoskrnl.exe 的基地址,然后使用 Windbg 定位感兴趣函数的前 4-10 个字节。您可以在 Windbg 命令提示符下发出以下命令 >uf nt!KiSetTimerEx。然后编写代码,从基地址开始一次读取一个字节,直到到达代码段的末尾。您很可能会在到达代码部分末尾之前找到感兴趣的函数。通过一次读取一个字节,将每个字节与在 Windbg 命令提示符下使用上述命令找到的字节数组的第一个字节(然后与第二个字节,一旦第一个匹配,等等)进行比较。此处可能会使用更高效的算法。