Friday, January 18, 2019

Windows Internals: Windows process and their handles

In this post, I will document a behavior of the Windows kernel structure, EProcess. EProcess is created whenever, a process is created in Windows. However, when a process terminate, we may assume EProcess just get cleaned up. However, this may not always be the case.

I will show what happens if a process is terminated but handles to the process is still held (or opened) by another process.

The following is a code that I will be using to explain this scenario:



The code is pretty simple. It used CreateProcessW() to launch a notepad process. Then, it calls WaitForSingleObject() to wait forever(infinite) till the notepad process is closed before the execution continues.

Using Process Explorer, we can observe a parent process that was created after the code is executed and then a child process (notepad.exe) will be created.


To demonstrate what happened to the EProcess structure of the notepad process, I will use local kernel debugging with Windbg.

First I will set a breakpoint at the following line.

1
2
  CloseHandle(pi.hProcess);//Handles must be explicitly closed if not parent process will hold on to it even if child process is terminated.
  CloseHandle(pi.hThread);


I will let the code compile and start debugging (F5 in VS2017).

A new EProcess structure for the notepad process will be created and let's see it in Windbg.


1
2
3
4
5
lkd> !process 0 0 notepad.exe
PROCESS fffffa800cdfab30
    SessionId: 1  Cid: 0e40    Peb: 7efdf000  ParentCid: 0ee4
    DirBase: 1510a000  ObjectTable: fffff8a003fd9dc0  HandleCount:  91.
    Image: notepad.exe

We can see this the only EProcess structure created for notepad.exe. At this point the code is waiting indefinitely till the notepad process is terminated (or signaled)

Using Process Explorer, we can observed 2 handles inside the process that was generated by the code. These 2 handles were generated when the child process (notepad.exe) was created.


Now let's close the notepad.exe application. The notepad process will now be terminated and the code will execute till the breakpoint is hit.

What we observed in Process Explorer:
1. The notepad process is no longer present.
2. The 2 handles to the notepad process is still present in the parent process.

However, when we go to windbg the EProcess structure for the notepad process is also still present.

Let's step over both lines of the following code in VS2017.

1
2
  CloseHandle(pi.hProcess);//Handles must be explicitly closed if not parent process will hold on to it even if child process is terminated.
  CloseHandle(pi.hThread);

The EProcess structure for the notepad process is GONE!

In summary,
The EProcess structure for a Windows process will only be removed after all the handles to the process is closed.

Please leave me any comments or questions below if you have any. :)

Additional notes:
The demo is done using Windows 7 x64, visual studio 2017 (VS2017), Windbg and Process Explorer.
Windbg is running as a local kernel debugging. (Able to only READ the kernel memory.)
Detail type information of the EProcess structure can be retrieved via this windbg command, dt nt!_EPROCESS
In Windows, processes and threads, signaled means that they are terminated.