Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results


More Info on Driver Writing and Debugging

The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.

Check out The OSR Learning Library at:

Before Posting...

Please check out the Community Guidelines in the Announcements and Administration Category.

Can't read some, presumably valid, kernel memory (in win32k.sys) from my driver

DavidXanatosDavidXanatos Member Posts: 19
edited September 3 in NTDEV


I'm trying to read the SSDT from Win32k.sys the address is set by KeAddSystemServiceTable as well as a counter.

struct _EX_CALLBACK Win32CallBack;
struct _KSERVICE_TABLE_DESCRIPTOR ServiceDescriptorTableShadow[2];
struct _KSERVICE_TABLE_DESCRIPTOR ServiceDescriptorTableFilter[2];

unsigned long *Base;
unsigned long *Reserved1;
unsigned long Limit;
unsigned int *Number;

my code successfully finds the ServiceDescriptorTableShadow[0] with valid data
and as far as I can tell ServiceDescriptorTableShadow[1] which contains the table for win32k.sys is also right as the Limit value is correct (the aforementioned counter)

The Base array and Number array points to a memory region owned by win32k.sys, according to process hacker,
so presumably the address should be valid. Also it seams to me that KiServiceInternal is accessing said address.

But when I try to read a value from that address in my driver I get a bug check (page fault) when testing with MmIsAddressValid it seams that i cant access any address from the range of the win32k.sys driver as well as no address from win32kbase.sys, win32kfull.sys and cdd.dll same behavior on different systems.
I have also noticed that the memory range of these 4 modules is different than the ranges used by all other drivers including ntoskrnl.exe
And on a random test it seams that I can read the base addresses of any other drivers except these 4.

So whats up with that?
1. why can't I read the memory at these addresses?
2. how does ntoskrnl.exe, when in KiServiceInternal or other function (KiSystemService and etc....), access this memory ?

My goal is to get the service routine addresses and call them directly from my driver, doing this for normal ntoskrnl.exe syscalls works just fine, just the win32k.sys seams particularly stubborn, and I don't understand why, the address is valid and plausible, yet it is not readable and causes a page fault.
There must be a way around this also I would like to understand why this odd behavior.


  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 8,671
    > My goal is to get the service routine addresses and call them directly from my driver

    Why on **earth** would you want to do that. Obviously, I that is not the proper way to invoke a system service.


    Peter Viscarola

  • ThatsBerkanThatsBerkan Member Posts: 61

    Win32k is not mapped in the system process, it is only mapped in usermode processes that deal with GUI/Rendering stuff and input processing. (The session id is different)

  • DavidXanatosDavidXanatos Member Posts: 19

    @Peter_Viscarola_(OSR) said:

    My goal is to get the service routine addresses and call them directly from my driver

    Why on earth would you want to do that. Obviously, I that is not the proper way to invoke a system service.


    Yes obviously, hence apparently I must have a good reason to do it this adventurous way ;)

    For a sandboxing project I want to filter all syscalls by hooking ntdll and win32u dll on a way that all sys calls go through an interface in my driver where they can be filtered and inspected before being executed.
    And sure I know when the process would remove the hooks or load a clean copy it could bypass these, hence there are other mechanisms in place to. How ever elaborating on those would be off topic for the problem at hand.

    I have found the solution:

    PEPROCESS pProcess;
    KAPC_STATE ApcState;
    PsLookupProcessByProcessId((HANDLE)588,&pProcess); //588is the csrss.exe Id: todo look up the actual id
    KeStackAttachProcess(pProcess, &ApcState);

    // here i can access the memory muhahahahahahah....

  • DavidXanatosDavidXanatos Member Posts: 19

    How I have an other problem at hand, the first win32k syscall must trigger KiConvertToGuiThread unfortunately neider this nor PsConvertToGuiThread is exported, so what would be the propper way to call a sys call from kernel space, such that I could route the first call normally to trigger that function. Alternatively I would need to find the address of KiConvertToGuiThread and call it.

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 8,671

    hence apparently I must have a good reason

    You’re idea of a “good reason” and my idea of a good reason might be different, though. Right?

    What your doing is a (a) a common malware technique, (b) actively prevented by Windows. You know that, right? But you’re asking us how to do it anyway?

    So, this question becomes “Please help me hook the system service table” … right? And the answer here is “no, we won’t”.

    This thread is locked. If the OP has a complaint they can email me.


    Peter Viscarola

This discussion has been closed.

Howdy, Stranger!

It looks like you're new here. Sign in or register to get started.

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Internals & Software Drivers 15 November 2021 Live, Online
Writing WDF Drivers TBD Live, Online
Developing Minifilters 7 February 2022 Live, Online
Kernel Debugging 21 March 2022 Live, Online