Windows Kernel Debugging: Processes

1. Introduction

How to debug the structures that store information about the process in the Windows operating system? This article will answer that question. You will also be introduced to the methods of manipulating the process. Finally, a method of making an existing process similar to a running instance of another program will be presented, using the notepad process and OneDrive.exe as an example. Prepare tea or coffee and feel free to read!

2. Windows process

Before we start looking at existing processes, one should answer the question what exactly is a process? When we talk about a process, we mean an instance of a running program. Each process in Windows has, among others:

3. Initial process analysis in WinDbg

This part of the article will present the methods of obtaining a list of running processes and basic information about this process. The method of presenting the EPROCESS structure instances of a given process will also be presented.

Run WinDBG in the prepared environment or just kd.exe :

C:> "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\kd.exe" -k net:port=50000,key=Win.Kernel.Debug.Env

In order to present the basic debugger commands, I ran the notepad.exe program on the analyzed machine. Let’s take a look at the newly established process.

As a first step, stop the operating system: the WinDBG select Break from the Debug menu or kd.exe session press Ctrl + C

To list running processes, use the command !dml_proc:

kd> !dml_proc
Address           PID  Image file name
ffffbf01`22260400 4    System
ffffbf01`2367c040 118  smss.exe
ffffbf01`243bf780 168  csrss.exe
ffffbf01`244b5780 1ac  smss.exe
ffffbf01`24468640 1b4  wininit.exe
...
ffffbf01`258c6780 11ac backgroundTask
ffffbf01`259a4780 11ec notepad.exe
ffffbf01`257b7780 1264 backgroundTask

A more detailed list of processes can be obtained using the command !process 0 0. However, be careful of the large amount of data supplied to the standard output. We probably won’t be able to use them effectively. It can take a long time for this command to complete, in proportion to the number of processes running.

kd> !process 0 0
**** NT ACTIVE PROCESS DUMP ****
PROCESS ffffbf0122260400
    SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 001aa000  ObjectTable: ffffe10394002340  HandleCount: <Data Not Accessible>
    Image: System

PROCESS ffffbf012367c040
    SessionId: none  Cid: 0118    Peb: 7d6928c000  ParentCid: 0004
    DirBase: 76341000  ObjectTable: ffffe1039468b540  HandleCount: <Data Not Accessible>
    Image: smss.exe

...

If there is a real need to generate detailed data on running processes (e.g. for parsing and later use), you can use the !process 0 7 command, which will list the processes listing most of the available details.

If we are interested in only one specific process, then using its address, you can only enter details of this process. This approach will be much faster and more effective.

So let’s take a look at the process notepad.exe. Its address is ffffbf01`259a4780. For this purpose, let’s use the !process command and list the details of this process:

kd> !process ffffbf01`259a4780 5
PROCESS ffffbf01259a4780
    SessionId: 1  Cid: 11ec    Peb: 2a4e032000  ParentCid: 0ab8
    DirBase: 42280000  ObjectTable: ffffe1039aea1840  HandleCount: <Data Not Accessible>
    Image: notepad.exe
    VadRoot ffffbf012589d260 Vads 83 Clone 0 Private 459. Modified 22. Locked 0.
    DeviceMap ffffe103941a2710
    Token                             ffffe1039adff060
    ElapsedTime                       00:00:35.395
    UserTime                          00:00:00.000
    KernelTime                        00:00:00.000
    QuotaPoolUsage[PagedPool]         238848
    QuotaPoolUsage[NonPagedPool]      11536
    Working Set Sizes (now,min,max)  (3582, 50, 345) (14328KB, 200KB, 1380KB)
    PeakWorkingSetSize                3501
    VirtualSize                       2097271 Mb
    PeakVirtualSize                   2097276 Mb
    PageFaultCount                    3644
    MemoryPriority                    FOREGROUND
    BasePriority                      8
    CommitCharge                      593

        THREAD ffffbf01259a5080  Cid 11ec.11f0  Teb: 0000002a4e033000 Win32Thread: ffffbf012566e8c0 WAIT
        THREAD ffffbf01259de080  Cid 11ec.1200  Teb: 0000002a4e035000 Win32Thread: 0000000000000000 WAIT
        THREAD ffffbf0125a2e080  Cid 11ec.1204  Teb: 0000002a4e037000 Win32Thread: 0000000000000000 WAIT
        THREAD ffffbf0125a30080  Cid 11ec.1208  Teb: 0000002a4e039000 Win32Thread: 0000000000000000 WAIT
        THREAD ffffbf0125a31080  Cid 11ec.120c  Teb: 0000002a4e03b000 Win32Thread: 0000000000000000 WAIT

Information on a given process is stored by Windows in the EPROCESS structure. In order to display the process data stored in the EPROCESS structure, use the command dt:

kd> dt _eprocess ffffbf01`259a4780
ntdll!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   +0x2d8 ProcessLock      : _EX_PUSH_LOCK
   +0x2e0 RundownProtect   : _EX_RUNDOWN_REF
   +0x2e8 UniqueProcessId  : 0x00000000`00000b18 Void
   +0x2f0 ActiveProcessLinks : _LIST_ENTRY [ 0xffffb10f`5d7a9370 - 0xffffb10f`5da12a70 ]
   +0x300 Flags2           : 0x200d000
   ...
   +0x798 DiskIoAttribution : (null)
   +0x7a0 ReadyTime        : 0
   +0x7a8 DxgProcess       : 0x00000000`00000025 Void

4. Process Environment Block analysis

This part of the article presents information on PEB and the method of its reading.

The Process Environment Block is a structure that describes the context of a given process.

In order to analyze the PEB of the notepad process, switch the debugger context to the process located at ffffbf01`259a4780:

kd> .process /p ffffbf01`259a4780
Implicit process is now ffffbf01`259a4780
.cache forcedecodeuser done

After switching the debugger context, you can print the information contained in the PEB of the notepad.exe process.

kd> !peb
PEB at 0000002a4e032000
    InheritedAddressSpace:    No
    ReadImageFileExecOptions: No
    BeingDebugged:            No
    ImageBaseAddress:         00007ff6107d0000
    NtGlobalFlag:             0
    NtGlobalFlag2:            0
    Ldr                       00007ff925d933a0
    Ldr.Initialized:          Yes
    Ldr.InInitializationOrderModuleList: 000001efa1382260 . 000001efa138e1d0
    Ldr.InLoadOrderModuleList:           000001efa13823d0 . 000001efa138e1b0
    Ldr.InMemoryOrderModuleList:         000001efa13823e0 . 000001efa138e1c0
                    Base TimeStamp                     Module
            7ff6107d0000 5789986a Jul 16 04:14:02 2016 C:\Windows\system32\notepad.exe
            7ff925c40000 59b0d03e Sep 07 06:51:10 2017 C:\Windows\SYSTEM32\ntdll.dll
            7ff924cc0000 5abdafe8 Mar 30 05:32:56 2018 C:\Windows\System32\KERNEL32.DLL
            7ff922e30000 5abdad60 Mar 30 05:22:08 2018 C:\Windows\System32\KERNELBASE.dll
            ...
            7ff91f4c0000 5ab31a04 Mar 22 03:50:44 2018 C:\Windows\SYSTEM32\wintypes.dll
            7ff920bb0000 5ab31a5c Mar 22 03:52:12 2018 C:\Windows\System32\twinapi.appcore.dll
    SubSystemData:     00007ff920cb0e30
    ProcessHeap:       000001efa1380000
    ProcessParameters: 000001efa13819b0
    CurrentDirectory:  'C:\Users\74wny0wl\'
    WindowTitle:  'C:\Users\74wny0wl\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Accessories\Notepad.lnk'
    ImageFile:    'C:\Windows\system32\notepad.exe'
    CommandLine:  '"C:\Windows\system32\notepad.exe" '
    DllPath:      '< Name not readable >'
    Environment:  000001efa1380dd0
        ALLUSERSPROFILE=C:\ProgramData
        APPDATA=C:\Users\74wny0wl\AppData\Roaming
        CommonProgramFiles=C:\Program Files\Common Files
        CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files
        CommonProgramW6432=C:\Program Files\Common Files
        ...
        USERPROFILE=C:\Users\74wny0wl
        windir=C:\Windows

5. Process manipulation

An example of deliberate manipulation of the process will be presented in the following part of the article

5.1 Process heap modification

As an example of modifying the memory of a process, let’s try to modify the contents of the text box in the notepad window.

notepad secret content

PEB analysis revealed the notepad process heap address:

ProcessHeap:       000001efa1380000

Let’s search the heap to find the address where the fragment of the searched text “ANY SECRET CONTENT” is located. Please note that the search text is Unicode encoded:

kd> s -u 000001efa1380000 L100000 "ANY SECRET CONTENT"
000001ef`a1385060  0041 004e 0059 0020 0053 0045 0043 0052  A.N.Y. .S.E.C.R.
kd> du 000001ef`a1385060
000001ef`a1385060  "ANY SECRET CONTENT"

Now let’s try to modify the process memory fragment corresponding to the contents of the text field of the notepad window:

kd> eu 000001ef`a1385060 "MALFORMED CONTENT"
kd> du 000001ef`a1385060
000001ef`a1385060  "MALFORMED CONTENTT"
kd> g

The changes made to memory took effect immediately. However, they are not immediately observable. To do this, you must also force the notepad window to be redrawn. One solution is to enter a character (such as a space) in the notepad edit field or to resize the window. From now on, the effects of memory modification will be visible to the user.

notepad secret content

5.2 PEB modification

Let’s try to modify the PEB of the notepad.exe process so that when the process is analyzed using popular tools, it resembles the OneDrive.exe process.

Note that I restarted the debug machine’s system and restarted the notepad whose PID is currently 1728::

notepad-init-proc-exp-prop

So at the same time I was forced to reread the address list of existing processes:

kd> !dml_proc
Address           PID  Image file name
ffffd58f`31e60400 4    System
ffffd58f`33295780 114  smss.exe
ffffd58f`33a8f080 170  csrss.exe
...
ffffd58f`34758080 6c0  notepad.exe
...
ffffd58f`35302780 1130 OneDrive.exe

So let’s read the data of the OneDrive.exe process:

kd> .process /p ffffd58f`35302780
Implicit process is now ffffd58f`35302780
.cache forcedecodeuser done
kd> !peb
PEB at 0000000000a07000
...

Let’s read the PEB structure of the OneDrive.exe process:

kd> dt ntdll!_peb 0000000000a07000
   +0x000 InheritedAddressSpace : 0 ''
   +0x001 ReadImageFileExecOptions : 0 ''
   +0x002 BeingDebugged    : 0 ''
   +0x003 BitField         : 0x4 ''
   +0x003 ImageUsesLargePages : 0y0
   +0x003 IsProtectedProcess : 0y0
   +0x003 IsImageDynamicallyRelocated : 0y1
   +0x003 SkipPatchingUser32Forwarders : 0y0
   +0x003 IsPackagedProcess : 0y0
   +0x003 IsAppContainer   : 0y0
   +0x003 IsProtectedProcessLight : 0y0
   +0x003 IsLongPathAwareProcess : 0y0
   +0x004 Padding0         : [4]  ""
   +0x008 Mutant           : 0xffffffff`ffffffff Void
   +0x010 ImageBaseAddress : 0x00000000`01280000 Void
   +0x018 Ldr              : 0x00007ff9`bc4533a0 _PEB_LDR_DATA
   +0x020 ProcessParameters : 0x00000000`00e619b0 _RTL_USER_PROCESS_PARAMETERS
   ...
   +0x388 TppWorkerpListLock : 0
   +0x390 TppWorkerpList   : _LIST_ENTRY [ 0x00000000`00a07390 - 0x00000000`00a07390 ]
   +0x3a0 WaitOnAddressHashTable : [128] (null)

In order to present the parameters of the OneDrive.exe process, read the content of the _RTL_USER_PROCESS_PARAMETERS structure instance of this process:

kd> dt ntdll!_RTL_USER_PROCESS_PARAMETERS 0x00000000`00e619b0
   +0x000 MaximumLength    : 0x7d6
   +0x004 Length           : 0x7d6
   +0x008 Flags            : 0x6001
   +0x00c DebugFlags       : 0
   +0x010 ConsoleHandle    : 0xffffffff`fffffffe Void
   +0x018 ConsoleFlags     : 0
   +0x020 StandardInput    : (null)
   +0x028 StandardOutput   : (null)
   +0x030 StandardError    : (null)
   +0x038 CurrentDirectory : _CURDIR
   +0x050 DllPath          : _UNICODE_STRING ""
   +0x060 ImagePathName    : _UNICODE_STRING "C:\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe"
   +0x070 CommandLine      : _UNICODE_STRING ""C:\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe" /background"
   +0x080 Environment      : 0x00000000`00e60dd0 Void
   +0x088 StartingX        : 0
   +0x08c StartingY        : 0
   +0x090 CountX           : 0
   +0x094 CountY           : 0
   +0x098 CountCharsX      : 0
   +0x09c CountCharsY      : 0
   +0x0a0 FillAttribute    : 0
   +0x0a4 WindowFlags      : 1
   +0x0a8 ShowWindowFlags  : 1
   +0x0b0 WindowTitle      : _UNICODE_STRING "C:\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe"
   +0x0c0 DesktopInfo      : _UNICODE_STRING "Winsta0\Default"
   +0x0d0 ShellInfo        : _UNICODE_STRING ""
   +0x0e0 RuntimeData      : _UNICODE_STRING ""
   +0x0f0 CurrentDirectores : [32] _RTL_DRIVE_LETTER_CURDIR
   +0x3f0 EnvironmentSize  : 0xbce
   +0x3f8 EnvironmentVersion : 3
   +0x400 PackageDependencyData : (null)
   +0x408 ProcessGroupId   : 0x1e8
   +0x40c LoaderThreads    : 0

We are interested in ImagePathName, CommandLine and WindowTitle:

   +0x060 ImagePathName    : _UNICODE_STRING "C:\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe"
   +0x070 CommandLine      : _UNICODE_STRING ""C:\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe" /background"
   +0x0b0 WindowTitle      : _UNICODE_STRING "C:\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe"

We take this opportunity to look at the structures _UNICODE_STRING:

kd> dt ntdll!_UNICODE_STRING 0x00000000`00e619b0+0x60
 "C:\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe"
   +0x000 Length           : 0x7e
   +0x002 MaximumLength    : 0x80
   +0x008 Buffer           : 0x00000000`00e61fc8  "C:\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe"
kd> dt ntdll!_UNICODE_STRING 0x00000000`00e619b0+0x70
 ""C:\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe" /background"
   +0x000 Length           : 0x9a
   +0x002 MaximumLength    : 0x9c
   +0x008 Buffer           : 0x00000000`00e62048  ""C:\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe" /background"
kd> dt ntdll!_UNICODE_STRING 0x00000000`00e619b0+0xb0
 "C:\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe"
   +0x000 Length           : 0x7e
   +0x002 MaximumLength    : 0x80
   +0x008 Buffer           : 0x00000000`00e620e4  "C:\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe"

We already know the ImagePathName, CommandLine and WindowTitle values of the OneDrive.exe process. Let’s make the appropriate changes to the structure of the notepad.exe process. For this, let’s switch to the context of this process:

kd> .process /p ffffd58f`34758080
Implicit process is now ffffd58f`34758080
.cache forcedecodeuser done
kd> !peb
PEB at 0000008a19224000
...

Let’s read the address where the _RTL_USER_PROCESS_PARAMETERS instance is saved:

kd> dt ntdll!_peb 0000008a19224000
...
    +0x020 ProcessParameters : 0x0000020b`0e5c19b0 _RTL_USER_PROCESS_PARAMETERS
...

Let’s list the contents of ProcessParameters of the notepad.exe process:

kd> dt ntdll!_RTL_USER_PROCESS_PARAMETERS 0x0000020b`0e5c19b0
   +0x000 MaximumLength    : 0x780
   +0x004 Length           : 0x780
   +0x008 Flags            : 0x6001
   +0x00c DebugFlags       : 0
   ...
   +0x060 ImagePathName    : _UNICODE_STRING "C:\Windows\system32\notepad.exe"
   +0x070 CommandLine      : _UNICODE_STRING ""C:\Windows\system32\notepad.exe" "
   ...
   +0x0b0 WindowTitle      : _UNICODE_STRING "C:\Users\74wny0wl\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Accessories\Notepad.lnk"
   ...
   +0x40c LoaderThreads    : 0

Finally, let’s take a look at how the process parameters of interest are stored in memory:

kd> dt ntdll!_UNICODE_STRING 0x0000020b`0e5c19b0+0x60
 "C:\Windows\system32\notepad.exe"
   +0x000 Length           : 0x3e
   +0x002 MaximumLength    : 0x40
   +0x008 Buffer           : 0x0000020b`0e5c1fc8  "C:\Windows\system32\notepad.exe"
kd> dt ntdll!_UNICODE_STRING 0x0000020b`0e5c19b0+0x70
 ""C:\Windows\system32\notepad.exe" "
   +0x000 Length           : 0x44
   +0x002 MaximumLength    : 0x46
   +0x008 Buffer           : 0x0000020b`0e5c2008  ""C:\Windows\system32\notepad.exe" "
kd> dt ntdll!_UNICODE_STRING 0x0000020b`0e5c19b0+0xb0
 "C:\Users\74wny0wl\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Accessories\Notepad.lnk"
   +0x000 Length           : 0xbe
   +0x002 MaximumLength    : 0xc0
   +0x008 Buffer           : 0x0000020b`0e5c204e  "C:\Users\74wny0wl\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Accessories\Notepad.lnk"

Note that the read strings for the OneDrive.exe process are longer than their counterparts in the notepad.exe process, thus taking up more memory space. Therefore, we need to consider how to save longer strings of characters in the memory of the notepad.exe process.

Note that the memory used for the individual buffers for ImagePathName, CommandLine and WindowTitle is a continuous structure with a size of 0x146 bytes.

memory layout before changes

We’re going to want to write two strings:

C:\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe
"C:\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe" /background

We can do a little optimization here: ImagePathName and WindowTitle can use the same buffer. Let’s count how much memory we need to save them. For this, I ran python in interactive mode:

$ python3 -q
>>> window_title=r'''C:\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe'''
>>> command_line=r'''"C:\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe" /background'''
>>> hex((len(window_title)+len(command_line))*2)
'0x118'

We need 0x118 bytes in the process’s address space, so we’ll fit into the 0x146 bytes area that has been used so far.

memory layout after changes

So let’s modify ImagePathName, CommandLine and WindowTitle of the notepad.exe process:

kd> ew 0x0000020b`0e5c19b0+0x60+0x0 0x7e
kd> ew 0x0000020b`0e5c19b0+0x60+0x2 0x80
kd> eu 0x0000020b`0e5c1fc8 "C:\\Users\\74wny0wl\\AppData\\Local\\Microsoft\\OneDrive\\OneDrive.exe"
kd> ew 0x0000020b`0e5c19b0+0x70+0x0 0x9a
kd> ew 0x0000020b`0e5c19b0+0x70+0x2 0x9c
kd> eu 0x0000020b`0e5c1fc8+0x80 "\"C:\\Users\\74wny0wl\\AppData\\Local\\Microsoft\\OneDrive\\OneDrive.exe\" \/background"
kd> ep 0x0000020b`0e5c19b0+0x70+0x8 0x0000020b`0e5c1fc8+0x80
kd> ew 0x0000020b`0e5c19b0+0xb0+0x0 0x7e
kd> ew 0x0000020b`0e5c19b0+0xb0+0x2 0x80
kd> ep 0x0000020b`0e5c19b0+0xb0+0x8 0x0000020b`0e5c1fc8

Let’s preview PEB notepad.exe with the changes made:

kd> !peb
PEB at 0000008a19224000
    InheritedAddressSpace:    No
    ReadImageFileExecOptions: No
    BeingDebugged:            No
    ImageBaseAddress:         00007ff7dc110000
    ...
    ProcessParameters: 0000020b0e5c19b0
    CurrentDirectory:  'C:\Users\74wny0wl\'
    WindowTitle:  'C:\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe'
    ImageFile:    'C:\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe'
    CommandLine:  '"C:\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe" /background'
    ...

Let’s take a look at the impact of the changes made on the operating system.

The process list read by the debugger has not changed:

kd> !dml_proc
Address           PID  Image file name
ffffd58f`31e60400 4    System
ffffd58f`33295780 114  smss.exe
...
ffffd58f`34758080 6c0  notepad.exe
...
ffffd58f`35302780 1130 OneDrive.exe
...

Preview of the notepad process in Task Manager:

notepad-basic-peb-taskmgr

Preview the notepad process in Process Explorer:

notepad-basic-peb-procexp

Preview the notepad process in Process Hacker:

notepad-basic-peb-prochacker

No errors have been found in a running instance of notepad.exe.

5.3 Modifying the fields of process structure

In this part of the article, another attempt will be made to modify the notepad.exe process so that when analyzed with the use of popular tools, it resembles the OneDrive.exe process.

Process information is stored by the Windows kernel in the EPROCESS structure. In order to present the notepad.exe process data contained in the EPROCESS structure instance, execute the command:

kd> dt ntdll!_eprocess ffffd58f`34758080
   +0x000 Pcb              : _KPROCESS
   +0x2d8 ProcessLock      : _EX_PUSH_LOCK
   ...
   +0x468 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
   ...

One of the fields of this structure is SeAuditProcessCreationInfo. The definition of _SE_AUDIT_PROCESS_CREATION_INFO looks like this:

typedef struct _SE_AUDIT_PROCESS_CREATION_INFO
{
     POBJECT_NAME_INFORMATION ImageFileName;
} SE_AUDIT_PROCESS_CREATION_INFO, *PSE_AUDIT_PROCESS_CREATION_INFO;

Let’s have a look at the SeAuditProcessCreationInfo content in OneDrive.exe:

kd> dt ntdll!_SE_AUDIT_PROCESS_CREATION_INFO ffffd58f`35302780+0x468
   +0x000 ImageFileName    : 0xffffd58f`352cea40 _OBJECT_NAME_INFORMATION
kd> dt ntdll!_OBJECT_NAME_INFORMATION 0xffffd58f`352cea40
   +0x000 Name             : _UNICODE_STRING "\Device\HarddiskVolume2\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe"

and in notepad.exe:

kd> kd> dt ntdll!_SE_AUDIT_PROCESS_CREATION_INFO ffffd58f`34758080+0x468
   +0x000 ImageFileName    : 0xffffd58f`350d2a50 _OBJECT_NAME_INFORMATION
kd> dt ntdll!_OBJECT_NAME_INFORMATION 0xffffd58f`350d2a50
   +0x000 Name             : _UNICODE_STRING "\Device\HarddiskVolume2\Windows\System32\notepad.exe"

So SeAuditProcessCreationInfo is a pointer to _UNICODE_STRING. The address used is in the kernel space, so we can use it in the SeAuditProcessCreationInfo field from an instance of the EPROCESS structure describing the notepad.exe process. So let’s make an appropriate modification so that the SeAuditProcessCreationInfo pointer points to the same ImageFileName from the OneDrive.exe process.

kd> ep ffffd58f`34758080+0x468 0xffffd58f`352cea40

Let’s take a look at the impact of the changes made on the operating system.

The process list read by the debugger has not changed:

kd> !dml_proc
Address           PID  Image file name
ffffd58f`31e60400 4    System
ffffd58f`33295780 114  smss.exe
ffffd58f`33a8f080 170  csrss.exe
...
ffffd58f`34758080 6c0  notepad.exe
...
ffffd58f`35302780 1130 OneDrive.exe
...

but for the !process command, we already have some surprising changes:

kd> !process ffffd58f`34758080 7
PROCESS ffffd58f34758080
    SessionId: 1  Cid: 06c0    Peb: 8a19224000  ParentCid: 0054
    DirBase: 5d3e6000  ObjectTable: ffffa10dedf32540  HandleCount: <Data Not Accessible>
    Image: OneDrive.exe
    ...
    THREAD ffffd58f3479c540  Cid 06c0.0bc0  Teb: 0000008a19225000 Win32Thread: ffffd58f3500b8c0 WAIT: (WrUserRequest) UserMode Non-Alertable
            ffffd58f3528eb80  SynchronizationEvent
        Not impersonating
        DeviceMap                 ffffa10def921dd0
        Owning Process            ffffd58f34758080       Image:         OneDrive.exe
        ...

Preview of the notepad process in Task Manager:

notepad-seaudit-taskmgr

Preview the notepad process in Process Explorer:

notepad-seaudit-procexp

Preview the notepad process in Process Hacker:

notepad-seaudit-prochacker

No errors have been found in a running instance of notepad.exe.

5.4 Further modifications to the fields of process structure

In this part of the article, another attempt will be made to modify the notepad.exe process so that when the process is analyzed using popular tools, it resembles the OneDrive.exe process.

One of the fields of the EPROCESS structure are ImageFilePointer and ImageFileName. Let’s take a look at the EPROCESS instance describing the OneDrive.exe process:

kd> dt ntdll!_eprocess ffffd58f`35302780
   +0x000 Pcb              : _KPROCESS
   +0x2d8 ProcessLock      : _EX_PUSH_LOCK
   ...
   +0x448 ImageFilePointer : 0xffffd58f`350f6bc0 _FILE_OBJECT
   +0x450 ImageFileName    : [15]  "OneDrive.exe"
   ...

In order to read the contents of the _FILE_OBJECT instance, execute the command dt as below:

kd> dt ntdll!_FILE_OBJECT 0xffffd58f`350f6bc0
   +0x000 Type             : 0n5
   +0x002 Size             : 0n216
   +0x008 DeviceObject     : 0xffffd58f`32fe2330 _DEVICE_OBJECT
   +0x010 Vpb              : 0xffffd58f`32fe3010 _VPB
   +0x018 FsContext        : 0xffffa10d`ee0c5150 Void
   +0x020 FsContext2       : 0xffffa10d`ed7130b0 Void
   +0x028 SectionObjectPointer : 0xffffd58f`351988a8 _SECTION_OBJECT_POINTERS
   +0x030 PrivateCacheMap  : (null)
   +0x038 FinalStatus      : 0n0
   +0x040 RelatedFileObject : (null)
   +0x048 LockOperation    : 0 ''
   +0x049 DeletePending    : 0 ''
   +0x04a ReadAccess       : 0x1 ''
   +0x04b WriteAccess      : 0 ''
   +0x04c DeleteAccess     : 0 ''
   +0x04d SharedRead       : 0x1 ''
   +0x04e SharedWrite      : 0 ''
   +0x04f SharedDelete     : 0x1 ''
   +0x050 Flags            : 0x44042
   +0x058 FileName         : _UNICODE_STRING "\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe"
   +0x068 CurrentByteOffset : _LARGE_INTEGER 0x0
   +0x070 Waiters          : 0
   +0x074 Busy             : 0
   +0x078 LastLock         : (null)
   +0x080 Lock             : _KEVENT
   +0x098 Event            : _KEVENT
   +0x0b0 CompletionContext : (null)
   +0x0b8 IrpListLock      : 0
   +0x0c0 IrpList          : _LIST_ENTRY [ 0xffffd58f`350f6c80 - 0xffffd58f`350f6c80 ]
   +0x0d0 FileObjectExtension : (null)

Let’s look at the _FILE_OBJECT instance pointed by ImageFilePointer for the notepad.exe process:

kd> dt ntdll!_eprocess ffffd58f`34758080
   +0x000 Pcb              : _KPROCESS
   +0x2d8 ProcessLock      : _EX_PUSH_LOCK
   ...
   +0x448 ImageFilePointer : 0xffffd58f`350caca0 _FILE_OBJECT
   +0x450 ImageFileName    : [15]  "notepad.exe"
   ...

kd> dt ntdll!_FILE_OBJECT 0xffffd58f`350caca0
   +0x000 Type             : 0n5
   +0x002 Size             : 0n216
   ...
   +0x058 FileName         : _UNICODE_STRING "\Windows\System32\notepad.exe"
   ...

Before we brutally overwrite strings, let’s check if we have enough memory space:

kd> dt ntdll!_UNICODE_STRING 0xffffd58f`350f6bc0+0x58
 "\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe"
   +0x000 Length           : 0x7a
   +0x002 MaximumLength    : 0xf8
   +0x008 Buffer           : 0xffffa10d`ee0cf0c0  "\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe"
kd> dt ntdll!_UNICODE_STRING 0xffffd58f`350caca0+0x58
 "\Windows\System32\notepad.exe"
   +0x000 Length           : 0x3a
   +0x002 MaximumLength    : 0x78
   +0x008 Buffer           : 0xffffa10d`ed71a230  "\Windows\System32\notepad.exe"

The size of the string we want to write is 0x7a bytes. We have a buffer with a size of 0x78 bytes at our disposal. So we are missing a few bytes that we need to “borrow” or make the address of the buffer containing the path to the OneDrive.exe file the same in both structures:

kd> ew 0xffffd58f`350caca0+0x58+0x0 0x7a
kd> ew 0xffffd58f`350caca0+0x58+0x2 0xf8
kd> ep 0xffffd58f`350caca0+0x58+0x8 0xffffa10d`ee0cf0c0

As the last step, let’s change the ImageFileName value in the EPROCESS structure describing the notepad.exe process:

kd> ea ffffd58f`34758080+0x450 "OneDrive.exe"

Let’s check the correctness of the introduced changes:

kd> dt ntdll!_eprocess ffffd58f`34758080
   +0x000 Pcb              : _KPROCESS
   +0x2d8 ProcessLock      : _EX_PUSH_LOCK
   ...
   +0x448 ImageFilePointer : 0xffffd58f`350caca0 _FILE_OBJECT
   +0x450 ImageFileName    : [15]  "OneDrive.exe"
   ...

kd> dt ntdll!_FILE_OBJECT 0xffffd58f`350caca0
   +0x000 Type             : 0n5
   +0x002 Size             : 0n216
   +0x008 DeviceObject     : 0xffffd58f`32fe2330 _DEVICE_OBJECT
   ...
   +0x058 FileName         : _UNICODE_STRING "\Users\74wny0wl\AppData\Local\Microsoft\OneDrive\OneDrive.exe"
   ...
   +0x0d0 FileObjectExtension : (null)

Let’s take a look at the impact of the changes made on the operating system.

Process list read by debugger extension !dml_proc has changed and the debugger lists the notepad process and the original Microsoft cloud client process as the OneDrive.exe process:

kd> !dml_proc
Address           PID  Image file name
ffffd58f`31e60400 4    System
ffffd58f`33295780 114  smss.exe
...
ffffd58f`34758080 6c0  OneDrive.exe
...
ffffd58f`35302780 1130 OneDrive.exe
...

Preview of the notepad process in Task Manager:

notepad-eprocess-taskmgr

Preview the notepad process in Process Explorer:

notepad-eprocess-procexp

Preview the notepad process in Process Hacker:

notepad-eprocess-prochacker

No errors have been found in a running instance of notepad.exe.

5.5 Ultimately making a process similar to another process

In this part of the article, a final attempt will be made to modify the notepad.exe process so that when analyzed using popular tools, it resembles the OneDrive.exe process.

Let the ImageFilePointer field in the EPROCESS structure instance of notepad.exe point to the same _FILE_OBJECT that ImageFilePointer points to in the EPROCESS instance of the OneDrive.exe process:

kd> ep ffffd58f`34758080+0x448 0xffffd58f`350f6bc0

After the changes, the EPROCESS structure describing the notepad.exe process should look like this:

kd> dt ntdll!_eprocess ffffd58f`34758080
   +0x000 Pcb              : _KPROCESS
   +0x2d8 ProcessLock      : _EX_PUSH_LOCK
   ...
   +0x448 ImageFilePointer : 0xffffd58f`350f6bc0 _FILE_OBJECT
   +0x450 ImageFileName    : [15]  "OneDrive.exe"
   ...

Let’s take a look at the impact of the changes made on the operating system.

Preview of the notepad process in Task Manager:

notepad-all-taskmgr

Preview the notepad process in Process Explorer:

notepad-all-procexp

Preview the notepad process in Process Hacker:

notepad-all-prochacker

No errors have been found in a running instance of notepad.exe.

6. Summary

The article presents methods of reading data structures defining the process in the Windows operating system: EPROCESS and PEB. The use of !dml_proc, !process, .process, !peb, dt, e* and d* commands is also shown.

On this occasion, it is worth emphasizing the importance of the often repeated statement: it is not worth trusting the results shown by only one tool. At various stages of successively modifying the structures responsible for storing the data constituting the process definition in the system, different results were obtained in popular tools informing about the status of processes: Task Manager, Process Explorer and Process Hacker. Eventually, it is brought to an operating system state where the notepad process is seemingly indistinguishable from the OneDrive.exe process.

Potential use of the described methods by malware may lead to confusion of some antivirus engines or DFIR specialists. Below is a table showing the changes in the tested tools and the effectiveness of the methods presented. When reading the table, be aware of the cumulative use of each method.

process-details-comparison-table-en

At this point, it should be emphasized that the modifications did not affect the correct operation of the application or the operating system: the system worked with the notepad running and OneDrive.exe for several hours, the notepad was tested for available functionalities and I did not notice any errors in the notepad application or the operating system.

Of course, after killing the notepad process or OneDrive.exe, the BSOD will show up and we are done. This is because the process uses the same instance data structures that exist in kernel space.

It is also worth noting that the mechanisms that exist in the Windows operating system kernel probably do not verify the integrity of the process definition structures or do not do so effectively.