Search code examples
debuggingwindowkernelwindbg

When Kernel Debugging - Find The Page Protection of a User Mode Address


While kernel debugging a windows (XP SP3) machine, I would like to find the page protection of a user mode address (actually just to check if it's a No-Execute page).

The extension !vprot (which does just that) doesn't work when kernel debugging.

I tried to change into this user mode address space (using '.process /i') and then call !pte on the address. But sometimes, the PTE entry is invalid, because it's paged out (I think).

Any suggestions?


Solution

  • You might try a combination of !vad and !address:

    0: kd> !process 0 0 calc.exe
    PROCESS 89e035f8  SessionId: 0  Cid: 021c    Peb: 7ffdd000  ParentCid: 00d4
        DirBase: 0aac0200  ObjectTable: e1f587a8  HandleCount:  44.
        Image: calc.exe
    
    0: kd> .process /i 89e035f8  
    

    Using !vad:

    3: kd> !vad 0x1000000
    VAD     level      start      end    commit
    89e02578 (-1)       1000     101e         3 Mapped  Exe  EXECUTE_WRITECOPY  \WINDOWS\system32\calc.exe
    3: kd> !vad 0x1014000
    VAD     level      start      end    commit
    89e02578 (-1)       1000     101e         3 Mapped  Exe  EXECUTE_WRITECOPY  \WINDOWS\system32\calc.exe
    

    The problem is that the !vad command gives you only the VAD (Virtual AQddress Descripptor) for the whole page range, which is more precisely the size of the VAD segment. Obviously the pages at 0x1000000 [PE Header] and 0x1014000 [.data section] haven't the same protections.

    Using !address:

    Note that the !address command will map a lot of things (including PTEs / PFNs and VADs):

    3: kd> !address 0x1000000
    Mapping user range ...
    Mapping system range ...
    Mapping page tables...
    Mapping hyperspace...
    Mapping HAL reserved range...
    Mapping User Probe Area...
    Mapping system shared page...
    Mapping system cache working set...
    Mapping loader mappings...
    Mapping system PTEs...
    Mapping system paged pool...
    Mapping session space...
    Mapping dynamic system space...
    Mapping PFN database...
    Mapping non paged pool...
    Mapping VAD regions...
    Mapping module regions...
    Mapping process, thread, and stack regions...
    Mapping system cache regions...
    

    Use the -v and -map options:

    3: kd> !address -v -map 0x1000000
    PDE:    c0600040 [contains 20b9a867]
    
            Page Frame Number:  20b9a, at address: 00000000
            Page Location:      6 (ActiveAndValid)
            PTE Frame:          00020a98
            Attributes:         M:Modified,Cached
            Usage:              PTEs Process 89e035f8 [calc.exe], Entries:22
    
    PTE:    c0008000 [contains 20d86025]
    
            Page Frame Number:  20d86, at address: 00000000
            Page Location:      6 (ActiveAndValid)
            PTE Frame:          00020384
            Attributes:         P:Prototype,M:Modified,Cached
            Usage:              MappedFile CA:8a1282e0 [\WINDOWS\system32\calc.exe]
            
    Type:   Valid
    Attrs:  Private,NormalPage,NotDirty,NotDirty1,Accessed,User,NotWritable,NotWriteThrough
    PFN:    20d86
           
           
    

    The Attrs output gives useful information. You might be able to use the !pte command at this point:

    3: kd> !pte c0008000
                        VA 01000000
    PDE at C0600040            PTE at C0008000
    contains 0000000020B9A867  contains 0000000020D86025
    pfn 20b9a     ---DA--UWEV  pfn 20d86     ----A--UREV
    

    The output of !pte gives the PTE bits (to the right), here: ----A--UREV:

    • A: Accessed
    • U: User page
    • R: Read-only
    • E: Executable
    • V: Valid

    Commands Documentation:

    Hope that solve your problem.