NTSTATUS FindPagefile()

in Silhouette/Filter_Main.cpp [67:177]


NTSTATUS FindPagefile()
{
    const ULONG systemProcessId = HandleToULong(PsGetProcessId(PsInitialSystemProcess)); // Always 4, but you never know?
    DECLARE_CONST_UNICODE_STRING(pagefile_sys, L"\\pagefile.sys");

    NTSTATUS ntStatus = STATUS_SUCCESS;
    PSYSTEM_HANDLE_INFORMATION pHandleInfo = NULL;
    ULONG handleInfoMem = 0;
    ULONG returnLength = 0;
    PFILE_OBJECT pFile = NULL;
    PFILE_NAME_INFORMATION pNameInfo = NULL;

    for (ULONG tries = 0; tries < 5; tries++)
    {
        ntStatus = ZwQuerySystemInformation(SystemHandleInformation, pHandleInfo, handleInfoMem, &returnLength);
        if (STATUS_INFO_LENGTH_MISMATCH != ntStatus)
        {
            break;
        }

        HandleDelete(pHandleInfo);
        handleInfoMem = returnLength * 2;
        pHandleInfo = (PSYSTEM_HANDLE_INFORMATION)ExAllocatePoolWithTag(PagedPool, handleInfoMem, POOL_TAG);
        if (!pHandleInfo)
        {
            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
            goto Cleanup;
        }
        RtlZeroMemory(pHandleInfo, handleInfoMem);
    }
    if (!NT_SUCCESS(ntStatus))
    {
        goto Cleanup;
    }

    for (ULONG i = 0; i < pHandleInfo->NumberOfHandles; i++)
    {
        UNICODE_STRING nameInfoUni = { 0, };

        if (systemProcessId != pHandleInfo->Handles[i].UniqueProcessId)
        {
            continue;
        }

        ReferenceDelete(pFile);
        PoolDeleteWithTag(pNameInfo, POOL_TAG);

            // I'm not fond of temporarily referencing other handles in the System process, but the point here is to prove the concept
        ntStatus = ObReferenceObjectByHandle(
            MAKE_KERNEL_HANDLE(ULongToHandle(pHandleInfo->Handles[i].HandleValue)), FILE_READ_DATA|FILE_WRITE_DATA, *IoFileObjectType, KernelMode, (PVOID*)&pFile, NULL);
        if (!NT_SUCCESS(ntStatus))
        {
            continue;
        }

        // pagefile.sys is opened without buffering
        if (!FlagOn(pFile->Flags, FO_NO_INTERMEDIATE_BUFFERING))
        {
            continue;
        }

        // pagefile.sys is opened for RW- with -W- sharing
        if (!pFile->ReadAccess || !pFile->WriteAccess || pFile->DeleteAccess || pFile->SharedRead || pFile->SharedDelete)
        {
            continue;
        }

        pNameInfo = (PFILE_NAME_INFORMATION)ExAllocatePoolWithTag(PagedPool, 4096, POOL_TAG);
        if (!pNameInfo)
        {
            continue;
        }
             
        RtlZeroMemory(pNameInfo, 4096);
        pNameInfo->FileNameLength = 4096 - sizeof(*pNameInfo); // Leave room for a NULL

        ntStatus = FsRtlQueryInformationFile(pFile, pNameInfo, 4096, FileNameInformation, &returnLength);
        if (!NT_SUCCESS(ntStatus) || (pNameInfo->FileNameLength > MAXUSHORT))
        {
            continue;
        }

        nameInfoUni.Buffer = pNameInfo->FileName;
        nameInfoUni.Length = (USHORT)pNameInfo->FileNameLength;
        nameInfoUni.MaximumLength = nameInfoUni.Length;

        if (!RtlEqualUnicodeString(&nameInfoUni, &pagefile_sys, FALSE))
        {
            continue;
        }

        ntStatus = FsRtlQueryInformationFile(pFile, &gProtectedFiles[0], sizeof(gProtectedFiles[0]), FileIdInformation, &returnLength);
        if (NT_SUCCESS(ntStatus) && (sizeof(gProtectedFiles[0]) == returnLength))
        {
            DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,
                "Silhouette: Pagefile: %wZ\n",
                &nameInfoUni);

            goto Cleanup;
        }
    }

    ntStatus = STATUS_PAGEFILE_NOT_SUPPORTED;

Cleanup:
    PoolDeleteWithTag(pHandleInfo, POOL_TAG);
    PoolDeleteWithTag(pNameInfo, POOL_TAG);
    ReferenceDelete(pFile);

    return ntStatus;
}