My setup: Windows 10 with windbg and target machine is Windows 7 N SP1. I'm debugging via com (i know it's slow ;).

So I get the process list with !process, one active process is Internet Explorer:

kd>!process 0 0

>PROCESS fffffa8001a3db30
>SessionId: 2  Cid: 07e0    Peb: 7efdf000  ParentCid: 0a90
>DirBase: 2cc0a000  ObjectTable: fffff8a002007620  HandleCount: 561.
>Image: iexplore.exe

After that, I want to see in which mode the process is running. So I looked at the content of the PDE at the U/S flags.

kd> !pte FFFFF6FB7EA00068
                                       VA fffff6fd4000d000
>contains 0000000004000863  contains 0000000004001863  contains 000000007FC009E3  contains 0000000000000000
>pfn 4000      ---DA--KWEV  pfn 4001      ---DA--KWEV  **pfn 7fc00     -GLDA--*K*WEV**  LARGE PAGE pfn 7fc9a

The usermode/kernelmode flag is set to K. That says, that iexplorer.exe is running in kernelmode. Why? I thought those aplications are running in usermode.

  • You are mixing up things. 99% of threads of every usermode process eventually transitions into kernel mode for file i/o, sockets, memory management and whatnot. Note that the transition of a thread's call stack from user to kernelmode is a well defined (security) boundary. You can't call any kernelmode functions directly. Sep 21 '17 at 10:02
  • @LievenKeersmaekers please try to avoid posting answers in comments, it's better to post an actual answer.
    – Igor Skochinsky
    Feb 28 '18 at 13:18
  • @IgorSkochinsky - impov, it's not fleshed out enough to serve as an answer and I don't have enough expertise on the subject to write a complete answer but I'll definitely take note! Feb 28 '18 at 17:41

What you have listed in your question isn't going to tell you what mode a process is executing in, and there's a couple things wrong with the thought process.

The help docs for !pte specify that the command takes a Virtual Address and displays PTE and PDE information about that address. The output of this command is kind of unintuitive because in actuality the PTE/PDE entries are physical addresses but Windows also maps them to kernel Virtual Kernel addresses as well.

In your output specifically the virtual address that you're analyzing is VA fffff6fd4000d000. What the output is showing is that the PXE entry for this Virtual Address is at the physical address 4000000 (this is given by the pfn entry and the lower portion is masked off for flags and etc), and is mapped at the virtual address FFFFF6FB7DBEDFA8.

So then the next part is why does the output show that the pages are kernel mode. Based on what you're doing the address you got from !address is fffffa8001a3db30. Without going into too much detail about the internals of the kernel this address is the virtual address for an EPROCESS object which is a kernel data structure used to manage processes on the system. Additionally, every object the kernel allocates has a header prepended to it that the system uses for reference counting and and some other management functionality.

You can see this header structure in windbg using the dt command: dt _OBJECT_HEADER and on x64 you'll notice that this structure is 0x30 bytes big. So the address of the actual EPROCESS is fffffa8001a3db30 but the base of the allocation includes the header which is fffffa8001a3db00.

So basically what you're doing when you run that !pte command is analyzing the page table entries for the kernel EPROCESS object but as I said in the last paragraph this is only a structure that the kernel allocates and uses to manage resources for the system, so this address is always going to be a kernel mode address.

To do what you actually want to do you want to use the following commands:

  • .process /p /r <iexplore.exe address from !process> - this puts you in the process context of internet explorer, which basically means all the usermode stuff (virtual memory and handles) that windbg accesses are valid for that process
  • !dml_proc <iexplorer address from !process> or !process <iexploer address from !process - this gives you information about the threads that are running in that process
  • From there if you use !dml_proc you can click the links to get thread stacks, or !process will just dump all threads out for you

Now, if you follow the above you'll get the stack trace for each thread. From there you can see where it's executing based on what module it's in. In particular, if you see nt!KiSystemServiceCopyEnd on the callstack that means that the thread has transitioned into kernel mode and is doing something.

However that being said I'm still not sure what you want to achieve since as one of the comments on your post mentions all threads are going to transition to kernel mode all the time anyway because basically everything that happens on your system happens in kernel mode.


On the pte command you use an address from where did you get that address FFFFF6FB7EA00068 <<<<<

If it is a virtual address does it truly belong to the active process context ?

are you in the process context of iexplore.exe ??
(did you do .process /p /r EPROC_ADDR )

just doing .process /p /r changes only the display in windbg and the actual underlying process may not be equal to the current process context

did you check if the process contexts DirectoryTableBase (DirBase) and register cr3 matches or not ??

if they don't match you might be looking at some spurious address that belongs to some other process context which might have the same virtual address

if it didnt match you may need to do .process /i and execute the target with g or f5

this makes windbg debug the underlying process invasively and when it rebreaks
after a few seconds the process you are interested in (iexplore.exe in your case)
will be set as active process context and page table entries are decoded with respect to active process context
( register cr3 and @$proc->Pcb.DirectoryTableBase will match and show same DirBase)

only when you are truly sure you have an active process context your question might make a reproducible query

a sample

target and host both are win7 sp1 32 bits (target is a vm)
windbg version is latest rtm as on the day of posting

Microsoft (R) Windows Debugger Version 10.0.16299.15 X86

target broken into windbg using ctrl+break

checking current cr3
kd> r cr3

checking for iexplore.exe process instance

kd> !process 0 0 iexplore.exe
PROCESS 841f3c08  SessionId: 1  Cid: 059c    Peb: 7ffdf000  ParentCid: 0774
    DirBase: 096de000  ObjectTable: 92aed4d0  HandleCount: 419.
    Image: iexplore.exe

PROCESS 841ce5d8  SessionId: 1  Cid: 0784    Peb: 7ffdf000  ParentCid: 059c
    DirBase: 0db73000  ObjectTable: 8b221ba0  HandleCount: 350.
    Image: iexplore.exe

command to see if iexplore module is available

kd> lm m iexp*
Browse full module list
start    end        module name

Unable to enumerate user-mode unloaded modules, Win32 error 0n30

no windbg is not in the correct process context
lets ask it to get into correct process context
keep in mind this is a display and not the targets state
see .cache (windbg refreshes the display from its cached

you can notice module iexplore.exe is now available for inspection

kd> .process /p /r 841ce5d8
Implicit process is now 841ce5d8
.cache forcedecodeuser done
Loading User Symbols

kd> lm m iexp*
Browse full module list
start    end        module name
00af0000 00b96000   iexplore   (deferred)             
kd> x iexplore!wWinMain
00af12a3          iexplore!wWinMain (<no parameter info>)

but the !pte for a virtual address in this
cached process context space is invalid because we are not in
active process context ( register cr3 and DirBase dont match)
to get into active process context windbg should
be debugging the targets process invasively
which is possible only if we do a .process /i

kd> !pte iexplore!wWinMain
                 VA 00af12a3
PDE at C0300008         PTE at C0002BC4
contains 00000000
not valid

kd> r cr3

kd> ?? @$proc->Pcb.DirectoryTableBase
unsigned long 0xdb73000

lets ask windbg to invasively debug iexplore.exe and
break when the process context is active

kd> .process /i /p /r /P 841ce5d8
You need to continue execution (press 'g' <enter>) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.
kd> g
Break instruction exception - code 80000003 (first chance)
8289dd00 cc              int     3

now you can see both the register context and Dirbase matches

kd> r cr3

kd> ?? @$proc->Pcb.DirectoryTableBase
unsigned long 0xdb73000

kd> !pte iexplore!wWinMain
                 VA 00af12a3
PDE at C0300008         PTE at C0002BC4
contains 0DD71867       contains 07B5F005
pfn dd71  ---DA--UWEV   pfn 7b5f  -------UREV

pte enties are valid now 

you can further match va to physical page contents as below

kd> !pte iexplore!wWinMain
                 VA 00af12a3
PDE at C0300008         PTE at C0002BC4
contains 0DD71867       contains 07B5F005
pfn dd71  ---DA--UWEV   pfn 7b5f  -------UREV

kd> db iexplore!wWinMain l 20
00af12a3  8b ff 55 8b ec 81 ec 30-01 00 00 a1 50 c0 af 00  ..U....0....P...
00af12b3  33 c5 89 45 fc 53 56 57-be 88 c5 af 00 56 e8 cb  3..E.SVW.....V..

kd> $$ from the !pte above we know pfn is at 7b5f 
kd> $$ we can confirm if this is the right physical page with either 
kd> $$ !vtop 0 va or simply adding the last 3 bytes of our va to the pfn 
kd> $$and dump the physical page 

dump of physical address contents

kd> !db 7b5f2a3 l20
# 7b5f2a3 8b ff 55 8b ec 81 ec 30-01 00 00 a1 50 c0 af 00 ..U....0....P...
# 7b5f2b3 33 c5 89 45 fc 53 56 57-be 88 c5 af 00 56 e8 cb 3..E.SVW.....V..

as seen virtual address content and physical page contents match
but lets look for a string that might be unique and reconfirm

kd> s -a iexplore!wWinMain L?100000 "Internet Explorer_Server"
00bb7df8  49 6e 74 65 72 6e 65 74-20 45 78 70 6c 6f 72 65  Internet Explore
kd> da /c 100 bb7df8
00bb7df8  "Internet Explorer_Server"

kd> !pte bb7df8
                 VA 00bb7df8
PDE at C0300008         PTE at C0002EDC
contains 0DD71867       contains 0D7B1025
pfn dd71  ---DA--UWEV   pfn d7b1  ----A--UREV

kd> !db d7b1df8 l 20
# d7b1df8 49 6e 74 65 72 6e 65 74-20 45 78 70 6c 6f 72 65 Internet Explore
# d7b1e08 72 5f 53 65 72 76 65 72-00 00 00 00 00 00 00 00 r_Server........

kd> !vtop 0 bb7df8
X86VtoP: Virt 0000000000bb7df8, pagedir 000000000db73000
X86VtoP: PDE 000000000db73008 - 0dd71867
X86VtoP: PTE 000000000dd71edc - 0d7b1025
X86VtoP: Mapped phys 000000000d7b1df8
Virtual address bb7df8 translates to physical address d7b1df8.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.