Convert any binary file to shellcode-usable output formats. Supports multiple output languages, chainable encoding, bad char scanning, analysis tools, transforms, and verification.
- Usage
- Output Formats
- Encoding
- Analysis
- Transforms
- Options
- Stdin Support
- Combining Flags
- Exit Codes
- Install
- License
bin2sc.py <file> <format(s)> [encoding(s)] [options]
bin2sc.py - <format(s)> [encoding(s)] [options]Pass - as the file to read raw bytes from stdin.
Multiple format flags can be combined in a single run. Each produces a separate block in the output.
C unsigned char array, 12 bytes per line. Also emits a _len variable.
If an encoding flag is present, a matching C decoder stub is appended.
bin2sc.py payload.bin --c
bin2sc.py payload.bin --c --name buf --arch x64Output:
/* x64 shellcode - 6 bytes */
unsigned char buf[] = {
0x48, 0x31, 0xc0, 0x48, 0x31, 0xff
};
unsigned int buf_len = 6;Python bytes literal in parentheses, 16 bytes per line. Also emits a _len
variable. If an encoding flag is present, a matching Python decoder stub is
appended.
bin2sc.py payload.bin --python
bin2sc.py payload.bin --python --name sc --arch x86Output:
# x86 shellcode - 6 bytes
sc = (
b"\x48\x31\xc0\x48\x31\xff"
)
sc_len = 6C# byte[] array, 16 bytes per line. Standard format for .NET loaders,
Cobalt Strike BOFs, and offensive C# tooling.
bin2sc.py payload.bin --csharp
bin2sc.py payload.bin --csharp --name shellcode --arch x64Output:
// x64 shellcode - 6 bytes
byte[] shellcode = new byte[6] {
0x48, 0x31, 0xc0, 0x48, 0x31, 0xff
};PowerShell [Byte[]] array, 16 bytes per line, using backtick line
continuation.
bin2sc.py payload.bin --powershell
bin2sc.py payload.bin --powershell --name bufOutput:
[Byte[]] $buf = `
0x48,0x31,0xc0,0x48,0x31,0xff
$buf_len = 6Java byte[] array, 8 entries per line. Values above 0x7F are cast with
(byte) since Java bytes are signed.
bin2sc.py payload.bin --java
bin2sc.py payload.bin --java --name payloadOutput:
byte[] payload = {
0x48, 0x31, 0xc0, (byte)0xff
};
int payload_len = 4;Go []byte slice, 12 bytes per line.
bin2sc.py payload.bin --go
bin2sc.py payload.bin --go --name sc --arch x64Output:
// x64 shellcode - 6 bytes
var sc = []byte{
0x48, 0x31, 0xc0, 0x48, 0x31, 0xff,
}
var scLen = 6Rust &[u8] static byte array, 12 bytes per line. Variable name is
uppercased per Rust convention.
bin2sc.py payload.bin --rust
bin2sc.py payload.bin --rust --name payload --arch x64Output:
// x64 shellcode - 6 bytes
static PAYLOAD: &[u8] = &[
0x48, 0x31, 0xc0, 0x48, 0x31, 0xff,
];
const PAYLOAD_LEN: usize = 6;NASM db format, 12 bytes per line. Uses equ $ - label for size.
bin2sc.py payload.bin --nasm
bin2sc.py payload.bin --nasm --name sc --arch x86Output:
; x86 shellcode - 6 bytes
sc: db 0x48, 0x31, 0xc0, 0x48, 0x31, 0xff
sc_len equ $ - scFASM db format, 12 bytes per line. Uses $ - label for size.
bin2sc.py payload.bin --fasm
bin2sc.py payload.bin --fasm --name sc --arch x86Output:
; x86 shellcode - 6 bytes
sc db 0x48, 0x31, 0xc0, 0x48, 0x31, 0xff
sc_size = $ - scMASM BYTE format with 0NNh suffix hex style, 12 bytes per line.
bin2sc.py payload.bin --masm
bin2sc.py payload.bin --masm --name sc --arch x86Output:
; x86 shellcode - 6 bytes
sc BYTE 048h, 031h, 0c0h, 048h, 031h, 0ffh
sc_len EQU $ - scBase64 encoded output split into 76-character lines, wrapped in a Python
block with an inline base64.b64decode call for direct use in scripts.
bin2sc.py payload.bin --base64Output:
# 6 bytes (8 base64 chars)
shellcode_b64 = (
"SDHASDHw"
)
import base64
shellcode = base64.b64decode(''.join(shellcode_b64))UUID shellcode format for UuidFromStringA / RtlEthernetStringToAddress
injection techniques. Pads the payload to a 16-byte boundary with NOPs
(0x90), then encodes each 16-byte block as a UUID string with correct
little-endian field ordering.
bin2sc.py payload.bin --uuid --arch x64Output:
# x64 shellcode - 16 bytes as UUIDs
# Usage: call UuidFromStringA on each entry, write to RWX buffer
shellcode_uuids = [
"c0314831-ff31-9090-9090-909090909090",
]
shellcode_count = 1xxd-style hex dump: offset, hex bytes, ASCII representation. 16 bytes per
line. Non-printable bytes shown as . in the ASCII column.
bin2sc.py payload.bin --hex-dumpOutput:
00000000 48 31 c0 48 31 ff 90 90 90 90 90 90 90 90 90 90 |H1.H1...........|
Clean uppercase hex string with no prefix, separators, or line breaks. Useful for pasting into CyberChef, Wireshark display filters, debugger search boxes, or any tool that expects raw hex input.
bin2sc.py payload.bin --hex
bin2sc.py payload.bin --xor 0x41 --hexOutput:
4831C04831FF
Single continuous \xNN hex string on one line. Paste directly into Python,
C strings, or any tool that uses this notation.
bin2sc.py payload.bin --linearOutput:
\x48\x31\xc0\x48\x31\xff
Write raw binary bytes to stdout or to --out. Use for piping or saving a
binary-transformed payload.
bin2sc.py payload.bin --xor 0x41 --raw --out encoded.bin
bin2sc.py payload.bin --raw | xxd | headEncoding flags are chainable and applied left to right in a fixed order:
xor -> xor-rolling -> not -> add -> sub. The decoder stubs
(emitted automatically with --c and --python) reverse this order.
Single-byte XOR. Every byte is XOR'd with the same key.
bin2sc.py payload.bin --xor 0x41 --cProduces a C array of the XOR'd bytes plus a decoder stub that XORs again
with 0x41 to restore the original.
Rolling XOR. Cycles through the key list: byte[0]^keys[0], byte[1]^keys[1],
..., wrapping back to keys[0] after the last key. Harder to detect than
single-key XOR because the repeating pattern is len(keys) bytes wide.
bin2sc.py payload.bin --xor-rolling "0x41,0x42,0x43" --cBitwise NOT. Flips every bit in every byte. Applying NOT twice restores the original, so the decoder just runs NOT again.
bin2sc.py payload.bin --not --linearAdd a constant value to every byte, wrapping at 256.
bin2sc.py payload.bin --add 0x05 --cSubtract a constant value from every byte, wrapping at 256.
bin2sc.py payload.bin --sub 0x13 --pythonFlags combine in order. The decoder stubs undo them in reverse.
bin2sc.py payload.bin --xor 0x41 --add 0x05 --c
bin2sc.py payload.bin --not --xor-rolling "0x11,0x22,0x33" --pythonTry all 255 possible single-byte XOR keys (skipping 0x00) and report
which ones produce zero bad char hits. Requires --badchars.
bin2sc.py payload.bin --xor-auto --badchars "\x00\x0a\x0d"Output lists each clean key and suggests the first one as a --xor argument.
Analysis flags operate on the original data before transforms and encoding. They print to stderr so they do not interfere with format output on stdout.
Scan for bad characters and report their offsets. Accepts \x00\x0a,
00 0a, or 0x00 0x0a notation. Works with any format or encoding flag.
bin2sc.py payload.bin --badchars "\x00\x0a\x0d"
bin2sc.py payload.bin --xor 0x41 --c --badchars "\x00\x0a\x0d"When combined with encoding, bad char hits are reported for both the original and the encoded output so you can verify the encoding eliminated them.
Check whether the payload contains any null bytes (0x00). Reports the count
and offsets if found, and notes whether the payload is safe for
strcpy/strlen-based copy routines.
bin2sc.py payload.bin --null-free
bin2sc.py payload.bin --xor 0x41 --null-free --cFind contiguous runs of printable ASCII (0x20-0x7e), minimum 4 bytes. Useful for spotting embedded strings, identifying known code patterns, or checking alphanumeric shellcode constraints.
bin2sc.py payload.bin --printableOutput:
============= PRINTABLE RANGES (3 found, min 4 bytes) ==============
Offset range Len String
-------------------- ----- ----------------------------------------
0x0005 - 0x000F 11 'Hello World'
Byte frequency histogram for the top 32 most common bytes. Bar width is scaled to the most frequent byte. Printable bytes show their ASCII character alongside the hex value.
bin2sc.py payload.bin --freq
bin2sc.py payload.bin --xor 0x41 --freqUseful for confirming encoding changed the byte distribution, or spotting a
dominant byte (such as 0x00 in sparse data) before choosing an XOR key.
Output:
========== BYTE FREQUENCY (top 8 of 8 unique) ===========
Byte Count Pct Histogram
------ ------ ------ ----------------------------------------
0x6c l 384 18.8% |########################################|
0x00 256 12.5% |########################## |
Search for a specific byte sequence and report all matching offsets.
Accepts \x90\x90, 90 90, or 0x90 0x90 notation.
bin2sc.py payload.bin --find-pattern "\x48\x31\xc0"
bin2sc.py payload.bin --find-pattern "90 90 90 90"Output shows a numbered table of all offsets, capped at 64 with an overflow count. Useful for locating function prologues, NOPs sleds, known signatures, or verifying a patch landed at the right location.
Print size, entropy, null byte count, bad chars (if --badchars is set),
and MD5/SHA1/SHA256 hashes, then exit without producing any format output.
Both flags behave identically.
bin2sc.py payload.bin --hash
bin2sc.py payload.bin --stats-only --badchars "\x00"Byte-by-byte comparison between the input file and FILE_B. Reports size,
total differences, a table of the first 64 differing offsets, and MD5 hashes
for both files.
bin2sc.py original.bin --diff modified.binAfter applying the encoding chain, decode the encoded payload in-memory in reverse order and assert it matches the original byte-for-byte. Exits with code 1 if verification fails and prints the first mismatching offset.
Use this whenever working with chained encoders to catch silent bugs such as a wrong key, wrong order, or off-by-one in the rolling XOR.
bin2sc.py payload.bin --xor 0x41 --add 0x05 --c --verify
bin2sc.py payload.bin --xor-rolling "0x11,0x22" --not --verify --linearOutput on success:
============================= VERIFY ROUND-TRIP ==============================
Original size : 2048 bytes
Encoded size : 2048 bytes
Decoded size : 2048 bytes
[+] Result : PASS -- decoded matches original exactly
Transforms are applied to the data before encoding. Order of application:
--patch -> --size-align -> --reverse.
Patch a single byte at the given offset before output. Both offset and value
accept decimal or 0x hex notation.
bin2sc.py payload.bin --patch "0x10 0x90" --c
bin2sc.py payload.bin --patch "16 144" --linearUseful for replacing a placeholder byte in a template payload or converting
a jmp target without reassembling.
Pad the payload to the next multiple of N bytes using NOP instructions
(0x90). Applied before encoding.
bin2sc.py payload.bin --size-align 4096 --c
bin2sc.py payload.bin --size-align 16 --uuidUseful for page-boundary alignment, loader requirements, or ensuring the UUID format receives full 16-byte blocks without unexpected NOP padding.
Reverse the byte order of the entire payload before encoding. Used in injection techniques where a loader writes bytes onto the stack from high address to low, or walks a buffer in reverse.
bin2sc.py payload.bin --reverse --linear
bin2sc.py payload.bin --reverse --xor 0x41 --cSet the variable name used in all format outputs. Default is shellcode.
bin2sc.py payload.bin --c --name buf
bin2sc.py payload.bin --python --rust --name stage2Add an architecture label as a comment in the output header. Has no effect on the bytes themselves.
bin2sc.py payload.bin --c --arch x64
bin2sc.py payload.bin --nasm --arch x86Write text output to a file instead of stdout. Binary output (--raw) also
uses this flag, but cannot share it with text formats in the same run.
bin2sc.py payload.bin --c --out shellcode.h
bin2sc.py payload.bin --python --out sc.py --name buf --arch x64Pass - as the filename to read from stdin. Useful for pipeline use.
cat payload.bin | bin2sc.py - --linear
cat payload.bin | bin2sc.py - --xor 0x41 --c --arch x64
cat payload.bin | bin2sc.py - --xor 0x41 --verify --hexMost flags are orthogonal and compose freely. A typical workflow:
# Check the payload first
bin2sc.py payload.bin --hash --badchars "\x00\x0a\x0d"
# Find a clean XOR key
bin2sc.py payload.bin --xor-auto --badchars "\x00\x0a\x0d"
# Encode, verify, and output in two formats
bin2sc.py payload.bin --xor 0x41 --verify --c --python \
--badchars "\x00\x0a\x0d" --arch x64 --name buf --out output.h
# Encode, save raw binary, check freq
bin2sc.py payload.bin --xor 0x41 --raw --out encoded.bin
bin2sc.py encoded.bin --freq0 Success
1 Error (file not found, invalid argument, --verify failed)
git clone https://github.com/0xNullll/bin2sc
cd bin2sc
python3 bin2sc.pyThis project is released under the MIT license. See LICENSE for full text.