Wednesday, January 23, 2019

Walking Windows 10 process list with WinDbg

This post is based on me refreshing my knowledge about processes in Windows and is based primarily on Ami Awbadhho article on his Jump$ blog. While that post focused on 32 bit Windows, I'm looking more at my Windows 10 64 bit.

To begin walking the Windows process list, we have to start by first enabling kernel mode debugging on our host. To enable kernel mode debugging on Windows 10, I did the following within an "Administrator" command prompt (cmd.exe).

C:\WINDOWS\system32>bcdedit /debug ON
The operation completed successfully.

Once the computer rebooted and I started WinDbg, the next thing was to take a look at what the doubly linked list structure looks like.

lkd> dt _LIST_ENTRY
nt!_LIST_ENTRY
   +0x000 Flink            : Ptr64 _LIST_ENTRY
   +0x008 Blink            : Ptr64 _LIST_ENTRY

Note: to get help on the commands I've used, in the input bar of the WinDbg "command" window, execute ".hh" and this will bring up the help screen. Once in there search for your command to learn what they do.

Above, we see that the list has two entries. One is the "Flink" and the second is the "Blink". To understand how these are used, we can look at the following blog post on "Kernel-Mode Basics: Windows Linked Lists" from the folks at OSR Online.
 
To begin walking the list, we need to find the head of this list. We can do this by looking at "nt!PsActiveProcessHead".

lkd> x nt!PsActiveProcessHead
fffff800`625ad3b0 nt!PsActiveProcessHead = <no type information>

From above, we see that our Active Process Head can be found at address "fffff800`625ad3b0".

Now that we have the pointer to the list, let's see what its Flink and Blink points to:

lkd> dt _LIST_ENTRY fffff800`625ad3b0
nt!_LIST_ENTRY
 [ 0xffff998b`c62cb328 - 0xffff998b`e9ae9368 ]
   +0x000 Flink            : 0xffff998b`c62cb328 _LIST_ENTRY [ 0xffff998b`c636b328 - 0xfffff800`625ad3b0 ]
   +0x008 Blink            : 0xffff998b`e9ae9368 _LIST_ENTRY [ 0xfffff800`625ad3b0 - 0xffff998b`e636d368 ]

Ok! From above we see some values returned for the Flink and Blink. Let's now learn where within the EPROCESS structure is the _LIST_ENTRY for "ActiveProcessLinks" found. Rather than list the entire EPROCESS structure, I've taken a bit of a short cut by specifying the "-y" option to get the specific field.

lkd> dt nt!_EPROCESS -y ActiveProcessLinks
   +0x2e8 ActiveProcessLinks : _LIST_ENTRY

To help get further clarity, let's pick on a process which is currently running. To see the list of processes currently known by the Kernel, let's use the "!process" extension.

lkd> !process 0 0
**** NT ACTIVE PROCESS DUMP ****
PROCESS ffff998bc62cb040
    SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 001aa002  ObjectTable: ffffd605aca14040  HandleCount: 6914.
    Image: System
....

PROCESS ffff998bd5c3b080
    SessionId: 1  Cid: 1858    Peb: baa6893000  ParentCid: 13d8
    DirBase: 31d200002  ObjectTable: 00000000  HandleCount:   0.
    Image: notepad.exe

PROCESS ffff998bd6303080
    SessionId: 1  Cid: 234c    Peb: e97bb99000  ParentCid: 198c
    DirBase: 3dc400002  ObjectTable: 00000000  HandleCount:   0.
    Image: firefox.exe

....

Above, we see a snapshot of some of the process returned from my use of "!process 0 0". Let's pick on "notepad.exe" at address "ffff998bd5c3b080"

lkd> !process 0xffff998bd5c3b080 0
PROCESS ffff998bd5c3b080
    SessionId: 1  Cid: 1858    Peb: baa6893000  ParentCid: 13d8
    DirBase: 31d200002  ObjectTable: 00000000  HandleCount:   0.
    Image: notepad.exe

Now that we have the process at the address and confirm it is "notepad.exe", let's now look at the EPROCESS structure of it.

lkd> dt nt!_EPROCESS ffff998bd5c3b080 -y ActiveProcessLinks
   +0x2e8 ActiveProcessLinks : _LIST_ENTRY [ 0xffff998b`d6303368 - 0xffff998b`d3d2c868 ]

From above, just as we saw before the "ActiveProcessLinks" can be found at +0x2e8. Therefore, to confirm if we subtract 0x2e8 from ffff998bd5c3b080, we will get to the head of the EPROCESS structure, let's test that theory.

lkd> dt nt!_EPROCESS ffff998bd5c3b080-0x2e8
   +0x000 Pcb              : _KPROCESS
   +0x2d8 ProcessLock      : _EX_PUSH_LOCK
   +0x2e0 UniqueProcessId  : 0xffffd605`b6216ea6 Void
   +0x2e8 ActiveProcessLinks : _LIST_ENTRY [ 0x00000001`00b60003 - 0xffff998b`d5c3b088 ]
   +0x2f8 RundownProtect   : _EX_RUNDOWN_REF
   +0x300 Flags2           : 0xd5c3b098
   +0x300 JobNotReallyActive : 0y0
   +0x300 AccountingFolded : 0y0
   +0x300 NewProcessReported : 0y0
.....

From above we see we are at the top of the EPROCESS structure. Let's move on to see how we can map the rest of the processes. To do so, let's do like Ami and go back to something we did before. That is to once again, figure out the head of the list by looking at the address of "PSActiveProcessHead".

lkd> x nt!PsActiveProcessHead
fffff800`625ad3b0 nt!PsActiveProcessHead = <no type information>

Once again, we get the value we had before in "fffff800`625ad3b0". Now that we have this, let's look at the _LIST_ENTRY once again.

lkd> dt nt!_LIST_ENTRY fffff800`625ad3b0
 [ 0xffff998b`c62cb328 - 0xffff998b`ea802568 ]
   +0x000 Flink            : 0xffff998b`c62cb328 _LIST_ENTRY [ 0xffff998b`c636b328 - 0xfffff800`625ad3b0 ]
   +0x008 Blink            : 0xffff998b`ea802568 _LIST_ENTRY [ 0xfffff800`625ad3b0 - 0xffff998b`e7b2b868 ]

Once again, the values look similar to what we saw before. Let's use the Flink value "0xffff998b`c62cb328" to begin walking the list. Do remember, we need to subtract "0x2e8" to get to the beginning of the next EPROCESS structure. Let's do that and grab the "ImageFileName" and the "ActiveProcessLinks" of the next process.

lkd> dt nt!_EPROCESS 0xffff998b`c62cb328-0x2e8 -y ActiveProcessLinks.Flink -y ActiveProcessLinks.Blink -y ImageFileName
   +0x2e8 ActiveProcessLinks       :  [ 0xffff998b`c636b328 - 0xfffff800`625ad3b0 ]
      +0x000 Flink                    : 0xffff998b`c636b328 _LIST_ENTRY [ 0xffff998b`d0e97868 - 0xffff998b`c62cb328 ]
      +0x008 Blink                    : 0xfffff800`625ad3b0 _LIST_ENTRY [ 0xffff998b`c62cb328 - 0xffff998b`ea78e468 ]
   +0x450 ImageFileName            : [15]  "System"

From above we see the first process is "System". We also see for it's "ActiveProcessLinks.Flink" that is the next process, it is at  "0xffff998b`c636b328" while the "ActiveProcessLinks.Blink" is at "0xfffff800`625ad3b0". Let's use the same logic we did previously to learn what is the next process seen by the Kernel after the "System" process. Do remember to once again subtract "0x2e8" from the "ActiveProcessLinks.Flink" value you received above.

lkd> dt nt!_EPROCESS 0xffff998b`c636b328-0x2e8 -y ActiveProcessLinks.Flink -y ActiveProcessLinks.Blink -y ImageFileName
   +0x2e8 ActiveProcessLinks       :  [ 0xffff998b`d0e97868 - 0xffff998b`c62cb328 ]
      +0x000 Flink                    : 0xffff998b`d0e97868 _LIST_ENTRY [ 0xffff998b`da09e868 - 0xffff998b`c636b328 ]
      +0x008 Blink                    : 0xffff998b`c62cb328 _LIST_ENTRY [ 0xffff998b`c636b328 - 0xfffff800`625ad3b0 ]
   +0x450 ImageFileName            : [15]  "Registry"

Above, we see the next process is the "Registry". Let's do two more examples to see if this pattern continues.

lkd> dt nt!_EPROCESS 0xffff998b`d0e97868-0x2e8 -y ActiveProcessLinks.Flink -y ActiveProcessLinks.Blink -y ImageFileName
   +0x2e8 ActiveProcessLinks       :  [ 0xffff998b`da09e868 - 0xffff998b`c636b328 ]
      +0x000 Flink                    : 0xffff998b`da09e868 _LIST_ENTRY [ 0xffff998b`d085b868 - 0xffff998b`d0e97868 ]
      +0x008 Blink                    : 0xffff998b`c636b328 _LIST_ENTRY [ 0xffff998b`d0e97868 - 0xffff998b`c62cb328 ]
   +0x450 ImageFileName            : [15]  "smss.exe"

... and finally for the Flink ...

lkd> dt nt!_EPROCESS 0xffff998b`da09e868-0x2e8 -y ActiveProcessLinks.Flink -y ActiveProcessLinks.Blink -y ImageFileName
   +0x2e8 ActiveProcessLinks       :  [ 0xffff998b`d085b868 - 0xffff998b`d0e97868 ]
      +0x000 Flink                    : 0xffff998b`d085b868 _LIST_ENTRY [ 0xffff998b`d0859868 - 0xffff998b`da09e868 ]
      +0x008 Blink                    : 0xffff998b`d0e97868 _LIST_ENTRY [ 0xffff998b`da09e868 - 0xffff998b`c636b328 ]
   +0x450 ImageFileName            : [15]  "csrss.exe"

Looks good so far. Let's verify this by looking by at the "!process" extension.

kd> !process 0 0
**** NT ACTIVE PROCESS DUMP ****
PROCESS ffff998bc62cb040
    SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 001aa002  ObjectTable: ffffd605aca14040  HandleCount: 7052.
    Image: System

PROCESS ffff998bc636b040
    SessionId: none  Cid: 0060    Peb: 00000000  ParentCid: 0004
    DirBase: 1e0c00002  ObjectTable: ffffd605aca28c00  HandleCount:   0.
    Image: Registry

PROCESS ffff998bd0e97580
    SessionId: none  Cid: 01d4    Peb: 65129c2000  ParentCid: 0004
    DirBase: 296d10002  ObjectTable: ffffd605af644540  HandleCount:  52.
    Image: smss.exe

PROCESS ffff998bda09e580
    SessionId: 0  Cid: 02a8    Peb: 705bc80000  ParentCid: 028c
    DirBase: 199900002  ObjectTable: ffffd605ae720c00  HandleCount: 756.
    Image: csrss.exe

PROCESS ffff998bd085b580
    SessionId: 0  Cid: 0304    Peb: 3aa038000  ParentCid: 028c
    DirBase: 45bc00002  ObjectTable: ffffd605af212380  HandleCount: 155.
    Image: wininit.exe

PROCESS ffff998bd0859580
    SessionId: 1  Cid: 030c    Peb: 5e45a62000  ParentCid: 02f8
    DirBase: 334200002  ObjectTable: ffffd605aea12680  HandleCount: 1213.
    Image: csrss.exe

PROCESS ffff998bda3ea480
    SessionId: 0  Cid: 0354    Peb: a3794a6000  ParentCid: 0304
    DirBase: 19a00002  ObjectTable: ffffd605afc25e80  HandleCount: 847.
    Image: services.exe

PROCESS ffff998bd85e8580
    SessionId: 0  Cid: 0368    Peb: 6c5042e000  ParentCid: 0304
    DirBase: 107a00002  ObjectTable: ffffd605afd3b8c0  HandleCount: 1749.
    Image: lsass.exe

PROCESS ffff998bd8e25080
    SessionId: 1  Cid: 03a4    Peb: 35e2b86000  ParentCid: 02f8
    DirBase: 46a800002  ObjectTable: ffffd605b091f600  HandleCount: 256.
    Image: winlogon.exe

....

PROCESS ffff998bea2e4580
    SessionId: 1  Cid: 26cc    Peb: 1002d1000  ParentCid: 0f34
    DirBase: 4a700002  ObjectTable: ffffd605b9b0a040  HandleCount: 142.
    Image: SystemIdleCheck.exe

PROCESS ffff998bf5ea0380
    SessionId: 0  Cid: 27ac    Peb: ce9260a000  ParentCid: 0354
    DirBase: 61900002  ObjectTable: ffffd605c637b680  HandleCount: 192.
    Image: WmiApSrv.exe
The snapshot above looks to tie in nicely with what we have learned so far. I believe if we continue this pattern, we will be able to walk the tree and identify all the processes via the Flink. However, we did not verify the Blink. Let's test a few of those before we move on.

Believe it or not, it is just the same as we did above. Only difference is instead of using the address in the Flink, we instead use the addresses in the Blink.

Let's look at the "Registry" process to see what it points to via its Blink.

lkd> !process ffff998bc636b040 0
PROCESS ffff998bc636b040
    SessionId: none  Cid: 0060    Peb: 00000000  ParentCid: 0004
    DirBase: 1e0c00002  ObjectTable: ffffd605aca28c00  HandleCount:   0.
    Image: Registry

Let's look at its "ActiveProcessLinks.Flink" and "ActiveProcessLinks.Blink".

lkd> dt nt!_EPROCESS ffff998bc636b040 -y ActiveProcessLinks.Flink -y ActiveProcessLinks.Blink -y ImageFileName
   +0x2e8 ActiveProcessLinks       :  [ 0xffff998b`d0e97868 - 0xffff998b`c62cb328 ]
      +0x000 Flink                    : 0xffff998b`d0e97868 _LIST_ENTRY [ 0xffff998b`da09e868 - 0xffff998b`c636b328 ]
      +0x008 Blink                    : 0xffff998b`c62cb328 _LIST_ENTRY [ 0xffff998b`c636b328 - 0xfffff800`625ad3b0 ]
   +0x450 ImageFileName            : [15]  "Registry"

If we now look at the Blink value to see where it points, we see we get:

lkd> dt nt!_EPROCESS 0xffff998b`c62cb328-0x2e8 -y ActiveProcessLinks.Flink -y ActiveProcessLinks.Blink -y ImageFileName
   +0x2e8 ActiveProcessLinks       :  [ 0xffff998b`c636b328 - 0xfffff800`625ad3b0 ]
      +0x000 Flink                    : 0xffff998b`c636b328 _LIST_ENTRY [ 0xffff998b`d0e97868 - 0xffff998b`c62cb328 ]
      +0x008 Blink                    : 0xfffff800`625ad3b0 _LIST_ENTRY [ 0xffff998b`c62cb328 - 0xffff998b`ea5a35a8 ]
   +0x450 ImageFileName            : [15]  "System"

Nice!!! As expected, "Registry" Blink points to the previous process in the list which is "System". Let's look at one more. Once again, considering what we looked at previously, let's look at the "smss.exe" process to see where that points. If all goes according to plan, its Blink should be pointing to "Registry". Let's see if this holds true.

lkd> !process ffff998bd0e97580 0
PROCESS ffff998bd0e97580
    SessionId: none  Cid: 01d4    Peb: 65129c2000  ParentCid: 0004
    DirBase: 296d10002  ObjectTable: ffffd605af644540  HandleCount:  52.
    Image: smss.exe

Let's look at its "ActiveProcessLinks.Flink" and "ActiveProcessLinks.Blink".

lkd> dt nt!_EPROCESS ffff998bd0e97580 -y ActiveProcessLinks.Flink -y ActiveProcessLinks.Blink -y ImageFileName
   +0x2e8 ActiveProcessLinks       :  [ 0xffff998b`da09e868 - 0xffff998b`c636b328 ]
      +0x000 Flink                    : 0xffff998b`da09e868 _LIST_ENTRY [ 0xffff998b`d085b868 - 0xffff998b`d0e97868 ]
      +0x008 Blink                    : 0xffff998b`c636b328 _LIST_ENTRY [ 0xffff998b`d0e97868 - 0xffff998b`c62cb328 ]
   +0x450 ImageFileName            : [15]  "smss.exe"

Let's now test the Blink value of "0xffff998b`c636b328" to see where it points.


lkd> dt nt!_EPROCESS 0xffff998b`c636b328-0x2e8 -y ActiveProcessLinks.Flink -y ActiveProcessLinks.Blink -y ImageFileName
   +0x2e8 ActiveProcessLinks       :  [ 0xffff998b`d0e97868 - 0xffff998b`c62cb328 ]
      +0x000 Flink                    : 0xffff998b`d0e97868 _LIST_ENTRY [ 0xffff998b`da09e868 - 0xffff998b`c636b328 ]
      +0x008 Blink                    : 0xffff998b`c62cb328 _LIST_ENTRY [ 0xffff998b`c636b328 - 0xfffff800`625ad3b0 ]
   +0x450 ImageFileName            : [15]  "Registry"

Nice!! Very Nice!!! So we confirm that the Flink and Blink points to the next process structure and the previous structure respectively.

Now for the image below. The image below represents a snapshot of what we saw above. However, I did not map all processes but the concept remains the same.









Well hope you enjoyed this post.

As always, do leave a comment if you think I missed something.

Reference:
http://jumpdollar.blogspot.com/2014/09/windbg-walking-windows-linked-lists.html
http://www.osronline.com/article.cfm?article=499
https://www.blackhat.com/presentations/win-usa-04/bh-win-04-butler.pdf

No comments:

Post a Comment