Intro
My hands have definitely been a little full lately, but since I got a new laptop recently, I’ve finally been able to dig a little deeper into some of the red team things I’ve been meaning to for a while (read as: I can spawn Windows VMs easily). One of the things I’ve been meaning to figure out recently is my preferred command and control framework, Sliver.
There are a bunch of things that I really like about it, including the frequent updates/developement, the amount of features, and the overall flexibility as everything is in Golang. The biggest issue I have with it is the rather limited documentation. The beginner’s guide has been in TODO since January forever, and I still get very confused with how certain things like staging or pivoting work. I don’t fully blame BishopFox for this; I’m also in the process of getting more comfortable with red team concepts in general, but I do think things could be slightly more descriptive.
This guide is meant to serve as a high-level overview of the basic features one would need to know to effectively use the Sliver C2 in a lab environment where OPSEC doesn’t really matter. Before that, we’ll briefly touch on what C2 actually is, and end up concluding with looking at it from the flip-side and how to detect this.
Beginning Phase: What’s a C2?
Intro to C2
I first heard about “command and control infrastructure” from participating in Cyber 9/12, a cyber-policy event, where they never really explained it and I just thought it was some eldrich magick that made hacking possible. Turns out, it’s a lot simpler than that.
The motivation for a command and control framework (aka C2 Framework) is simple. When an advesary attacks a large network of hundreds or possibly thousands of devices, it is simply infeasible to try and manage 10, 50, or more different shell sessions on compromised hosts. The idea behind C2 is to manage all of those different sessions and provide additional post-exploitation features to make the quality of life for a red teamer better. If you’ve ever used the Metasploit Framework, you’ve technically used a C2 before! It features custom payload generation, various listeners, session management, and additional post exploitation commands, but you probably don’t need to use many of these things if you only use it to run quick exploits.
Here are some well known command and control frameworks (aside from Sliver):
- Empire - A previously abandoned, open-source C2 brought back to life by BC-Security, heavily based around PowerShell
- Mythic - An open-source C2 framework heavily focused around collaboration, and allows for individuals to create their own implants in whatever language they choose
- Cobalt Strike - A closed-source and infamous C2 framework developed by HelpSystems that is well-known for being a goto for real-world attackers (it’s just that good)
- Brute Ratel - A closed-source “C4” (it’s just marketing) by Chetan Nayak or Paranoid Ninja which has strong networking features
You can read up more about various command and control frameworks in the C2 Matrix, a website that catalogs all of the major C2s, open and closed source, out there right now.
Components
Aside from the C2 server itself, there are two core components you’ll see in almost any C2:
- Listeners. Like when you run
nc -lvnp 1337
, listeners are just applications running on the server that are waiting for a connection on a specific port or protocol. You’ll likely hear about HTTP(S) and DNS the most - Implants/Agents/Payloads/[Cool_Name]. They go by different names depending on the framework, but these are the actual programs that you run on a target computer to get the remote connection back on your C2 server. They can come in many different forms, such as binaries, shellcode, PowerShell commands, or quite frankly just any type of code execution, but getting these programs to run are the key to taking advantage of the C2.
Most frameworks will also have some kind of staging options, post-exploitation modules, multi-user capabilities, etc., but the core pieces are the two mentioned above. It seems very simple in concept, which it is. The complexity comes in the age old question of “How do you want to do this?“. Depending on the situation, you’ll likely end up asking yourself questions like:
- What type of payload should I use?
- Can I get away with X without raising too much suspicion?
- How do I bypass this AV/EDR product?
- How do I make sure I don’t burn through all of my prepared evasion techniques?
And this is where a lot of the creativity and complexity in command and control design/usage comes in, which won’t really be covered here. Our goal today is just to understand the basics (and maybe a little bit more), which should be applicable for any other C2.
Installation
There’s a few ways to go about this. Since 99% of the framework is in Golang, you can really run this on any operating system that there’s a release for, and all you need is the client binary and the server binary. As implied earlier, C2 is an example of client-server architecture, meaning we have a central server to handle our requests, and multiple clients interacting with that server.
An in-depth discussion of good red-team architecture is beyond the scope of this blog (but HuskyHacks has spoken on the subject matter many times), so if you’re like me and just using it for personal use, there’s really not much beyond this. If you are running the C2 on a Linux box, you can use the below one-liner to automatically set it up as a service.
Also, if you don’t already have Metasploit and the MinGW compiler installed, you should do that. This should be as easy as installing the mingw-w64
package on Debian-based Linux or MacOS.
When using Sliver (or any C2 quite frankly), you’ll need to run the server in the background, and use the client to connect to it. If you use the Linux one-liner, this will already be set up for you as a service, so use the appropriate service
or systemctl
command to start and stop it.
Pre-Combat Main Phase: Basic Usage
Generating Implants
Throughout this blog, I will be using a local setup with my Kali VM and a Windows VM on the same network, Sliver being used and installed on the Kali VM.
Suppose, in this fictional scenario, I am attacking this network and am trying to get my first implant down on this Windows host that I already have command execution on. To start, we first need to generate an implant.
I’ll connect to my server by running sliver
.
You can prepend help
to any command to list further options, and I highly encourage you to read up on all of the different options here. However, for the sake of simplicity, we will generate the simplest of implants, which will use the HTTP protocol for a callback.
Note: Sliver (1.5+) has two types of implants, beacons and sessions. Beacons will check in with your server every now and then to see if you’ve told them to do something, and then executes and returns the results. An implant in session mode is a real-time session that is more like a reverse shell. Implants compiled for session mode cannot switch to being beacons, but you can have beacons open up interactive sessions if need be.
From here, I can run an SMB server on my local machine using impacket to transfer it to the remote Windows machine.
And on the Windows machine…
Yep. Sliver has only been getting popular by the day, and its signatures are in Microsoft Defender’s database. An in-depth discussion of evasion techniques is outside the scope of this blog post, so we’ll just disable antivirus for now and try again.
Listeners
Once we’ve taken care of that, all we have to do is set up a listener on our client. In other C2 frameworks, such as Covenant and Empire, this is a little more involved, but here we can just run http
in our shell to start it up. However, http
is not the only listener, and it’s not even the recommended one. Here’s a brief description of what the other listeners are for.
http
/https
- for communication over the HTTP(S) protocol, pretty standard across any C2- You can also use the
websites
command to stage a fake website on the listener port so it looks more legit if someone tries to look at your listener.
- You can also use the
mtls
- communication using mutual-TLS, a protocol in which both the implant and the server present a certificate that the other must validate. If one certificate fails, the connection does not happen.- Note that Sliver does hardcode the TLS configuration so that’s something to think about for OPSEC
wg
- communication using WireGuard, which essentially creates a lightweight VPN to communicate over. This is also a highly recommended option by the devs, but if you want to learn more about this, I think this discussion answers most questionsdns
- definitely one of the more finnicky options where you leverage a domain that you control to transmit data over. This is all UDP and I don’t really recommend it for beginners.
Each of these have their own set of options and capabilities that the wiki/source code can explain much better than I ever could.
Since our beacon was only configured to have an http
callback, we can run http
in our shell and then execute the beacon on the remote Windows computer.
Oh wait you said “Sliver”? Ah, wrong game, my bad.
Combat Phase: Interacting with the Target
Beacons
Now that we have a beacon on the target, what can we do with it? We can list the current beacons we have using the beacons
command.
Recall that beacons are different from sessions in that they will periodically check in about every minute or so by default. From an OPSEC perspective, this is better because it doesn’t look like a reverse shell, which is a continuous connection. I also say that a beacon checks in every minute or so because of jitter. Jitter is essentially making the check-ins more irregular, making it so that the beacon is not checking in at exactly every 60 seconds, because that would also be suspicious.
Tangent aside, we can interact with our beacon with the use
command, followed by the ID of the beacon, which we can use the Tab key for auto fill.
The help
command here shows us a lot of commands we can use. We’re still not in an actual shell (and if we were on a real engagement we might not ever want to enter a full shell), so we don’t have access to every Windows command under the sun, but there’s a lot already out there for us to do.
We can start with the most basic command: ls
.
You’ll notice we did not get a response immediately. This is because any commands we send are actually tasks that are put into a queue, and recieved everytime the beacon checks in. Just wait about a minute, and we see:
If you ever forget what the result of a task was, for documentation or you just don’t want to execute another command, you can use tasks
to list the things you’ve done so far, and then tasks fetch <id>
to fetch the output of a specific task.
A lot of the commands in a beacon might be familiar if you’ve ever used Meterpreter, so I won’t explain every single possible thing you can do. However, differing from Meterpreter, there are a lot more commands to help simplify some of the things you might need to do as a red teamer.
Sessions
To be able to use some of the commands that require a session, we can use interactive
to enter session mode.
You can’t really see it here, but in the UI, the name of the implant is blue when it’s in beacon mode, and red when it’s in session mode. Not only do we now get quicker turnarounds on our tasks, because everything is happening immediately, but we can also use commands like getsystem
, portfwd
, or shell
that require a constant connection. The big downside is that is the beacon process continuously shows up in Task Manager. Ideally, you rename the executable file to svchost.exe
or explorer.exe
or something less suspicious, but the problem still remains.
Other than that, they’re really not that much different than beacons. From a workflow perspective, you’ll almost always default to beacons, then pull out the session if necessary. After all you can only go from beacon to session, not vice versa.
Speaking of which, we can also kill a session to make sure we clean up our steps.
The lowercase -k
flag can be used to specify a specific session, I just wanted to get rid of any and all of them.
Profiles
Once you get deep into the weeds of it, typing out entire generation commands can get quite cumbersome and tedious. To make it easier, you can save your favorite configurations to a profile. Suppose I have a regular setup I like using to generate my beacon shellcode. I can use the below command to save it for later
Then, to generate this beacon shellcode, I can run a profiles generate
You can also generate session implants in the same way, just omit the beacon
part. We can also view what profiles we have saved, and what implants we have generated.
If at any point you accidentally delete an implant or just need to get an implant back, the regenerate
command will create a new one instantly.
Post-Combat Main Phase: Cool Things
Sliver has a lot to offer, and I’ll cover more of these things in a part 2 to this post, but I thought I’d cover a few things that are not entirely Sliver specific.
Staging
Sliver is written in Golang, a programming language that compiles statically by default. This is different from your typical C executable, which is usually linked to external libraries to import commands from. As such, you’ll notice that Sliver’s generated implants are very large by default. This is because of the use of Golang, which compiles statically, meaning that in addition to the program code, the entire standard library of functions (and any other imported libraries) will get baked into the compiled output. Such is the tradeoff for getting very easy cross-compilation.
If you’ve ever used Metasploit, you should be familiar with the idea of a staged versus a stageless payload. A stageless payload is a single binary (or any payload) that contains all of the necessary data to connect back to you, and that’s pretty much the end of the story. A staged payload, also commonly referred to as a “dropper”, is a much smaller payload that, when executed, will call back to the C2 server to download and execute the second stage of the payload in-memory, which is where you actually get the beacon to execute. You may think that staged payloads are just strictly better than stageless payloads, and you’re kind of right. But, certain situations call for different needs, and if you’re interested in further reading about the topic, I recommend checking out Spooky aka NaisuBanana’s blog about that (I totally don’t have the same Jekyll theme as them).
Creating a staged payload, as shown in the docs, is a little confusing, so I’ll walk through a different example slowly. Note that as of right now, the only stager format available is in shellcode, the other options they show you are just ways to use the shellcode, there are no oneliners like Covenant or Empire. With that out of the way, we start by creating a new profile for the implant we want to generate.
After multiple hours of troubleshooting, I was unable to have the stage listener work withUpdate: Turns out I actually stumbled onto a bug where the wronghttps
, the more secure and responsible thing to be doing. Hopefully I remember to update this blog once I get a better answer as to how that works.msfvenom
command was being run. You can see the discussion and the patch for more information about what happened. if i was any faster that could have been a free pr smh
Once we’ve created the profile, we start a listener for the initial callback. We specify the profile to tell the server that when you get a callback on this URL, the agent you should send a Sliver (i.e. agent) with the specified profile. We use the --prepend-size
since we’re going to be using the Metasploit/msfvenom
stager, but if you write your own custom one, you shouldn’t include that flag.
We then start another listener to catch the stage 2 callback.
And then we actually generate the stager with the correct parameters.
If you are having unexpected errors here like
rpc error: code = Unknown desc = exit status 2
, be sure to check the server logs first for troubleshooting. The current version of Sliver requires a fairly recent version of Metasploit, so versioning is something to consider.
We can see the size of this staged payload is remarkably smaller than the stageless binary.
Since I used shellcode, I’ll place it into a simple C++ dropper. This is also a huge benefit of staged payloads, as they’re much easier to work with when developing custom droppers and such. I’m using C++ because it’s the language I first learned when doing malware development with Sektor7 (great courses by the way), but you’re free to insert this into any programming language to your heart’s content. I highly recommend checking out this repo by chvancooten for more info on developing your own loaders and droppers.
We can compile this and also see the smaller binary size.
Running the implant, we get a callback at our C2.
We can see exactly what this looked like on the network using Wireshark. One of the first packets we should see is an HTTP request to some random looking URL, but probably has a .woff
extension in it.
The binary data inside this request is actually the stage 2 payload right there in plain sight! Since our request was done using HTTP instead of HTTPS, anyone eavesdropping or logging this could also probably see this request happening. However, they won’t be able to tell what communication is happening. After scrolling past a lot of repeated ACK packets, we see some TLS packets.
As we have set up an MTLS listener, where both the client and server must verify each others’ certificates, we have a cryptographic exchange where we do all of this verification, and if successful, all sequential packets will be encrypted and unreadable for anyone without the keys.
If you haven’t already noticed, Sliver uses Metasploit to actually generate and handle the staged payloads. With this, we can not only just use Metasploit directly to create staged payloads, but we can also make custom droppers too, as noted in the wiki, which gives us even more flexibility with how we approach payload design. Here, it’s actually very important considering Metasploit is a tool that’s been fingerprinted for who knows how long, and any usable AV/EDR will catch Metasploit shellcode fairly quickly.
Armory
Introduced in Sliver v1.5, the armory is Sliver’s Alias and Extension package manager which allows you to install tools that other people outside of the core Sliver devs have made. We can see all of the different public packages available just by typing armory
.
Obviously, each package plays differently, but we can play around with one of the aliases like sharpsecdump
as a demo. We can use armory install <name>
to install a specific alias or extension.
Once we’ve installed the alias, we can check the help information from an active session.
That warning is a pretty useful read, and I recommend checking it out. When using an alias, pass the Sliver-specific flags first, then use a --
, and then proceed to submit any other flags specific to the alias.
An alias, like seatbelt
, is just an abstraction for using sideload
or execute-assembly
to run a program inside the current process, as opposed to spawning a new child process. Extensions are a little more complicated, as they are shared libraries that get loaded into the Sliver implant, and possibly have additional dependencies.
BOF: Beacon Object Files
The term “Beacon Object File” (BOF) originated from a feature in the well-known Cobalt Strike command and control framework. Quote TrustedSec:
“BOFs allow users to execute code without following Cobalt Strike’s well-defined patterns. Typically, Cobalt Strike will always perform cross-process injection or start cmd.exe / powershell.exe to accomplish its more useful goals […] When a technique is coded using a BOF, you gain the benefit of running code inside of beacon itself and without starting a child process. You also do not have the Indicators of Compromise (IoCs) associated with execute-assembly where you would start your spawn-to process and inject code into it.” Original Blog
Basically (and please correct me if I’m wrong), BOFs allow you to essentially just add additional “functions” and capabilities to your implant without having to compromise OPSEC and fork a process. Sliver implements this through the armory, supported by the COFF Loader extension, so you’ll need to install that first. However, if you install any of the BOFs already available in the armory, the COFF Loader will also be installed anyway.
The usage of the BOFs in the armory is pretty much identical to getting other aliases so I won’t go through that process again. However, if you want to use existing BOFs that are not in the armory, you’ll need to create a manifest.json
file to register them as an extension with your client, and the documentation covers this well enough. That being said, there’s already a lot of them in the armory.
oh wait wrong game again
Ending Phase: Detection
As fun as the l33t h4x are, it is also necessary to understand some of the indicators that Sliver has. This is beneficial to catch people who are being lazy with their usage of the C2, but also only extends the back and forth between detection and evasion. The ideas discussed here are, for the most part, specifically for Sliver- general C2 operation detection is something that’s suited a lot better for a general malware analysis post or something like that.
The two best references I’ve seen for this are linked here, but I’ll run through some of the things that they say here:
- Microsoft - Looking for the ‘Sliver’ lining
- Cyber Attack & Defense - Finding the Sliver Lining Seems like they weren’t all too original with their titles.
One thing to note here is that a highly sophisticated threat actor or adversary is probably not going to be letting the easy default config stuff slip through. Realistically, it’s more important to understand that there is a C2 in play and taking some malware samples and tooling (typical Pyramid of Pain stuff) that they leave rather than to look at an alert and go “hmm, is this Sliver?” That being said, we all make mistakes, and this is still good information.
shell
One of the first things you might stumble into while using the C2 is if you want to drop into a real shell on the remote host, and you’ll get a prompt like this
The C2 is calling you out for good reason. We’ve already talked about the fact that the session itself will be in the currently running processes, but the shell
takes it to a new level. If we drop into a shell, then run some commands, and check the Windows Event Viewer, we’ll see an interesting entry.
The -Command [Console]::OutputEncoding=[Text.UTF8Encoding]::UTF8
(in the event ID 400, 600, or 4104) is actually an indicator for the Sliver implant. However, although this isn’t specific to Sliver, it’ll probably be easier to find this anytime someone runs a whoami
or systeminfo
from that shell. RastaMouse has a good talk on the subject of OPSEC and how you get caught.
psexec
and getsystem
I could have thrown more commands under this header, but the general idea here is that these commands and others are considered core to most major C2 functionality. The exact syntax of the indicators will obviously change from framework to framwork, but many of the indicators of Sliver are well documented in the Microsoft link from before.
In the case of psexec
, Sliver achieves the lateral movement using a service binary, similar to how impacket also handles it. In this case, the detection is very similar. By default, Sliver will run the binary from C:\Windows\Temp
and give it a randomized 10 character name, so just look for that file path in the logs. Alternatively, if a hacker is especially careless, they’ll probably not change the name and description of the service, which are “Sliver” and “Sliver implant” resplectively. To that note, any mention of Sliver as a string, while not 100% guarantee of a Sliver beacon, should at least raise some suspicions when searching.
getsystem
is basically a macro that attempts to inject into another process, spoolsv.exe
by default, and abusing the SeDebugPrivilege
to get NT AUTHORITY\SYSTEM
privileges within that process, pretty much exactly how Meterpreter does it. Sysmon is a great tool for detecting this and I don’t have it installed in my dev machine (nor do I want to being this far into it), but again, a lot of this stuff is already documented. All you have to do is just find the patterns.
Config Extraction
When dealing with an incident response (IR) event, it’s important to be able to get the most information as quickly as possible so that you can take remediation steps quickly. For C2’s, the key to this is attempting to extract the configuration that is stored in the implant. Ippsec has a great video on Malleable Agent Configs and how they might be put together in certain implementations.
An adversary is not going to just leave their config out in the open- that’s just bad practice. Most C2s will encrypt their configurations, and then obfuscate the code itself so static analysis becomes an absolute pain. However, you can’t just use the configuration while it’s encrypted, it has to be decrypted (usually in-memory), and then used. Because this blog post has gone on long enough, however, I will probably save this for a post in the future.
Conclusion
So it turns out C2 is much more complex than I was originally anticipating, so I plan on making a part 2 to this post where I dive into some of the more advanced techniques that Sliver can offer like process hollowing, msf-inject
, etc., but I think this is a good enough place to stop. It’s really cool to see some of these huge projects really push the boundaries of what we can already do, whether it’s through automation or presenting some novel idea. Now that I have a new laptop, I’m hoping to be able to explore some of these complex topics I wasn’t able to do as easily before. It also makes you realize how far behind open-source blue team tooling is in comparison, so maybe that’s a blog post for another day.
Follow me @An00bRektn, and feel free to shoot me a DM if you have any questions, comments, or concerns.
Until next time! :D
References
Definitely collected information from all over the place, here are links that were helpful in putting all of this together that I don’t remember linking explicitly in the blog.
- The Official Wiki - A MUST READ along with the source code
- path_h/to/file - Hunting Sliver
- Dominic Breuker - Learning Sliver C2
- tishina - Sliver OPSEC
- Team Cymru - Sliver Case Study