Skip to content

Reverse HTTP Listener for Built Agents

The HTTP Listener establishes an HTTP server on a specified port, managing data traffic with agents through HTTP or HTTPS connections. This provides secure and discreet communication channels between the C2 infrastructure and agents, blending with regular web traffic.

Plugin ID: shelldot.listener.agent-reverse-http

Configuration

The table below documents all available configuration parameters in a logical order:

Attribute Explanation
port Port number where the generated payload calls home. If bindToPort is set to null, it will also be the port that listener runs
bindToPort Port number where the listener actually runs. Default is "null", in that case the "port" variable is used
https Protocol flag (false = HTTP, true = HTTPS).
startTime Optional UTC start time (e.g., "2023-04-10T11:02:09Z").
getUri URI used by the agent for GET requests when no data to send.
postUri URI used by the agent for sending data via POST (also receives data).
stagedUri URI requested for generating agent executable/dll/service/shellcode.
stagedUriPayloadId What GET parameter should containg id of the payload to download via stagedUri
fileStorageUri Base URI for retrieving files from file storage.
metadataCookieName Cookie name used to hold metadata.
metadataPrefix Prefix appended to metadata.
metadataSuffix Suffix appended to metadata.
instantResponses Boolean indicating if the agent sends data immediately or waits for the sleep timeout (for OPSEC).
headers[ ] Additional HTTP headers (array of objects with "name" and "value").
  ↳ name Name of the header.
  ↳ value Value of the header.
httpCallbacks[ ] Array of callback configuration objects.
  ↳ hosts[ ] Array of IP addresses or hostnames the agent can use to connect.
  ↳ sleep Base sleep time (ms) between requests.
  ↳ sleepRandom Variation (ms) in the sleep time.
  ↳ hostHeaders[ ] Array of HTTP host header values used when connecting.
  ↳ hostsRotation Rotation rules for host selection.
      ↳ type Rotation method (FAILOVER, ROTATE, RANDOM).
      ↳ counter Numeric value indicating when to rotate hosts.
      ↳ unit Unit for the counter (TRIES, SECONDS, MINUTES, HOURS).
  ↳ hostHeaderRotation Rotation rules for host headers.
      ↳ type Rotation method for host headers (FAILOVER, ROTATE, RANDOM).
      ↳ counter Numeric value for header change frequency.
      ↳ unit Unit for the header counter (TRIES, SECONDS, MINUTES, HOURS).

Rotation Rules

Rotation rules within the configuration are defined guidelines dictating when a listener's shellcode should alternate the host it connects to, or modify the HTTP host header within the request itself. This latter function is particularly useful for domain fronting, a technique employed to disguise the true destination of a web request.

Rule Type

This specifies the nature or category of the rotation rule. It determines the condition under which the rotation should occur, providing a contextual basis for the switch.

  • FAILOVER - With this kind of rule, the switch to next host or host header will happen if agent is failed it's connection to C2 for given set of tries or given set of time.
  • ROTATE - With this kind of rule, the switch to next host or host header will happen if agent is done (successful or not) given set of tries to connect to C2 or given set of time is passed.
  • RANDOM - The switch to next host or host header happens in random. With this type, the unit value is not important and before every connection to C2, the listener shellcode will "throw a dice" and decides to switch or not. The chance for switching is 1/counter

Rule unit

This element provides a unit of measurement for the numeric value, offering a scale or dimension to the rule. It contextualizes the numeric value, whether it's time-based, or count-based.

  • TRIES
  • SECONDS
  • MINUTES
  • HOURS

Rule examples

Switch to next happens after 7 request to C2, no matter if they succeed or not

  • type: ROTATE
  • counter: 7
  • unit: TRIES

Switch to next happens after 2 consecutive failed request to C2

  • type: FAILOVER
  • counter: 2
  • unit: TRIES

Switch to next happens when there has been 3 minutes since last successful request to C2

  • type: FAILOVER
  • counter: 3
  • unit: MINUTES

Switch to next happens when there has been 1 hour since last change

  • type: ROTATE
  • counter: 1
  • unit: HOURS

Before every request there is 12.5% (1/8) possibility that switch is made

  • type: RANDOM
  • counter: 8
  • unit: TRIES

Rotation Logic

The rotation logic in our system follows a specific workflow diagram, designed to guide the decision-making process for when and how the listener shellcode should switch its connection host or modify the HTTP host header.

alt text

Rotation Logic Example 1

In this simple example, let's consider a scenario where an agent is configured to alternate between two IP addresses for connection attempts, and it utilizes three different host header names. The rotation logic for this setup could be described as follows.

{
    "port": 8070,
    "httpCallbacks": [
      {
        "hosts": [
          "1.2.3.4",
          "5.6.7.8"
        ],
        "hostsRotation": {
          "type": "FAILOVER",
          "counter": 9,
          "unit": "TRIES"
        },
        "sleep": 10,
        "sleepRandom": 1,
        "hostHeaders": [
          "alpha",
          "bravo",
          "charlie"
        ],
        "hostHeaderRotation": {
          "type": "FAILOVER",
          "counter": 3,
          "unit": "TRIES"
        }
      }
    ],
    "fileStorageUri": "/files/",
    "getUri": "/ask_commands",
    "postUri": "/give_result",
    "metadataCookieName": "PHPSESSID",
    "metadataPrefix": "",
    "metadataSuffix": "",
    "https": true,
    "sleep": 10,
    "sleepRandom": 0,
    "headers": [
        { 
          "name": "Extra-Header-Name",
          "value": "Extra-Header-Value"
        }
      ]
}

How it works:

  1. Agent starts with connection to IP 1.2.3.4 using host header "alpha"
  2. If connection to C2 fails 3 times straight (because hostHeaderRotation has "FAILOVER" type with counter 3)
    1. the host header "bravo" is now used
    2. connection to 1.2.3.4 remains same because hostsRotation rule is not yet reached
  3. If connection to C2 fails another 3 times straight (because hostHeaderRotation has "FAILOVER" type with counter 3)
    1. the host header "charlie" is now used
    2. connection to 1.2.3.4 still remains same because hostsRotation rule is still not yet reached
  4. If connection to C2 fails another 3 times straight then 2 rules are reached - the hostsRotation and hostHeaderRotation. In such situation hostHeaderRotation is ignored
    1. connection to 5.6.7.8 is now used
    2. hostHeaderRotation counters are reset and first value "alpha" is now used
  5. If connection to C2 fails another 3 times straight (because hostHeaderRotation has "FAILOVER" type with counter 3)
    1. the host header "bravo" is now used
    2. connection to 5.6.7.8 remains same because hostsRotation rule is not yet reached
  6. If connection to C2 fails another 3 times straight (because hostHeaderRotation has "FAILOVER" type with counter 3)
    1. the host header "charlie" is now used
    2. connection to 5.6.7.8 still remains same because hostsRotation rule is still not yet reached
  7. If connection to C2 fails yet another 3 times straight then 2 rules are again reached - the hostsRotation and hostHeaderRotation. Again hostHeaderRotation is ignored
    1. connection to 1.2.3.4 is now used - circular selection
    2. hostHeaderRotation counters are reset and first value "alpha" is now used

Extra notes

  • The counters for host rotation and hostHeader rotations operate independently. In this scenario, if there are three failed connections followed by a successful connection, and then six subsequent failures, the connection will not switch to 5.6.7.8. This is because its counter resets after the successful connection. Similarly, the host header counters reset, but they are activated after every three consecutive failed connections. Consequently, in this specific case, the host header will have undergone three rotations, ultimately returning to the value "charlie."