Aug 14 2024 | forrest kasler

Sleeping With the Phishes

Share

Hiding C2 With Stealthy Callback Channels

Write a custom command and control (C2) implant — Check ✅

Test it on your system — Check ✅

Test it in a lab against your client’s endpoint detection and response (EDR) product — Check ✅

Convince a target to download the payload — Check ✅

Get your hard earned shell… — Nada! Nil! Goose Egg! ❌

What happened?

If we’ve written a custom implant, and even taken precautions to test it against the same EDR, then we can be reasonably assured that the payload executed. The only remaining explanation as to why you didn’t receive a callback is that the outbound communication must have been blocked. Your poor shell is alive and well, but it’s crying out for help and can’t find its way home.

How can we avoid such a tragedy?

What is Stealthy, Anyway?

When it comes to network traffic, the best approach we can take to remain “stealthy” is to try to blend in with existing traffic. By far, HTTP(S) is the most popular callback method for beaconing malware for three reasons:

  1. It’s easy to implement — Simple, text-based, flexible protocol with many available libraries
  2. It’s likely to be open outbound — Browser-based workflows necessitate HTTP(S) outbound
  3. There is a ton of existing traffic — Our traffic will be a needle in a haystack

As long as the contents of our HTTP(S) messages look similar to real web traffic (a.k.a., our “C2 profile”) then we should be able to blend in and remain “stealthy”. But, there is a catch:

“Everything is stealthy until someone is looking for it.” — @tifkin_

However you chose to structure your messages, there may be telltales that could give away your particular brand of malware in the future. If you don’t write your own C2 profile and just use an open-source one, then it is likely that some security products have already fingerprinted your malware’s communication style.

In addition to fingerprinting C2 profiles, network defenders have a few more ways to block a lot of unknown malicious traffic, and cause a headache for red teams:

  1. Blocking traffic to new or uncategorized domains
  2. Blocking traffic to any domain that is new to the target network (first visits)
  3. Only allowing traffic to a narrow set of websites required to do business (allow listing)

Bypassing block number one is easy. Just host some benign content on your domain until it is a few months old and categorized. Blocks two and three are a bit more challenging to bypass. Let’s look at a few options that will likely still work even in the case of domain allow listing and that are also somewhat “stealthy”.

The Classic: DNS

DNS has long been the preferred choice for red teams as a long-haul C2 callback. Like HTTP(S), it is extremely likely that DNS traffic is allowed outbound. There is also a ton of existing traffic to blend in. It only comes with two caveats:

  1. Size limits — We only get 253 characters max per request to work with
  2. Case insensitive — We will need to add additional bytes to encode data that isn’t lowercase alphanumeric

DNS responses can be up to 512 bytes, but that’s still a major limitation. What this means is that most DNS C2 profiles break up the call and response data into small chunks and generate a very high volume of DNS requests over short periods. In addition, most DNS C2 profiles are designed to be “efficient” and use all of the available bytes for each request, which generates requests that don’t look normal at all compared to regular DNS lookups. Keeping this in mind, here’s some tips on how to use DNS effectively, while staying stealthy:

First, I would recommend only using DNS for check-ins, or other communications that require very small data transfers. In general, try to stay well under the 253 character limit.

Second, design post-exploitation commands that require very little output. For instance, one command might simply retrieve a host name, and let you know if the implant can load a webpage on that host. Another command might then instruct the implant to call back to that host over HTTPS.

Finally, remember that DNS caching is a thing. Make sure that every DNS request from your implant has at least one random or incrementing portion so that your requests aren’t dropped early by a caching DNS server.

The Overlooked: ICMP

ICMP is also very frequently allowed outbound. Even if the only TCP ports allowed outbound are 80 and 443, remember that ICMP is its own protocol separate from TCP. Unfortunately, each ICMP packet can only carry 32 bytes of information and is oftentimes overlooked on the stealth front. If you happen to land in an environment that isn’t monitoring ICMP at all, then the size limitation shouldn’t matter.

We can generate a huge volume of traffic while still flying under the radar. The only problem is, if defenders do set up ICMP monitoring, then flagging anomalous requests is insanely easy. That’s because normal ECHO Request (PING) and ECHO Reply messages always have a data payload of ‘abcdefghijklmnopqrstuvwabcdefghi’. Why? I have no idea. Just know that fake messages are easy to spot so ICMP tends to be all or nothing when used for C2 traffic.

You’ve Got Mail(ware): C2 Over SMTP

One of my favorite tricks to help my implants blend in is to use Microsoft Component Object Models (COMs) to drive legitimate Windows binaries to do my bidding; for example, creating a hidden instance of Internet Explorer and using it to navigate to my C2 domain to make my HTTPS connections look like they are normal web traffic.

On networks that restrict outbound access over HTTP(S), we can use this same trick to exfiltrate data over email (SMTP) instead using Outlook’s COM interface. If you get fancy with setting some custom email rules for the compromised user, you could write an implant that uses only SMTP for C2 communications.

One major advantage to this approach would be that you aren’t using HTTP(S) traffic at all. No matter how locked down the corporate web proxy is, if the compromised user can send and receive emails, then your implant will likely be able to call home.

In addition, you wouldn’t need the implant to Beacon at all. Your implant could just sit and wait for special emails to come in with its next instructions.

The last major upside to this C2 method is that data is exchanged between email addresses and not C2 domains, making it much easier to make changes on the fly. For instance, instructions could come from multiple different email addresses. Outputs could be sent to multiple destination addresses using email CC or BCC just in case one email address gets blocked. If you used disposable addresses, like Gmail accounts, you wouldn’t even need to purchase a C2 domain at all.

Old Dog, New Transport: DNS Over TLS and HTTPS (DoT and DoH)

The DNS protocol does not support encryption, which means that all of your DNS requests, “can be read by networks, ISPs, or anybody able to monitor transmissions”. To address this issue, DNS over TLS (DoT), and DNS over HTTPS (DoH) are now commonplace alternatives for traditional DNS. Most web browsers these days use DoH as an added security feature (or to enact exclusive access to monitor you). That means that most networks will have a decent volume of legitimate DoH traffic for us to blend in. DoT is an okay option, but requires additional lift to implement in an implant. DoT also uses port 853 instead of the traditional 53, which might be blocked outbound on restrictive networks. DoH, on the other hand, just uses port 443/TCP. It is DNS exposed as a web API. Here’s a couple of examples:

https://dns.google/resolve?name=example.com

curl -H "accept: application/dns-json" "https://cloudflare-dns.com/dns-query?name=example.com&type=A"

Even if our target network is utilizing domain allow listing, what are the odds that “dns.google”, or “cloudflare-dns.com”, or both are on the list? I’d say pretty high. We still have DNS size limitations to deal with, but get some major advantages over a traditional DNS callback. First, our requests are encrypted. We can safely go back to generating extremely anomalous 253 byte DNS queries. Second, our implant is no longer sending raw DNS requests. HTTPS is going to look a lot more normal comparatively. Finally, we can implement a DNS callback without needing a DNS library. The DNS protocol is complex, but these DoH APIs are extremely simple.

LOTS of Options: Living Off Trusted Sites

Speaking of sites that are likely to be on a corporate allow list, there are plenty of “trusted sites” we might be able to leverage to broker messages between our implants and our C2 server. This technique is known as living off trusted sites, or LOTS for short. The idea is that there are some sites that are used so commonly by businesses, that blocking them would be prohibitive for most organizations. Many of those same sites allow users to post or store data in some capacity, where it can subsequently be retrieved. You can therefore leverage the reputation of these sites to get data in and out of your target network. Here’s a great list curated by @mrd0x:

https://lots-project.com/

You can use the “C&C” filter to find sites that are particularly suited for use as C2 message brokers. You might also find a few good places to host a static phishing site or deliver a payload!

Swimming Upstream: STUN and TURN

If you’ve never heard of Session Traversal Utilities for NAT (STUN) or Traversal Using Relays around NAT (TURN), then you are not alone. Not many red teamers need to interact with these protocols or even know what they are. These protocols are the backbone for most web based audio and video streaming services. Think Discord, GoToMeeting, Facebook Messenger, and Google Hangouts to name a few. All these services have one challenge in common: How do we connect two (or more) devices so they can stream data between each other when they are both behind firewalls? That’s where STUN and TURN come into play. Note that they both have “traversal” and “NAT” (A.K.A firewall) in the name. These protocols allow devices to set up peer connections even when they are behind a firewall. It’s kind of like poking a little hole in the firewall so we can talk efficiently with someone else who also poked a hole in theirs.

At their core, all reverse shells do the same thing. We can’t use a bind shell because there is a firewall that will block our inbound connection. Therefore, the implant needs to send a request outbound to initiate the connection, and any subsequent response data is then allowed based on NAT rules. STUN and TURN are just a far more robust way of traversing the firewall. A few benefits that might make STUN and TURN useful for C2 is that they are commonly allowed, UDP based, and highly complex. All of these factors make them a potential blind spot for many organizations.

Flow Like Water: Mixed Callbacks

I like to think about C2 communications as sort of like sharing notes back in grade school. There may be many paths a note might take from A to B; maybe between a mutual friend or mutual friends. Maybe you use an agreed upon drop box location (maybe multiple), or implement your own special code. In any case, the path the note (data) traverses doesn’t matter as long as it gets from A to B and back again. So when I apply this viewpoint to C2 communications, I prefer to break up the problem into two questions:

  1. How can I get data into the organization from the outside?
  2. How can I send data from inside the organization to the outside?

The answer to each question doesn’t need to match. They just have to be individually valid answers. You could receive instructions from a shared Google Doc, and post the output to a private GitHub repository. You could perform an initial check-in over SMTP, send regular follow-up check-ins over DNS, pull instructions over DoH, and exfiltrate output using a “video feed” over STUN. You could even use a mix of methods for any one step, either in parallel, or in round-robin fashion. You are only limited by your creativity.

Warning: I am not actually suggesting that you write a complex system like this. I merely want to break your conception of what a C2 channel is. Generally, it’s best to stick to one or two methods based on needs.

I think at a minimum, it’s useful to modularize each of these separate actions in implant code and have at least a couple options available for each. That way we can easily tweak payloads to better suit our target environment. And certainly don’t limit yourself to just the standard HTTPS callback.

In Conclusion

C2 communication is just a matter of passing notes (data) in and out of the target network. There is already a massive volume of data traversing in and out of your target network every day. You just need to guess what some of those common channels might be, and use the same channels to sneak instructions to your implants and outputs back to your C2 server. If you happen to use the right channel(s) then blending in should be easy, and your shells will find their way home.

Marlin:
How do you know if they’re ready?

Crush:
Well, you never really know, but when they know, you know, y’know?


Sleeping With the Phishes was originally published in Posts By SpecterOps Team Members on Medium, where people are continuing the conversation by highlighting and responding to this story.