Search code examples
c++memorywindows-kernel

User land access to Kernel land driver system notifications


I have recently came across a mechanism in Windows that allows drivers to respond to low memory conditions and wondered if it is possible for my application to respond to events similar to the Standard Event Objects as defined by (via some other mechanism) :

https://msdn.microsoft.com/en-us/library/windows/hardware/ff563847(v=vs.85).aspx

  • HighMemoryCondition
  • LowMemoryCondition
  • HighPagedPoolCondition
  • LowPagedPoolCondition
  • HighNonPagedPoolCondition
  • LowNonPagedPoolCondition
  • LowCommitCondition
  • HighCommitCondition
  • MaximumCommitCondition

This sounds ideal for what I am doing in my application as I need to detect throttle conditions and respond accordingly.

However, it seems that these are in Kernel land so how is an application in User land supposed to respond to the same conditions?

Thanks for any pointers - Laythe


Solution

  • you can very easy use this events in user mode too. simply open it with ZwOpenEvent and all. for example

    HANDLE hEvent;
    STATIC_OBJECT_ATTRIBUTES(ke,"\\KernelObjects\\LowMemoryCondition") ;
    ZwOpenEvent(&hEvent, SYNCHRONIZE|EVENT_QUERY_STATE, &ke);
    WaitForSingleObject(hEvent, INFINITE);
    

    STATIC_OBJECT_ATTRIBUTES - my macro for static initialize Unicode string. you can write own implementation - use RTL_CONSTANT_STRING as hint or initialize Unicode string in run-time


    example of discovery \KernelObjects directory

    void TestKO()
    {
        STATIC_OBJECT_ATTRIBUTES(soa, "\\KernelObjects");
    
        OBJECT_ATTRIBUTES oa = { sizeof(oa) };
    
        if (0 <= ZwOpenDirectoryObject(&oa.RootDirectory, DIRECTORY_QUERY, &soa))
        {
    
            ULONG Context = 0, rcb;
            PVOID buf = alloca(PAGE_SIZE);
    
            NTSTATUS status, s;
    
            do 
            {
                if (0 <= (status = ZwQueryDirectoryObject(oa.RootDirectory, buf, PAGE_SIZE, FALSE, FALSE, &Context, &rcb)))
                {
                    DIRECTORY_BASIC_INFORMATION* pdbi = (DIRECTORY_BASIC_INFORMATION*)buf;
    
                    while (pdbi->ObjectTypeName.Length)
                    {
                        //DbgPrint("%wZ %wZ\n", &pdbi->ObjectTypeName, &pdbi->ObjectName);
    
                        STATIC_UNICODE_STRING_(Event);
    
                        if (RtlEqualUnicodeString(&Event, &pdbi->ObjectTypeName, TRUE))
                        {
                            oa.ObjectName = &pdbi->ObjectName;
    
                            HANDLE hEvent;
                            if (0 <= (s = ZwOpenEvent(&hEvent, READ_CONTROL|EVENT_QUERY_STATE, &oa)))
                            {
                                EVENT_BASIC_INFORMATION ebi;
                                if (0 <= (s = ZwQueryEvent(hEvent, EventBasicInformation, &ebi, sizeof(ebi), &rcb)))
                                {
    
                                    PCSTR szEventType;
                                    switch (ebi.EventType)
                                    {
                                    case NotificationEvent: 
                                        szEventType = "Notification   ";
                                        break;
                                    case SynchronizationEvent: 
                                        szEventType = "Synchronization";
                                        break;
                                    default:
                                        char cc[16];
                                        sprintf(cc, "%x", ebi.EventType);
                                        szEventType = cc;
                                    }
                                    DbgPrint("%x %s %wZ\n", ebi.EventState, szEventType, &pdbi->ObjectName);
                                }
                                else
                                {
                                    DbgPrint("QueryEvent(%wZ)=%x\n", &pdbi->ObjectName, s);
                                }
    
                                DumpAccess(hEvent);// not lisred here
                                NtClose(hEvent);
                            }
                            else
                            {
                                DbgPrint("OpenEvent(%wZ)=%x\n", &pdbi->ObjectName, s);
                            }
                        }
                        pdbi++;
                    }
                }
            } while (status == STATUS_MORE_ENTRIES);
    
            NtClose(oa.RootDirectory);
        }
    }
    

    and results (event state, type and access) :

    0 Notification    MemoryErrors
    T FL AcessMsK Sid
    0 00 00120001 S-1-1-0 Everyone
    0 00 001F0003 S-1-5-32-544 Administrators
    0 00 001F0003 S-1-5-18 SYSTEM
    0 00 00120001 S-1-15-2-1 ALL APPLICATION PACKAGES
    0 Notification    LowNonPagedPoolCondition
    T FL AcessMsK Sid
    0 00 00120001 S-1-1-0 Everyone
    0 00 001F0003 S-1-5-32-544 Administrators
    0 00 001F0003 S-1-5-18 SYSTEM
    0 00 00120001 S-1-15-2-1 ALL APPLICATION PACKAGES
    1 Notification    SuperfetchScenarioNotify
    T FL AcessMsK Sid
    0 00 001F0003 S-1-5-32-544 Administrators
    0 00 001F0003 S-1-5-18 SYSTEM
    0 Synchronization SuperfetchParametersChanged
    T FL AcessMsK Sid
    0 00 001F0003 S-1-5-32-544 Administrators
    0 00 001F0003 S-1-5-18 SYSTEM
    0 Notification    PhysicalMemoryChange
    T FL AcessMsK Sid
    0 00 00120001 S-1-1-0 Everyone
    0 00 001F0003 S-1-5-32-544 Administrators
    0 00 001F0003 S-1-5-18 SYSTEM
    0 00 00120001 S-1-15-2-1 ALL APPLICATION PACKAGES
    0 Notification    HighCommitCondition
    T FL AcessMsK Sid
    0 00 00120001 S-1-1-0 Everyone
    0 00 001F0003 S-1-5-32-544 Administrators
    0 00 001F0003 S-1-5-18 SYSTEM
    0 00 00120001 S-1-15-2-1 ALL APPLICATION PACKAGES
    1 Notification    HighNonPagedPoolCondition
    T FL AcessMsK Sid
    0 00 00120001 S-1-1-0 Everyone
    0 00 001F0003 S-1-5-32-544 Administrators
    0 00 001F0003 S-1-5-18 SYSTEM
    0 00 00120001 S-1-15-2-1 ALL APPLICATION PACKAGES
    1 Notification    HighMemoryCondition
    T FL AcessMsK Sid
    0 00 00120001 S-1-1-0 Everyone
    0 00 001F0003 S-1-5-32-544 Administrators
    0 00 001F0003 S-1-5-18 SYSTEM
    0 00 00120001 S-1-15-2-1 ALL APPLICATION PACKAGES
    0 Notification    SystemErrorPortReady
    T FL AcessMsK Sid
    0 00 00120001 S-1-2-0 LOCAL
    0 00 00120001 S-1-15-2-1 ALL APPLICATION PACKAGES
    0 00 001F0003 S-1-5-18 SYSTEM
    0 00 00120001 S-1-1-0 Everyone
    0 Notification    MaximumCommitCondition
    T FL AcessMsK Sid
    0 00 00120001 S-1-1-0 Everyone
    0 00 001F0003 S-1-5-32-544 Administrators
    0 00 001F0003 S-1-5-18 SYSTEM
    0 00 00120001 S-1-15-2-1 ALL APPLICATION PACKAGES
    1 Notification    LowCommitCondition
    T FL AcessMsK Sid
    0 00 00120001 S-1-1-0 Everyone
    0 00 001F0003 S-1-5-32-544 Administrators
    0 00 001F0003 S-1-5-18 SYSTEM
    0 00 00120001 S-1-15-2-1 ALL APPLICATION PACKAGES
    1 Notification    HighPagedPoolCondition
    T FL AcessMsK Sid
    0 00 00120001 S-1-1-0 Everyone
    0 00 001F0003 S-1-5-32-544 Administrators
    0 00 001F0003 S-1-5-18 SYSTEM
    0 00 00120001 S-1-15-2-1 ALL APPLICATION PACKAGES
    0 Notification    LowMemoryCondition
    T FL AcessMsK Sid
    0 00 00120001 S-1-1-0 Everyone
    0 00 001F0003 S-1-5-32-544 Administrators
    0 00 001F0003 S-1-5-18 SYSTEM
    0 00 00120001 S-1-15-2-1 ALL APPLICATION PACKAGES
    0 Notification    LowPagedPoolCondition
    T FL AcessMsK Sid
    0 00 00120001 S-1-1-0 Everyone
    0 00 001F0003 S-1-5-32-544 Administrators
    0 00 001F0003 S-1-5-18 SYSTEM
    0 00 00120001 S-1-15-2-1 ALL APPLICATION PACKAGES
    1 Synchronization PrefetchTracesReady
    T FL AcessMsK Sid
    0 00 001F0003 S-1-5-32-544 Administrators
    0 00 001F0003 S-1-5-18 SYSTEM