Insights > Network Visibility + Security

Empire C2 : Networking into the Dark Side

2021-06-16  |  16 min read 

Command and Control

Empire is one of the most popular Command and Control frameworks available open source in GitHub. There are a lot of basic how-to Empire articles available on the internet, so in this blog we skip the basics and are going to take an in-depth look at Empire from the network packets perspective, see what is being exchanged, try to decrypt those packets, and understand what each of the fields in the packets mean. So, without further ado, let us get right into it.

Components Used

The Empire’s source code is written in Python, which makes it a lot easier (at least for me) to understand what is happening inside the framework. To keep the blog short, we are only going to examine the behavior with the default HTTP listener (the HTTP protocol server which listens for victim) that Empire has and use the ‘PowerShell stager’ (PowerShell based initial program ran on the victim) with ‘windows/launcher_bat’ (the extension of the initial malware) for exploitation.

Communication Phases

Before we get in-depth into Empire’s communication, we first take a high-level overview at the packets exchanged.

Empire’s communication Phases with the victim can be classified as one of the following two types.

  1. Staging Phase
  2. Command / Post-exploitation module execution Phase

Staging Phase

This is where the stager is executed on the victim and the victim tries to set up a connection with the Empire Command and Control Server. Various key exchanges occur during this phase between the client and server which are being used to encrypt and decrypt future communications. The end of this exchange completes the staging phase where a victim is successfully connected to the server.

When we look at the packet exchange that occurs at this phase using Wireshark, we see there are 3 pairs of Request and Responses exchanged.

  1. STAGE 0 - First, the victim sends a GET beacon with a cookie in the HTTP headers, server replies with 200 OK with a big (~ 5.5 KB) encrypted payload.
  2. STAGE 1 - The victim sends a POST message with an encrypted payload, to which server sends a 200 OK response with a small payload.
  3. STAGE 2 - Finally, the victim sends another POST message, to which server replies with an even bigger (~ 41KB) payload.

Post-Exploitation Module Execution Phase

The victim has completed its staging phase with the server and now sends regularly timed beacons (GET) to the server for any task to execute. There can be two scenarios here.

  1. When server does not have any task for the victim. The victim sends GET beacons to server. The server replies with a 200 OK default response

  2. When the server has some task, such as executing some command/modules, it wants the victim to do.
    • The victim sends GET beacons to server and the server sends the respective payload for the command/module it wants the victim to execute in response.
    • The victim might send a POST message with a small payload indicating job has been started. This is optional and depends on the module to be executed. The server replies with a 200 OK with the same default response.
    • The victim sends the actual output of the command/module in a POST request and the server sends 200 OK with the same default response.

      NOTE - The victim might send more POST requests with more output results depending on the module executed. For example, in cases like clipboard monitor module, where the victim sends out multiple post messages containing the clipboard contents up until that time.


Empire Stager

We first look at the initial stager, the first script that is detonated on the victim, we can see that it runs an encoded PowerShell script. When we base64 decode and remove the null bytes, we get –

We can see two important info embedded here –

  1. StagingKey 'Vz(@nGEb/a-9LU[Jq_#HjCgovBh+D:?>' , which will be needed to decrypt the initial payload from server.
  2. We also have the base64 encoded string (highlighted in the image) within that when Base64 decoded and removed null bytes reveals the server IP and port to contact –

Encryption Techniques

Empire uses 3 types of encryption techniques –

  1. RC4 encryption (Symmetric Cryptography)
  2. RSA encryption (Asymmetric Cryptography)
  3. AES encryption with HMAC verification (Symmetric Cryptography)

Decryption of Staging Payload

Empire uses combination of the encryption techniques mentioned above, in various stages of the staging phase.


We look at the request responses shared between the server and victim –

We can see that the Victim sends an encrypted cookie where mEKiQrsvlaKxYknBCZ/m2QEp7Co= is the cookie which when base64 decoded and then RC4 decrypted with the stagingKey gives –


NOTEFields in all the packet structures are in little Endian format

  • The session ID has not yet been assigned, so it is 00000000.
  • The language is PowerShell since, 1 = PowerShell, 2 = Python, referenced from dictionary named LANGUAGE here.
  • The meta field is 1, so it is stage 0, referenced from dictionary named META here.

Next for the server response, we copy the hex bytes of the HTTP payload from Wireshark, we once again do an RC4 decryption with the same StagingKey, we can see the payload getting decrypted. This does not have a structure like the above one, instead it just packs the PowerShell script directly. This script will handle the next phase of the communication on the victim side.


We now look at the second pair of Request and Responses, exchanged:

This time the victim packs a payload with its request, we apply RC4 decryption to the first 20 bytes of the payload with the StagingKey, we see it got decrypted again. The payload obtained is:

  • We see we have a proper session ID ‘GSTN5PW1’ this time.
  • The meta field is now 02, indicating we are in STAGE 1.
  • This time we have a length field indicating the length of rest of the payload after the 20th byte. Since the fields are all in little endian, when length is converted to decimal gives 442.
  • When we applied the AES decryption on the 442 bytes of data after 20th byte with StagingKey as the key, we got the rest of the payload decrypted. It is an RSA public key PEM converted to XML. From the XML we can get the PEM using this.

With that decrypted, we now move to the response of this request, since the client sent it is RSA public key, so this response should be encrypted by that key for client to be able to decrypt. Since we do not have the client’s private key, we cannot really decrypt it. But, by diving into Empire’s code, we were able to figure out that the payload was in fact RSA encrypted with that RSA public key and the payload that was being sent was a 16 Bytes numeric nonce and 32 Bytes Session key concatenated which looked something like this –

You can also find the session key which is used for decryption of further communication in the GUI of empire (Starkiller).


We come to the last stage of the Staging phase, where client sends a POST message and server replies with another payload.

We once again take the first 20 bytes of the payload and apply RC4 decryption with the StagingKey, the payload obtained:

We see the usual fields with the meta field being 03, indicating Stage 2.

We get rest of the 186 bytes of the payload, and apply AES decryption, but this time we use SessionKey as the key which the server sent to client in the earlier response. We see that the payload gets decrypted and reveals the information client sent –

Here is a breakdown of the information sent by the victim -

  • 8297847267265727= nonce sent by the server earlier
  • = server IP and port
  • DESKTOP-7BSBJKM = Victim hostname
  • ayan = Victim Username
  • Victim IP
  • Microsoft Windows 10 Pro N = Victim OS
  • PowerShell = stager language
  • 7564 = Process ID where the victim is running
  • 5 = PowerShell Version

We now look at the server response, this can be decrypted directly via the AES decryption function with the SessionKey as the key. This seems to be the final agent code to be used by the victim for future C2 communication.

Decryption of Modules Payload

We will now try to analyze the payload exchanged during Command and a Post-Exploitation module execution. We will perform two types of tasks, first a simple shell command and then a post-exploitation module supported by Empire and analyze their payload.

Shell Command Execution

When we execute the shell command ‘pwd’, we look at the traffic captured in Wireshark –

The regularly timed beacon that is sent by the victim, only has the encrypted cookie lPPaNKKX3Cnn1FpwgtLV+oNChjc= which when decoded and RC4 decrypted with Staging Key gives –

We have meta = 04 indicating it is a Tasking Request (asking the server to give task) by victim.

As a response, server sends the command payload which when we take and do a RC4 decryption of the first 20 bytes with StagingKey and AES decryption on the rest with Session Key, we get the following payload.

First 20 bytes:

Here the meta is 06 meaning it is a Server Response

Rest of the bytes:

Type is 40, which according to the dictionary named PACKET_NAMES here , is TASK_SHELL, which makes sense since we executed a shell command. We can also see the actual command/payload sent to be executed on the victim.

Then we go to the next set of request and response received, the first one being a POST request sent by the client what hopefully is the output of the task.

We take the payload and decrypt it as before –

Meta is 05 indicating Result Post meaning a task result packet.

We can still see the same Task ID being used indicating to which task this response belongs.

The task data is base64 encoded. When we decode it –

We see the current directory of the victim as expected from the pwd command.

To its response server has nothing to send back, so responds with the default reply.

Post-Exploitation Module Execution

When we execute one of the post-exploitation modules available in Empire, the request response payload structure is similar to the one we discussed above in command execution but with a difference. The difference is that the job type changes from TASK_SHELL to either of the below mentioned types.

  1. TASK_CMD_JOB = Here job type is 110 (decimal), before sending the actual output, victim sends a POST request stating that “Job started: 51FANB”. Here 51FANB is an ID assigned to the job (different than task ID). Then after the job completes on victim, the actual output is sent.
  2. TASK_CMD_WAIT = Here the job type is 100. It is similar to the shell command, where the output is given directly in the next packet.


Empire Decryption Flow Diagram

Here is a diagram summarizing all the decryption steps in various phases:

Leverage Subscription Service to Stay Ahead of Attacks

Keysight's Application and Threat Intelligence (ATI) Subscription provides daily malware and bi-weekly updates of the latest application protocols and vulnerabilities for use with Ixia test platforms. The ATI Research Center continuously monitors threats as they appear in the wild and has just released a detailed implementation of Empire as part of BreakingPoint System’s recent update 2021-13.

The SuperFlows released for Empire are heavily customizable allowing users from using their own keys and certs for payload traffic encryption to using one of the many implemented post-exploitation modules supported by Empire.

Use BreakingPoint’s huge collection of Security applications to do robust testing of your DUT against malicious traffic like Empire and much more. More Command-and-Control applications to be added in the future releases. 

Customers of BreakingPoint have now access to attack campaigns for different advanced persistent threats, allowing them to test their currently deployed security controls’ ability to detect or block such attacks. For more details about Keysight Breakingpoint, visit  BreakingPoint.

This concludes our little venture into understanding Empire’s communication from the network perspective. This is a very capable toolkit effective in both right and wrong hands. We may soon take a similar deep dive into other Command and Control Frameworks, stay tuned for that!