如何从PEPROCESS中读取驱动程序中的导入地址表?

问题描述 投票:6回答:2

我正在编写驱动程序以创建防病毒软件。但是,我一直在从进程中读取导入地址表。

我有一个CreateProcessNotify:

VOID CreateProcNotify(HANDLE  ParentId, HANDLE  ProcessId, BOOLEAN Create)
{
    UNREFERENCED_PARAMETER(ParentId);
    UNREFERENCED_PARAMETER(Create);
    PEPROCESS Process;
    KAPC_STATE Apc;
    PVOID ModuleBase;

    // From PID to PEPROCESS
    PsLookupProcessByProcessId(ProcessId, &Process);

    // Attach into the target process' memory
    KeStackAttachProcess(Process, &Apc);

    ModuleBase = GetModuleBase(Process);

    PIMAGE_IMPORT_DESCRIPTOR pImportAddressTable = GetIAT(ModuleBase);

    DPrint("Imports of [Meias] are: \n");
    DPrint("IAT: %x\n", pImportAddressTable);
    // Iterate all Modules Imports
    while (pImportAddressTable->Name != 0) {
        DPrint("{%s}, ", (PCHAR)((ULONG)ModuleBase + (pImportAddressTable->Name)));

        pImportAddressTable++;
    }

    // Unattach ourselves from the target process' memory
    KeUnstackDetachProcess(&Apc);
}

同时还具有以下功能:

/*Returns the Base of the Process*/
PVOID GetModuleBase(PEPROCESS Process)
{
    PVOID ModuleBase;

    __try
    {
        ModuleBase = PsGetProcessSectionBaseAddress(Process);
    }
    __except (GetExceptionCode())
    {
        return 0;
    }

    return ModuleBase;
}

/*Returns the Import Address Table*/
PIMAGE_IMPORT_DESCRIPTOR GetIAT(PVOID ModuleBase)
{
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)ModuleBase;
    PIMAGE_NT_HEADERS32 pNtHeader32 = NULL;
    PIMAGE_NT_HEADERS64 pNtHeader64 = NULL;
    PIMAGE_IMPORT_DESCRIPTOR pIAT = NULL;

    if (ModuleBase == 0)
        return NULL;

    DPrint("ModuleBase: 0x%x\n", pDosHeader);

    // If the magic value isn't MZ then isn't a valid PE
    if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
        return NULL;

    pNtHeader32 = (PIMAGE_NT_HEADERS32)((PUCHAR)ModuleBase + pDosHeader->e_lfanew);
    pNtHeader64 = (PIMAGE_NT_HEADERS64)((PUCHAR)ModuleBase + pDosHeader->e_lfanew);

    // If the image doesn't have a DOS
    if ((INT)pNtHeader32 != IMAGE_NT_SIGNATURE)
        return NULL;

    // Check if is 32 bit
    if (pNtHeader32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
        pIAT = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG_PTR)ModuleBase + pNtHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
    }
    // Check if is 64 bit
    else if (pNtHeader64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
        pIAT = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG_PTR)ModuleBase + pNtHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
    }

    return pIAT;
}

使用WinDBG进行调试时:

The exception it throw

使用!analyze -v:

例外:enter image description here

代码:enter image description here

我在this的帮助下实现了GetIAT

你可以看到问题是它没有正确地获得IAT,但我不知道为什么......

提前致谢。

c++ c windbg drivers portable-executable
2个回答
4
投票

问题是因为我正在使用

if ((INT)pNtHeader32 != IMAGE_NT_SIGNATURE)
        return NULL;

当我应该检查它的签名时:

if ((INT)pNtHeader32->Signature != IMAGE_NT_SIGNATURE)
        return NULL;

完成。


1
投票

IAT功能的代码是不可靠的。如果导入表地址为0,则将是BSOD的原因。

例如,这个project(分析依赖关系;翻译旧遗留软件depends.exe)的导入表地址为0。

enter image description here

为避免BSOD,您需要添加一个检查,如下所示:

...
    // Check if is 32 bit
    if (pNtHeader32->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
        if (pNtHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0)
            return NULL;

        pIAT = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG_PTR)ModuleBase
            + pNtHeader32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
    }
    // Check if is 64 bit
    else if (pNtHeader64->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
        if (pNtHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0)
            return NULL;

        pIAT = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG_PTR)ModuleBase + pNtHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
    }
...
© www.soinside.com 2019 - 2024. All rights reserved.