Like many frameworks out there, Cobalt Strike is capable of generating both staged and stageless payloads.

  It's assumed here that you understand the difference between the two.  If not, just search for "staged vs stageless payloads" or similar in your favourite search engine.

You can generate staged payloads at **Attacks > Packages > Payload Generator** and **Attacks > Packages > Windows Executable**.  For the most part, we don't use staged payloads because they have quite bad OPSEC, but the Cobalt Strike team server still supports this staging process by default.

If you launch a staged payload, you will see a web log entry.  This is the stager asking the team server for the full payload stage.  Using the `webbug_getonly` profile, it looks like this:

11/08 11:26:33 visit (port 443) from: 127.0.0.1
	Request: GET /__init.gif
	beacon beacon stager x64
	Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; MALC)

  

There are separate URIs for x86 and x64 stagers, which are defined in the `http-stager` block:

http-stager {
        set uri_x86 "/_init.gif";
        set uri_x64 "/__init.gif";
        ...
}

  

If your malleable C2 profile does not explicitly define this block, Cobalt Strike will revert to its default behaviour, which looks like a random four character URI:

11/08 11:35:51 visit (port 443) from: 127.0.0.1
	Request: GET /mQNQ/
	beacon beacon stager x64
	Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; BOIE8;ENUS)

  

The actual resource being returned is the full Beacon shellcode, which subsequently gets loaded by the stager.  These characters are not exactly random - they equate to an 8-bit checksum.  When the team server receives the request it:

-   Converts each character into its integer representation.
-   Calculates the sum of those integers.
-   Divides that sum by 256 and checks the remainder.
    -   If the remainder equals 92, it's an x86 request.
    -   If the remainder equals 93, it's an x64 request.

Let's try this manually first.

Any ASCII table or [online converter](https://www.rapidtables.com/convert/number/ascii-hex-bin-dec-converter.html) will provide the decimal for `mQNQ`: 109 81 78 81.

-   109 + 81 + 78 + 81 = 349
-   349 / 256 = 1.36328125
-   0.36328125 * 256 = **93**.

This process can be automated to generate "random" URIs for both staging requests.  Credit to [James D](https://twitter.com/FranticTyping) for the following Python code (already on the Attacker Linux VM at `/home/ubuntu/checksum-generator.py`).

ubuntu@teamserver ~> ./checksum-generator.py
Generated x86 URI: /8Sfk
Generated x64 URI: /CWzI

  

Why is this bad?  The request is completely unauthenticated which means it can be made from anyone or anywhere, it's not limited to a legitimate CS stager.  For instance, we can download the entire shellcode blob using curl.

C:\Users\Administrator\Desktop>curl -k https://10.10.0.69/CWzI -A "not curl :)" -o shellcode.bin
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  259k  100  259k    0     0   259k      0  0:00:01 --:--:--  0:00:01 1854k

05/29 08:51:02 visit (port 443) from: 10.10.0.252
	Request: GET /CWzI/
	beacon beacon stager x64
	not curl :)

  

   The above command is using curl.exe in `C:\Program Files (x86)\curl-7.83.1_3-win64-mingw\bin`, not the PowerShell alias for Invoke-WebRequest.

  

Beacon parsers (such as [CobaltStrikeParser](https://github.com/Sentinel-One/CobaltStrikeParser) by Sentinel-One) can read this shellcode and tell you everything you need to know about it.  Copy the shellcode to the Attacker Linux VM first.

PS C:\Users\Administrator\Desktop> pscp -i ssh.ppk shellcode.bin ubuntu@10.10.0.69:/home/ubuntu/.
shellcode.bin             | 259 kB | 259.6 kB/s | ETA: 00:00:00 | 100%

ubuntu@teamserver ~> python3 CobaltStrikeParser/parse_beacon_config.py shellcode.bin
BeaconType                       - HTTPS
Port                             - 443
SleepTime                        - 5000
MaxGetSize                       - 1048616
Jitter                           - 0
MaxDNS                           - Not Found
PublicKey_MD5                    - c8b0b9d814ec7139ad7b8462c4047ff0
C2Server                         - 10.10.5.39,/___utm.gif,10.10.5.246,/___utm.gif
UserAgent                        - Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; MALC)
HttpPostUri                      - /__utm.gif
Malleable_C2_Instructions        - Remove 15 bytes from the beginning
                                   Remove 15 bytes from the beginning
                                   Remove 10 bytes from the beginning
HttpGet_Metadata                 - ConstParams
                                        utmac=UA-2202604-2
                                        utmcn=1
                                        utmcs=ISO-8859-1
                                        utmsr=1280x1024
                                        utmsc=32-bit
                                        utmul=en-US
                                   Metadata
                                        base64url
                                        prepend "__utma"
                                        parameter "utmcc"

  

This would provide defenders a huge amount of information about your campaign, useful for them to respond very effectively.  For instance, it would disclose all of your redirector IPs or domains, traffic profile and post-ex configuration.

The use of redirectors can somewhat mitigate the risk of these staging URIs being reachable, but since stagers are generally not used anyway, the safest course of action is to just disable them altogether.  This can be done by adding the following configuration to the global options in your C2 profile.

set host_stage "false";

  

Restart the team server for the changes to take effect and now any stage requests will return a 404.

C:\Users\Administrator\Desktop>curl -v -k https://10.10.0.69/CWzI -A "not curl :)"
< HTTP/1.1 404 Not Found
< Date: Sun, 29 May 2022 09:02:24 GMT
< Content-Type: text/plain
< Content-Length: 0
<


