Close file handle of process from kernelmode driver on Windows

282 views Asked by At

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.

0

There are 0 answers