@ThatsBerkan said:
MiWalkPageTables and MiWalkPageTablesRecursively.
These functions like I stated, are NOT exported, INTERNAL to Windows 10, so you won’t find any documentation online.
You need to learn to use a disassembler program if you want to continue that path to catch cheaters.
Now to your other question, let me respond with what happens when you allocate memory in the System Process:
- The function turns your allocation size to a count of pages using the
BYTES_TO_PAGES(NumberOfBytes)
macro.
We will call the result of that macro NumberOfPages
.
- The function reserves
NumberOfPages
amount of PTE entries.
- Using a for-loop on the
NumberOfPages
, it will allocate pages of memory (a page is 0x1000 bytes) by calling MiGetPage()
(optionally specifying a “color”).
- For each of thoses pages we just allocated, we will set their id to the PTEs we’ve previously reserved, so the PTEs points to that physical memory (the page(s)).
- One or multiple PFN entries are added to the
MmPfnDatabase
, describing which process owns thoses pages, and their state.
So as you can see, 2 things changed on the system after allocating memory in the System Process.
The MmPfnDatabase
array, and the PTE entries. Which means there is only 2 ways (afaik) of detecting what you’re trying to achieve. Now what’s harder is defining what is a valid executable page and what is not. The kernel does have executable memory outside of the allocation done for drivers codes sections. Previous to 1909 I believe (or 2004 ?), the documentation changed, all allocations are executable by default and you have to opt-in to use a Nx (non-executable) variant. Literally all drivers to this day uses the ExAllocatePool(NonPagedPool) and not ExAllocatePool(NonPagedPoolNx). The integrity/security of the allocations done by drivers wasn’t really a thing developers took care of, until those last years.
Also the System Process doesn’t have VAD entries to back up the kernel range allocations, so you can’t even compare to that, like you would do for a user address. Each process also has its own kernel page tables entries (the upper 256 to 512 entries), even thought the kernel is accessible in every processes. It’s sort-of “synchronized” between processes. But a cheater can finely modify it and make it point somewhere else in a specific process. So you even have that to take care of. It can be achieved, but it’s an enormous work to do. You need experience and a good understanding of Windows’ internals (and I’m not talking about the book there, I’m talking about hard and pure messing with Windows 10’s code, something experienced cheat developers do nearly everyday).
It used to be a common thing to call cheaters “kids living in mom’s basement”. It’s true for most of them, sure. But today ? It’s another story. As Peter stated, you “have to assume they are smarter than you are”. People DO THIS FOR A LIVING. They will do whatever it takes. Good luck.
Thank you for the detailed answer, OK so MiWalkPageTables/MiWalkPageTablesRecursively are only available in Windows 10, correct? because if so, we can’t use this approach. we need to cover all versions vista+
so other than parsing page tables, what other techniques do you suggest for solving this issue? do you think using pool descriptors is possible for solving this? or any other method? considering how vast the kernel is, there has to be many methods of finding executable regions in kernel.
@Daniel_Terhell said:
In principle, drivers need to be signed. So the cheaters would need to boot the system with driver signing disabled or test signing enabled. Consider adding a non-signed and test-signed driver with your product and see if they load (or check the boot configuration). If they do then stop the show.
//Daniel
Oh believe me, finding these in kernel is our best shot right now, you won’t believe the amount of stolen certificate, bought/new certificates that these cheaters use, also there is a sea of exploitable drivers out there that they use to load their drivers. blocking them or detecting exploiting drivers is not an option right now, trust me we tried its not gonna work.
but right now i am not even worried about other methods, the task that was giving to me is solving this issue by finding executable regions in kernel, so any help is appreciated, i am just looking to find ALL the possible ways of solving this issue. so far the only good way i found is parsing page tables.