Reigning the Empire, evading detection

- 2 mins

tl;dr: Configure a (valid) certificate and add jitter to have Empire communications stay below the radar.

Empire, an open-source post exploitation framework by now well-known among pentesters and red teamers. @harmj0y, @sixdub, and @enigma0x3 did a terrific job making Empire OpSec safe using various obfuscation techniques. On the endpoints, the most prominent and effective one is having most of the PowerShell modules ran in memory. On the network, it appears to be HTTP traffic where its communications are AES encrypted (more here). Empire has been very effective for me, evading pretty much all of the detection mechanisms I had to pass. But recently, it got picked up on the wire by the custom IDS rules of a SOC service provider. As it turned out, I was being a bit sloppy, because Empire can be easily setup to evade these (rather lousy) IDS rules. This is a quick post on what is detected and how to set up Empire to bypass detection.

So, let’s start out by firing up a listener with default values at


Empire listener with default values.

Execute the stager on the victim at and let’s sniff the traffic between attacker and victim.


Packet capture of HTTP traffic going to the Empire C2.

Instantly popping up is the large amount of HTTP keep-alive beacons the agent sends back to the C2. This in itself was not the issue, however, the fact that it requests the default Empire pages /admin/get.php, /news.asp, /login/process.jsp was. If we look more closely to the C2 response, we also see that a default “It works!” webpage is returned.


Empire C2 response viewed in Wireshark. Default "It works!" page is returned.

A user constantly refreshing an “It works!” page doesn’t really looks like the benign behaviour to me… Let’s see if we can obfuscate this a bit. First thing we can do is customise the listeners’ DefaultProfile to, in this case, /feed.xml and index.html.


Empire listener with customised DefaultProfile parameter.

This change results in an obvious customisation of the HTTP requests. In my scenario, this alone was enough to evade the IDS.


Keep-alive beacon using customised profile.

However, the default webpage “It works!” is still there, which is lame.

Now, if we provide the listener with a certificate (you may want to use a valid cert to increase stealthiness) and add random jitter, the communication is wrapped in a TLS layer and Empire specifics are gone!

Excellent. 👌🏼


Listener set up to use TLS for its communications.


TLS wrapped communications between the agents and C2.
rss facebook twitter github youtube mail spotify lastfm instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora quora