'Close file handle of process from kernelmode driver on Windows

I'm trying to close a specific file handle of a process from a kernelmode driver on Windows. For this, I'm using ZwQuerySystemInformation to enumerate all handles on the system and then filter them based on a given process id and by checking for a specific substring in the handle name. However, I'm not sure how I can close this handle once I found the target. Using NtClose returns STATUS_INVALID_HANDLE.

My code looks like this:

BOOL TerminateHandle(DWORD64 processId)
{
    BOOL retVal = FALSE;
    PSYSTEM_HANDLE_INFORMATION handleInfo = NULL;
    PSYSTEM_HANDLE_TABLE_ENTRY_INFO handleEntry = NULL;
    POBJECT_NAME_INFORMATION nameInfo = NULL;
    ULONG required = 0, size = 0, requiredName = 0;
    NTSTATUS handleInfoStatus;

    do {

        if (handleInfo)
        {
            fpExFreePool(handleInfo);
            handleInfo = NULL;
        }

        size += 1024;

        if(!(handleInfo = fpExAllocatePool(NonPagedPool, size)))
            goto Done;

    } while ((handleInfoStatus = fpZwQuerySystemInformation(0x10, handleInfo, size, &required)) == STATUS_INFO_LENGTH_MISMATCH);

    if (!NT_SUCCESS(handleInfoStatus))
        goto Done;
    
    for (DWORD i = 0; i < handleInfo->NumberOfHandles; i++)
    {
        requiredName = 0;
        handleEntry = (PSYSTEM_HANDLE_TABLE_ENTRY_INFO)&handleInfo->Handles[i];

        if (handleEntry->UniqueProcessId != processId)
            continue;
        
        fpObQueryNameString(handleEntry->Object, NULL, 0, &requiredName);

        if (requiredName && (nameInfo = fpExAllocatePool(NonPagedPool, requiredName)))
        {
            if (NT_SUCCESS(fpObQueryNameString(handleEntry->Object, nameInfo, required, &requiredName)) && nameInfo->Name.Buffer)
            {
                if (FindSubstring(nameInfo->Name.Buffer, nameInfo->Name.Length / sizeof(WCHAR), L"ExampleSubStr", 13))
                {
                    fpDbgPrintEx(0, 0, "Found: %wZ\n", &nameInfo->Name);
                    fpDbgPrintEx(0, 0, "Try closing: %x\n", NtClose((HANDLE)handleEntry->HandleValue)); //STATUS_INVALID_HANDLE 
                }
            }

            fpExFreePool(nameInfo);
        }
    }

Done:

    if (handleInfo)
        fpExFreePool(handleInfo);

    return retVal;
}

By the way, is there a way to make this code more efficient? Iterating through all handles of the system is not very resource friendly.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source