Quantcast
Channel: Active questions tagged kernel - Stack Overflow
Viewing all articles
Browse latest Browse all 6393

Allocate page with execution privileges at an arbitrary currently unused virtual address in a windows kernel driver

$
0
0

I'm writing a kernel mode driver (Windows 10 64-bit) where I require code execution at a virtual address in another driver's virtual address space that is currently unused(MmIsAddressValid returns false).

What I have tried:

  1. calling the undocumented ntoskrnl function MiFillPteHierarchy. This function returns 4 pointers one of which is meant to be a pointer to the PTE structure which I would need to change in order to give code execution privileges to the page. I have found that when I deference these pointers I get a page segmentation fault BSOD. The function works fine when I give it an address for which MmIsAddressValid returns true(which is to be expected).

The MIFILLPTEHIERARCHY function in ntoskrnl returns 4 virtual addresses corresponding to the PTE,PDE,PDPTE, and PML4E(to the best of my knowledge)Here is the function sig I have:

typedef uint64_t(__fastcall* MIFILLPTEHIERARCHY)(void* virtualaddy, PTE_HIERARCHY* hierarchy);

The PTE_HIERARCHY structure looks like this

struct PTE_HIERARCHY {    PTE* pte;    uint64_t* PDE;    uint64_t* PDPTE;    uint64_t* PML4E;};

(PTE structure is the only one i've made)

as per the INTEL manual I have been reading https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.pdfThe PTE structure looks like this:

union PTE{    uint64_t raw;    struct {        uint64_t present : 1; //Present; must be 1 to map a 4-KByte pag        uint64_t read_write : 1; //Read/write; if 0, writes may not be allowed to the 4-KByte page referenced by this entry (see Section 4        uint64_t user_supervisor : 1; //User/supervisor; if 0, user-mode accesses are not allowed to the 4-KByte page referenced by this entry (see Section 4.6)        uint64_t PWT : 1; //Page-level write-through; indirectly determines the memory type used to access the 4-KByte page referenced by this entry (see Section 4.9.        uint64_t PCD : 1; //Page-level cache disable; indirectly determines the memory type used to access the 4-KByte page referenced by this entry (see Section 4.9.2        uint64_t accessed : 1; //Accessed; indicates whether software has accessed the 4-KByte page referenced by this entry (see Section 4.8        uint64_t dirty : 1; //Dirty; indicates whether software has written to the 4-KByte page referenced by this entry (see Section 4.8)        uint64_t PAT : 1; //Indirectly determines the memory type used to access the 4-KByte page referenced by this entry (see Section 4.9.2)        uint64_t global : 1; //Global; if CR4.PGE = 1, determines whether the translation is global (see Section 4.10); ignored otherwis        uint64_t ignored : 3;        uint64_t physical_page_address : 36; //Physical address of the 4-KByte page referenced by this entry        uint64_t reserved : 4;        uint64_t ignored2 : 7;        uint64_t protection_key : 4; //Protection key; if CR4.PKE = 1, determines the protection key of the page (see Section 4.6.2); ignored otherwise        uint64_t xd : 1; //if IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 4-KByte page controlled by this entry; see Section 4.6); otherwise, reserved (must be 0    }values;};

My implementation:

//enumerate system modulesuint32_t buffersize=0;PRTL_PROCESS_MODULES mods=nullptr;            ZwQuerySystemInformation(SystemModuleInformation,0,buffersize,&buffersize);mods = (PRTL_PROCESS_MODULES)ExAllocatePool(NonPagedPool, buffersize);ZwQuerySystemInformation(SystemModuleInformation, mods, buffersize, &buffersize);//using ACPI as an exampleconst char* drivername = "ACPI.sys";for (uint32_t i = 0; i < mods->NumberOfModules; i++) {    RTL_PROCESS_MODULE_INFORMATION mod = mods->Modules[i];    char currentdriver[0x100] = { 0 };    memcpy(&currentdriver[0], &mod.FullPathName[mod.OffsetToFileName], 8);    if (!strcmp(currentdriver, drivername)) {            imagebase = mod.ImageBase[i]            imagesize=mod.size[i]            break;}}//I then find some unused virtual address in the drivers address space//something like for imagebase < address < infinity (just find some address that is not validif(!MmIsAddressValid(address))targetaddress= addresselseaddress++//query MiFillPteHierarchy for PTE hierarchyPTE_HIERARCHY hierarchy = {0};MiFillPteHierarchy(targetaddress, &hierarchy);hierarchy.PTE->values.present //BSOD here//However if I have a virtual address where MmIsAddressValid returns true;hierarchy.PTE->values.present //NO BSOD 

My idea was to get the PTE structure and modify it such that I have code execution privileges and the OS/CPU doesn't overwrite this virtual memory region with another page.

  1. MmMapLockedPagesSpecifyCache. When I use this method the return pointer is nowhere near where the target virtual address is.

This is my code using this method

//where MmIsAddressValid(targetvirtualaddress)=falsevoid* pool = ExAllocatePool(NonPagedPool/PagePool(tried both),50);memset(pool, 0, 50);PMDL MDL = IoAllocateMdl(pool, 50, false, false, nullptr);MmBuildMdlForNonPagedPool(MDL);void* resultantaddress = MmMapLockedPagesSpecifyCache(MDL, KernelMode, MmNonCached, targetvirtualaddress, false, HighPagePriority);//resultantaddress is nowhere near targetvirtualaddress

Ideally what I would want:

MmIsAddressValid(targetaddress) returns false //windows can overwrite//do something to page hereMmIsAddressValid(targetaddress) returns true //windows wont overwrite//modify PTE to gain code execution privileges 

(To the best of my knowledge if MmIsAddressValid returns true it means windows knows the virtual address is in use and won't try to overwrite it)

I guess my question is why does de-referencing the PTE/PDE for this virtual address that is not being used result in a BSOD(page segmentation fault)? And why does MmMapLockedPagesSpecifyCache not allocate a page anywhere near the target address? And If both of these methods will not work for my purposes what can I do?


Viewing all articles
Browse latest Browse all 6393

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>