Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read Import Address Table, in a driver, from a PEPROCESS?

I am coding a driver in order to create an Antivirus. However, I am stuck in reading the import address table from a process.

I have a 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);
}

While also having the following functions:

/*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;
}

When debugging with WinDBG:

The exception it throw

Using the !analyze -v:

The exception: enter image description here

The code: enter image description here

I implemented the GetIAT with the help of this

As you can see the problem is that it isn't getting the IAT properly but I don't know why...

Thanks in advance.

like image 477
L3n Avatar asked May 01 '17 16:05

L3n


People also ask

How does the import address table work?

First, it reads the files of a PE structure and loads an executable image into the memory. The other thing it does is to scan the Import Address Table (IAT) of an executable to locate the DLLs and functions that the executable uses and load all these DLLs and map them into the process address space.

Where is the import address table?

The Import Directory Table is a Data Directory located at the beginning of the . idata section. It consists of an array of IMAGE_IMPORT_DESCRIPTOR structures, each one of them is for a DLL.

What is IAT hooking?

IAT hooking is a way to run malicious code by modifying the Import Address Table of a specific executable. Consisting of replacing one legitimate function from imported DLL by a malicious one. IAT hooking and inline hooking are generally known as userland rootkits.


2 Answers

The problem was because I was using

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

When I should be checking the Signature of it:

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

Done.

like image 156
L3n Avatar answered Sep 22 '22 05:09

L3n


The code of IAT function is unreliable. If Import Table Address is 0 it will be a reason for BSOD.

For example, this project (to analyze dependencies; remake of the old legacy software depends.exe) has Import Table Address is 0.

enter image description here

For avoiding BSOD you need to add a check, like this:

...
    // 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);
    }
...
like image 34
slinkin Avatar answered Sep 22 '22 05:09

slinkin