If you’ve ever used Evil-WinRM to run commands on a remote host, you might have noticed that any background processes you start will die as soon as you exit or otherwise disconnect the remote session. This can make it difficult to start other long-running processes (such as a C2 agent) that you want to keep running after you disconnect.

This post will explore why that happens and how to get around it. 

TL;DR

Spawned processes run in the context of a Job that ensures all normally-spawned children die when the remote session ends. 

One workaround is to use PowerShell’s Invoke-WmiMethod command, which starts the target process with a different parent:

Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList "C:\full\path.exe args"

Test Setup

If you want to follow along with these steps, you’ll need:

  • Windows 10 VM (Windows 11 should also work)
  • Linux VM with Evil-WinRM installed
  • Working networking between the two VMs

WinRM can be configured by starting the Windows Remote Management service, then running winrm quickconfig in an admin PowerShell window. If the WinRM service was already started, you can say No to the prompt to change that service to a “delayed auto start” (if you want to avoid having it always turn on at boot). Respond with Yes for all the other questions. 

All members of the local Administrators group should now be able to access the Windows VM remotely using WinRM clients.

Initial Access

On Kali, use Evil-WinRM to connect to the Windows machine’s IP using any account credentials that have admin access. In my case the highpriv account is a local admin:

evil-winrm -i 192.168.50.128 -u highpriv
Enter Password: 
...                                   
Info: Establishing connection to remote endpoint
*Evil-WinRM* PS C:\Users\highpriv\Documents>

Problem Demonstration

Log into the Windows VM using the same account that you used for WinRM and start up Process Explorer

In the Evil-WinRm CLI, run notepad.exe. Notice that the CLI doesn’t hang, waiting for the process to end; it starts the process and immediately returns control back to you. Now find that process in Process Explorer.

The spawned notepad.exe process
The spawned notepad.exe process

This reveals that the spawned notepad.exe process is a child of the wsmprovhost.exe process, which is the “Host process for WinRM plug-ins.” This wsmprovhost process is the parent process under which all the commands that you run in Evil-WinRM will spawn. 

Side Note: you can’t see the Notepad window because all processes spawned this way will end up in Session 0 (shown on the far right of that screenshot). This is a special GUI-less session typically used for Windows service separation, so no GUI applications running there will be visible to anyone using the computer. 

Now run exit in the Evil-WinRM CLI to end the connection and thereby kill the wsmprovhost process. Notice that both the wsmprovhost and the Notepad processes immediately die.

This is unusual in Windows. Normally children processes (Notepad) remain running when their parents (wsmprovhost) die. For example, you could start Notepad from the Start Menu and it would become the child of the Explorer process. If you forcibly kill Explorer, the Notepad process remains running. So why are processes started through WinRM different?

Problem Source

Start another evil-winrm connection and use that to start a new notepad.exe process. Then start a second Notepad process using the Start Menu. Find both in Process Explorer and double-click them to open their Properties windows. You may need to use File –> Show Details for All Processes in Process Explorer to access the WinRM Notepad process.

Comparing Notepad processes spawned with Explorer (left) vs WinRM (right)
Comparing Notepad processes spawned with Explorer (left) vs WinRM (right)

At first glance, things seem very similar between the two processes. The one on the left has Explorer as the parent, the one on the right has a wsmprovhost parent. There are also a few privilege differences as a result of how they were started, but most properties seem to be equivalent. The relevant difference here is the presence of the Job tab on the right window, which is absent on the left window.

Job info for the WinRM process tree
Job info for the WinRM process tree

The information in this Job tab indicates that the Notepad process started through WinRM automatically becomes a part of a Job inherited from the parent wsmprovhost process; this seems to be true for all child processes started through WinRM. The most important piece of information here is the “Kill on Job Close” value linked to the children processes, which is set to True. This is the reason that normal child processes die when the remote session ends.

To avoid spawned children getting killed when the WinRM session is closed, we need a way to spawn a new process that breaks out of this job control. 

Breaking Out of Job Control

I’m not an expert on how job control works on Windows. But my limited testing revealed that, in most cases, processes that were NOT spawned as children of the wsmprovhost process would not be included in that job and would therefore survive session exits. One of the easiest ways I found to accomplish this is with PowerShell’s Invoke-WmiMethod command:

Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList "C:\full\path.exe args"
  • If the target binary is in the PATH (like notepad.exe is) you can avoid using the full path; but other relative paths will not work.

This command will return several rows of data like this:

__GENUS          : 2
__CLASS          : __PARAMETERS
__SUPERCLASS     :
__DYNASTY        : __PARAMETERS
__RELPATH        :
__PROPERTY_COUNT : 2
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
ProcessId        : 2640
ReturnValue      : 0
PSComputerName   :

If the ReturnValue is 0, the process was started succesfully and this process will continue running after you exit the Evil-WinRM CLI. If Windows had a problem starting the process (for example, because the target executable doesn’t exist) then you’ll get a non-zero value there indicating an error.

Parent Process Proof

Process Explorer shows that this method causes the target process to be spawned as a parent of WmiPrvSE.exe (“WMI Provider Host”), and results in no Job tab in its Properties window.

Notepad process spawned with WmiPrvSE.exe as the parent
Notepad process spawned with WmiPrvSE.exe as the parent

Other Methods

I’ll leave testing other bypass methods as an exercise for the reader. But here’s a hint: many common methods of jumping from Admin to SYSTEM also create a new process that exists outside this job control, likely as a result of a spawning from a different parent. And as luck would have it, accounts that can use WinRM are usually local admins- because WinRM defaults to providing remote access to Admin users only.