Exegol and Windows - emulating a bridged VM
If you haven’t come across Exegol before, it is (in their own words) ‘a community-driven hacking environment, powerful and yet simple enough to be used by anyone in day-to-day engagements. Exegol is the best solution to deploy powerful hacking environments securely, easily and professionally. Exegol fits pentesters, CTF players, bug bounty hunters, researchers, beginners and advanced users, defenders, from stylish macOS users and corporate Windows pros to UNIX-like power users’.
It is a fantastic, easy to use way of running environments whilst testing. I strongly encourage you to have a read through and see how it may benefit your use case here.
But since you’re here, I’m going to assume you at least know about Exegol and are aware of one of the main restrictions of operating it under Windows – you can’t share the network interfaces of the host with the container that you create. You can under Linux, but under Windows it is a limitation of the Docker Desktop. Find out more here.
With the amount of remote testing that we are still doing, it is not uncommon for us to send an image to a customer, already set up with the majority of testing tools that we would require for that engagement. In an attempt to streamline this process as much as possible, and allow clients that may only have internal Wintel expertise for troubleshooting issues, we have created Windows 11 images for Hyper-V, ESX etc so that in theory, the burden on the client for setting this up is absolutely minimised.
However, the lack of network sharing can still pose some issues for certain tools that just play nicer under Linux than under Windows, even if there is roughly equivalent tooling. So, we went to work to see if we can find a way of emulating a bridged VM using Exegol.
And we found one!
In SoftEther. This was chosen as it also operates on layer 2 and opposed to just layer 3 allowing you to do fun stuff like ARP scanning if required.
The initial set up is simple, though there are quite a few steps to go through. But once done and set up as a template, nice and easy to deploy and operate. Please note, these instructions follow on from once you have successfully installed and set up Exegol on the host – these instructions can be found in the link above to the Exegol documentation – worth noting that Docker Desktop doesn’t (at the time of writing) work on a server version of Windows.
So to start with we download the server software for the host (in our case for Windows) – select the options and pick the download you’d like :
Installation is fairly simple – you can follow the instructions here.
Once the SoftEther VPN Server is installed we create a VPNhub and add a user.
In the above screenshots, we have created a VPN hub imaginatively called VPN and a user, even more imaginatively, called Cybaverse.
Next is to set up the connection from the Exegol container. It is VERY VERY IMPORTANT, that the Exegol container you start is started with the - - privileged flag.
Here we create a container called test :
In this instance we are going to walk through manually the setup of the VPN client however you can add a script to ~\.exegol\my-resources\setup\load_user_setup.sh with a list of things to do each time a container is created.
The my-resources directory is a shared folder between the container and the host – easy to administer through Windows to drop stuff in there and instantly access it from within the container. To speed things up, I have a small script to install the SoftEther Client and some other tools at the same time. The script can be found here.
Running the script will also install arp-scan and dhclient :
Once it is complete (along with some rather funky coloured warnings)
Let’s test connectivity to the VPN server. Most of the VPN client software can be configured through the VPNCMD as shown below, though what we actually do for deployment is drop a .vpn file in the my-resources directory with all of these settings in and just import that into the client. Easy is good!
As we can see we have made a connection to the server. Few more quick changes to be made and we should be good to go.
To get Layer 2 we set up the bridge in the Soft Ether Server Manager as shown below.
This can require a restart in some circumstances so better to be safe than sorry. One reboot later, you will notice that the VPN adapter is missing – it is because we haven’t set the VPN service to start automatically. This is far too technical for the scope of this document. Maybe Google can help with that 😉. You will notice that when we start the container this time we no longer need to use the --privileged option.
Once started we reconnect and check everything is OK
We don’t get an IP address dynamically for the interface, so a quick dhclient is required.
Which happily gives us an IP address in the host range
However we still don’t have the ability to do fun layer 2 stuff like a rp-scan for example :
Final quick change to some networking routes (in the below example 192.168.1.189 is the host IP address and 172.17.0.1 is the docker gateway) - et voila!
Now we can even run things like responder and capture hashes😊.
This is something very difficult to do with the standard Exegol installation. Even attempting to forward host ports to the container, when using SMB and the like, the host won’t allow that to happen
It works fine for other ports that aren’t already in use on the system but these limitations can be a bit of a pain when mid test so we have tried to iron all of them out pre-deployment.
Obviously this solution, as presented, could be streamlined. Internally we have some other scripts and steps that we take to get the images we send to the customer working how we like it (for example setting the VPN service to start automatically etc). Once these are all set up and the image sent to the client, having a fully working Exegol and Windows test rig that gives us all of the major tooling we would like to use only takes a matter of a few minutes.
Finally, if you want or need IPv6 then you can just
- sysctl -w net.ipv6.conf.all.disable_ipv6=0
- sysctl -w net.ipv6.conf.default.disable_ipv6=0
There we go – hopefully you will find this useful!