user1618465
user1618465

Reputation: 1941

Interact with Session type Kernel objects

This is my first time dealing with Windows kernel objects so please correct me if the terminology or what I say it's not accurate

I'm trying to open and send some data to a Session type kernel object named \KernelObjects\\Session0.

From Windows Internals book:

KernelObjects [...] Contains event objects that signal kernel pool resource conditions, the completion of certain operating system tasks, as well as Session objects (at least Session0) representing each interactive session, and Partition objects (at least MemoryPartition0) for each memory partition.

The Session0 type object exist as can be seen in WinObj:

WinObj screenshot

Below is the code I wrote to:

#include <winternl.h>
#include <stdio.h>


struct driverData
{
    [...] ;
};

typedef NTSTATUS(WINAPI* NTOpenEventAPI)(
    OUT PHANDLE EventHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes);

typedef NTSTATUS(WINAPI* NtNotifyChangeSession)(_In_ HANDLE SessionHandle, _In_ ULONG ChangeSequenceNumber, _In_ PLARGE_INTEGER ChangeTimeStamp,
    _In_ int Event, _In_ int NewState, _In_ int PreviousState,
    _In_reads_bytes_opt_(PayloadSize) PVOID Payload, _In_ ULONG PayloadSize);

typedef NTSTATUS(WINAPI* NtClose1)(_In_ HANDLE);


static
HANDLE OpenKernelSession(const wchar_t* event_name, OUT HANDLE* session) {
    static HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll");
    static const auto NtOpenSessionFunc = (NTOpenEventAPI)::GetProcAddress(ntdll, "NtOpenSession");
    if (!NtOpenSessionFunc) {
        fprintf(stderr, "Cannot load NtOpenSession function. Error: %u\n", ::GetLastError());
        return NULL;
    }

    static const auto RtlInitUnicodeStringFunc =
        reinterpret_cast<decltype(&::RtlInitUnicodeString)>(GetProcAddress(ntdll, "RtlInitUnicodeString"));
    if (!RtlInitUnicodeStringFunc) {
        fprintf(stderr, "Cannot load RtlInitUnicodeString function. Error: %u\n", ::GetLastError());
        return NULL;
    }

    UNICODE_STRING object_name;
    RtlInitUnicodeStringFunc(&object_name, event_name);

    OBJECT_ATTRIBUTES object_attrib;
    InitializeObjectAttributes(&object_attrib, &object_name, 0, nullptr, nullptr);


    //HANDLE session;
    NTSTATUS status = NtOpenSessionFunc(session, 2, &object_attrib);
    if (!NT_SUCCESS(status)) {
        fprintf(stderr, "Cannot open event %S. Error: 0x%08X\n", event_name, status);
        return NULL;
    }
    else {
        printf("Success opening object %S\n", event_name);
    }
    return session;
}

static
HANDLE notifyChangeSession(HANDLE* session) {
    static HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll");
    static const auto NtNotifyChangeSessionFunc = (NtNotifyChangeSession)::GetProcAddress(ntdll, "NtNotifyChangeSession");
    if (!NtNotifyChangeSessionFunc) {
        fprintf(stderr, "Cannot load NtNotifyChangeSession function. Error: %u\n", ::GetLastError());
        return NULL;
    }


    static const auto RtlInitUnicodeStringFunc =
        reinterpret_cast<decltype(&::RtlInitUnicodeString)>(GetProcAddress(ntdll, "RtlInitUnicodeString"));
    if (!RtlInitUnicodeStringFunc) {
        fprintf(stderr, "Cannot load RtlInitUnicodeString function. Error: %u\n", ::GetLastError());
        return NULL;
    }
   
    struct driverData drdata;

    NTSTATUS status = NtNotifyChangeSessionFunc(session, 0, 0, 1,
        4, 4, &drdata, sizeof(struct driverData));

    if (!NT_SUCCESS(status)) {
        fprintf(stderr, "Error calling NtNotifyChangeSessionFunc. Error: 0x%08X\n", status);
        return NULL;
    }
    else {
        printf("Success calling NtNotifyChangeSessionFunc\n");
    }

    return nullptr; // ToDo change  
}


static
int closeSession(HANDLE& session) {
    static HMODULE ntdll = ::GetModuleHandleW(L"ntdll.dll");
    static const auto NtCloseFunc = (NtClose1)::GetProcAddress(ntdll, "NtClose");
    if (!NtCloseFunc) {
        fprintf(stderr, "Cannot load NtCloseFunc function. Error: %u\n", ::GetLastError());
        return -1;
    }

    NTSTATUS status = NtCloseFunc(session);

    if (!NT_SUCCESS(status)) {
        fprintf(stderr, "Cannot close session\n");
        return -1;
    }
    else {
        printf("Success closing session\n");
    }

    return 0;
}

int main(int argc, char* argv[]) {

    HANDLE session = { 0 };
    OpenKernelSession(L"\\KernelObjects\\Session0", &session);

    notifyChangeSession(&session);

    Sleep(2000);

    return closeSession(session);
}

Opening the object works fine but calling NtNotifyChangeSession errors with:

STATUS_INVALID_HANDLE 0xC0000008 An invalid HANDLE was specified.

I guess two things may be happening:

Thank you very much in advance.

Upvotes: 1

Views: 376

Answers (1)

Luke
Luke

Reputation: 11421

Your notifyChangeSession() function takes a pointer to a handle instead of a handle.

Upvotes: 1

Related Questions