Endianness
# Value: 0xDEADBEEF
# Big-endian (network order): DE AD BE EF
# Little-endian (x86/x64): EF BE AD DE
# Python pack/unpack
import struct
struct.pack('>I', 0xDEADBEEF) # → b'\xde\xad\xbe\xef' big
struct.pack('<I', 0xDEADBEEF) # → b'\xef\xbe\xad\xde' little
struct.unpack('<I', b'\xef\xbe\xad\xde')[0] # → 3735928559
# struct format characters:
# > = big-endian < = little-endian ! = network (big)
# B = uint8 H = uint16 I = uint32 Q = uint64
# b = int8 h = int16 i = int32 q = int64
Bit operations (Python)
# Bitwise operators
0b1010 & 0b1100 # → 0b1000 AND
0b1010 | 0b1100 # → 0b1110 OR
0b1010 ^ 0b1100 # → 0b0110 XOR
~0b1010 # → -11 NOT (two's complement)
0b0001 << 3 # → 0b1000 left shift = multiply by 2
0b1000 >> 2 # → 0b0010 right shift = divide by 2
# Extract specific bits
val = 0b11010110
bit3 = (val >> 3) & 1 # → bit 3 = 0
nibble_hi = (val >> 4) # → upper nibble = 0b1101 = 13
nibble_lo = val & 0x0F # → lower nibble = 0b0110 = 6
# Set/clear/toggle a bit
val |= (1 << 3) # set bit 3
val &= ~(1 << 3) # clear bit 3
val ^= (1 << 3) # toggle bit 3
Dec / Hex / Bin / ASCII (0–127)
| Dec | Hex | Bin | ASCII |
Dec | Hex | Bin | ASCII |
Dec | Hex | Bin | ASCII |
Dec | Hex | Bin | ASCII |
| 32 | 0x20 | 00100000 | SPACE | 48 | 0x30 | 00110000 | 0 | 65 | 0x41 | 01000001 | A | 97 | 0x61 | 01100001 | a |
| 33 | 0x21 | 00100001 | ! | 49 | 0x31 | 00110001 | 1 | 66 | 0x42 | 01000010 | B | 98 | 0x62 | 01100010 | b |
| 36 | 0x24 | 00100100 | $ | 57 | 0x39 | 00111001 | 9 | 90 | 0x5A | 01011010 | Z | 122 | 0x7A | 01111010 | z |
| 10 | 0x0A | 00001010 | LF \n | 13 | 0x0D | 00001101 | CR \r | 9 | 0x09 | 00001001 | TAB \t | 0 | 0x00 | 00000000 | NULL |
| 123 | 0x7B | 01111011 | { | 125 | 0x7D | 01111101 | } | 95 | 0x5F | 01011111 | _ | 127 | 0x7F | 01111111 | DEL |
# Printable ASCII range: 32 (space) → 126 (~)
# Uppercase A-Z: 0x41–0x5A (65–90) lowercase a-z: 0x61–0x7A (97–122)
# Digits 0-9: 0x30–0x39 (48–57) lowercase = uppercase | 0x20
# picoCTF{ = 70 69 63 6F 43 54 46 7B (hex)
bashASCII ↔ char
# Decimal → char
printf '\x70' # → p (hex escape)
printf '%b' '\x70' # → p
printf '\160' # → p (octal: 160 octal = 0x70 = 112 dec)
echo -e "\x70\x69\x63" # → pic
# Char → decimal/hex
printf '%d' "'p" # → 112 (decimal of 'p')
printf '%x' "'p" # → 70 (hex of 'p')
# String → hex dump
echo -n "picoCTF" | xxd
echo -n "picoCTF" | xxd -p # → 7069636f435446 (no spaces)
echo -n "picoCTF" | od -An -tx1
# od formats: -tx1 hex bytes, -td1 decimal, -tb octal
pythonASCII ↔ char
# char → int
ord('p') # → 112
ord('p') == 0x70 # → True
# int → char
chr(112) # → 'p'
chr(0x70) # → 'p'
# string → bytes → list of ints
list(b'picoCTF') # → [112, 105, 99, 111, 67, 84, 70]
b'picoCTF'.hex() # → '7069636f435446'
# list of ints → string
''.join(chr(c) for c in [112,105,99]) # → 'pic'
bytes([112,105,99]).decode() # → 'pic'
# bytes ↔ string
"hello".encode() # → b'hello'
b'hello'.decode() # → 'hello'
b'hello'.decode('latin-1') # for non-UTF8 bytes
bashHex conversions
# Dec → hex
printf '%x\n' 255 # → ff
printf '%X\n' 255 # → FF (uppercase)
printf '%08x\n' 255 # → 000000ff (zero-padded 8 chars)
echo "obase=16; 255" | bc # → FF
# Hex → dec
printf '%d\n' 0xff # → 255
echo "ibase=16; FF" | bc # → 255 (uppercase required for bc)
$(( 16#ff )) # → 255 (bash arithmetic)
# Hex string → bytes → file
echo "7069636f435446" | xxd -r -p # → picoCTF
echo "7069636f435446" | xxd -r -p > out.bin
# Hex dump a file
xxd file.bin
xxd -p file.bin # plain hex, no offsets
xxd -l 16 file.bin # first 16 bytes only
xxd -s 0x100 file.bin # start at offset 0x100
pythonHex conversions
# Int → hex string
hex(255) # → '0xff'
f'{255:#010x}' # → '0x000000ff' (padded)
f'{255:08x}' # → '000000ff' (no prefix)
f'{255:02X}' # → 'FF'
# Hex string → int
int('ff', 16) # → 255
int('0xff', 16) # → 255
int('0xdeadbeef', 0) # → auto-detect base
# Hex string → bytes
bytes.fromhex('7069636f') # → b'pico'
import binascii
binascii.unhexlify('7069636f') # → b'pico'
# Bytes → hex string
b'pico'.hex() # → '7069636f'
b'pico'.hex(':') # → '70:69:63:6f' (separator)
binascii.hexlify(b'pico') # → b'7069636f'
bashBinary conversions
# Dec → binary
echo "obase=2; 65" | bc # → 1000001
printf '%08d\n' $(echo "obase=2; 65" | bc) # → 01000001
# Binary → dec
echo "ibase=2; 01000001" | bc # → 65
$(( 2#01000001 )) # → 65 (bash arithmetic)
# Binary string → bytes → ASCII (your image challenge!)
python3 -c "
bits = open('data.txt').read().replace('\n','').replace(' ','')
data = bytes(int(bits[i:i+8],2) for i in range(0,len(bits),8))
open('out.bin','wb').write(data)
"
file out.bin # check type
# Count bits set (popcount)
python3 -c "print(bin(0xFF).count('1'))" # → 8
pythonBinary conversions
# Int → binary string
bin(65) # → '0b1000001'
f'{65:08b}' # → '01000001' (8-bit, zero-padded)
f'{65:b}' # → '1000001' (no padding)
# Binary string → int
int('01000001', 2) # → 65
int('0b01000001', 2) # → 65
# Bytes → binary string (per byte)
for b in b'Hi':
print(f'{b:08b}') # → 01001000 01101001
# Binary string → bytes
bits = '0100100001101001' # 'Hi'
data = bytes(int(bits[i:i+8],2) for i in range(0,len(bits),8))
# → b'Hi'
# All formats at once
n = 65
print(bin(n), oct(n), hex(n), n) # 0b1000001 0o101 0x41 65
bashEncode & decode
# Base64 encode / decode
echo -n "picoCTF" | base64 # → cGljb0NURg==
echo "cGljb0NURg==" | base64 -d # → picoCTF
# File encode / decode
base64 file.bin > file.b64
base64 -d file.b64 > file.bin
# Base32
echo -n "picoCTF" | base32 # → OBWGKYLTEB3W4===
echo "OBWGKYLTEB3W4===" | base32 -d
# Remove newlines from base64 output
base64 file.bin | tr -d '\n'
# URL-safe base64 (- and _ instead of + and /)
echo -n "hello" | base64 | tr '+/' '-_' | tr -d '='
pythonBase64/32/16
import base64
# Base64
base64.b64encode(b'picoCTF') # → b'cGljb0NURg=='
base64.b64decode('cGljb0NURg==') # → b'picoCTF'
# URL-safe base64
base64.urlsafe_b64encode(b'data')
base64.urlsafe_b64decode('ZGF0YQ==')
# Base32
base64.b32encode(b'picoCTF') # → b'OBWGKYLTEB3W4==='
base64.b32decode('OBWGKYLTEB3W4===')
# Base16 (= hex uppercase)
base64.b16encode(b'pico') # → b'7069636F'
base64.b16decode('7069636F') # → b'pico'
# Handle missing padding
s = 'cGljb0NURg' # missing ==
base64.b64decode(s + '==' * (4 - len(s)%4 if len(s)%4 else 0))
bashCut & slice
# cut — extract fields/columns
echo "aa:bb:cc:dd" | cut -d: -f2 # → bb
echo "aa:bb:cc:dd" | cut -d: -f2-4 # → bb:cc:dd
echo "abcdef" | cut -c3-5 # → cde (chars 3-5)
# dd — extract raw bytes from file
dd if=file.bin of=out.bin bs=1 skip=16 count=4 # bytes 16-19
dd if=file.bin of=out.bin bs=512 skip=2 count=1 # block 2
# head / tail — byte ranges
head -c 16 file.bin # first 16 bytes
tail -c 16 file.bin # last 16 bytes
tail -c +17 file.bin # from byte 17 to end
# Combine: extract bytes 10-20
head -c 20 file.bin | tail -c +11
pythonSlice & pack
# Bytes slicing
data = b'\x00\x01\x02\x03\x04\x05\x06\x07'
data[2:5] # → b'\x02\x03\x04'
data[:4] # → first 4 bytes
data[4:] # → from byte 4 to end
data[::2] # → every other byte
data[::-1] # → reversed
# struct — parse binary data
import struct
# Unpack: big-endian uint32 at offset 0
struct.unpack_from('>I', data, offset=0) # → (66051,)
# Pack multiple values
struct.pack('>HHI', 1, 2, 0xdeadbeef) # → 8 bytes
# Split into N-byte chunks
n = 4
chunks = [data[i:i+n] for i in range(0, len(data), n)]
# int.to_bytes / from_bytes
(0xdeadbeef).to_bytes(4, 'big') # → b'\xde\xad\xbe\xef'
int.from_bytes(b'\xde\xad\xbe\xef', 'big') # → 3735928559
bashNetcat / raw bytes
# Send plain string
echo "hello" | nc host 1337
# Send WITHOUT trailing newline
echo -n "hello" | nc host 1337
printf "hello" | nc host 1337
# Send raw hex bytes
printf '\xde\xad\xbe\xef' | nc host 1337
echo "deadbeef" | xxd -r -p | nc host 1337
# Send binary file
cat payload.bin | nc host 1337
nc host 1337 < payload.bin
# Interactive: keep connection open after sending
(echo "input"; cat) | nc host 1337
# Send multiple lines with delay
{ echo "line1"; sleep 1; echo "line2"; } | nc host 1337
# Build payload inline and send
python3 -c "import sys; sys.stdout.buffer.write(b'A'*40 + b'\xef\xbe\xad\xde')" \
| nc host 1337
pythonsocket / pwntools
# Raw socket
import socket
s = socket.socket()
s.connect(('host', 1337))
s.send(b'hello\n') # send bytes
s.send(bytes.fromhex('deadbeef'))
print(s.recv(1024)) # receive up to 1024 bytes
s.close()
# pwntools (best for CTF)
from pwn import *
p = remote('host', 1337)
# or local: p = process('./challenge')
p.recvuntil(b'Enter: ') # wait for prompt
p.sendline(b'answer') # send + \n
p.send(b'\xde\xad\xbe\xef') # raw bytes, no \n
p.sendlineafter(b'> ', b'cmd') # wait then send
data = p.recvline() # read one line
p.interactive() # manual shell
Build payloads for nc
# Pattern: read prompt → compute answer → send
python3 -c "
import socket, struct
s = socket.socket()
s.connect(('host', 1337))
# Read challenge
data = s.recv(1024)
print('Got:', data)
# Build response (example: send 4-byte little-endian int)
answer = struct.pack('
# One-liner for simple sends
python3 -c "print('A'*100)" | nc host 1337
python3 -c "import sys; sys.stdout.buffer.write(b'\x00'*8)" | nc host 1337
# ncat with ssl
ncat --ssl host 1337
bashRead & write raw bytes
# Write hex bytes to file
echo "deadbeef0102030405" | xxd -r -p > out.bin
printf '\xde\xad\xbe\xef' > out.bin
# Append bytes
printf '\x00\x01' >> out.bin
# Check file size in bytes
wc -c < file.bin
stat -c %s file.bin
ls -la file.bin
# Search for byte pattern in file
grep -boa $'\xde\xad' file.bin # byte offset of pattern
xxd file.bin | grep "dead"
# Patch a byte at offset (example: offset 10, byte 0x41)
printf '\x41' | dd of=file.bin bs=1 seek=10 conv=notrunc
# Split file at byte boundary
split -b 512 file.bin chunk_ # 512-byte chunks
pythonRead & write raw bytes
# Read entire file as bytes
data = open('file.bin', 'rb').read()
# Write bytes
open('out.bin', 'wb').write(b'\xde\xad\xbe\xef')
# Patch byte at offset
data = bytearray(open('file.bin','rb').read())
data[10] = 0x41 # patch offset 10
data[10:14] = b'\xde\xad\xbe\xef' # patch 4 bytes
open('patched.bin','wb').write(data)
# Search for pattern
pos = data.find(b'\xde\xad') # → byte offset or -1
all_pos = [i for i in range(len(data)) if data[i:i+2] == b'\xde\xad']
# Hexdump (manual)
for i in range(0, min(64, len(data)), 16):
chunk = data[i:i+16]
print(f'{i:04x}', chunk.hex(' '), '|', chunk.decode('latin-1'))
bashCommon one-liners
# Hex string → ASCII text
echo "7069636f4354467b74657374 7d" | tr -d ' ' | xxd -r -p # → picoCTF{test}
# Binary string → ASCII (like the image challenge)
python3 -c "
bits='0111000001101001011000110110111101000011010101000100011001111011'
print(bytes(int(bits[i:i+8],2) for i in range(0,len(bits),8)).decode())
" # → picoCTF{
# Decimal list → ASCII
python3 -c "print(bytes([112,105,99,111,67,84,70]).decode())" # → picoCTF
# Base64 → hex
echo "cGljb0NURg==" | base64 -d | xxd -p # → 7069636f435446
# Hex → base64
echo "7069636f435446" | xxd -r -p | base64 # → cGljb0NURg==
# ROT13
echo "cvpbPGS{...}" | tr 'A-Za-z' 'N-ZA-Mn-za-m'
# URL encode
python3 -c "from urllib.parse import quote; print(quote('hello world'))"
# URL decode
python3 -c "from urllib.parse import unquote; print(unquote('hello%20world'))"
# String → little-endian 64-bit int (for stack overflow payloads)
python3 -c "import struct; print(struct.pack('<Q', 0x401234).hex())" # → 341240000000000
pythonSwiss-army conversion function
# Drop this at the top of any CTF solve script
from pwn import * # p8/p16/p32/p64, u8/u16/u32/u64, xor, enhex, unhex
import base64, struct, binascii
# pwntools shortcuts
p32(0xdeadbeef) # → b'\xef\xbe\xad\xde' (little-endian)
p64(0xdeadbeef) # → 8 bytes LE
u32(b'\xef\xbe\xad\xde') # → 0xdeadbeef
xor(b'data', b'key') # → XOR bytes
enhex(b'pico') # → '7069636f'
unhex('7069636f') # → b'pico'
# Common conversions table
string → bytes : s.encode() or b'literal'
bytes → string : b.decode() or b.decode('latin-1')
bytes → hex : b.hex() or enhex(b)
hex → bytes : bytes.fromhex(h) or unhex(h)
int → bytes : n.to_bytes(length, 'little')
bytes → int : int.from_bytes(b, 'little')
int → b64 : base64.b64encode(n.to_bytes(...))
bits → bytes : bytes(int(bits[i:i+8],2) for i in range(0,len(bits),8))
bashrax2 — radare2 base/format converter
rax2 0x1337 # hex → decimal (4919)
rax2 4919 # decimal → 0x1337
rax2 -s 41424344 # hex pairs → string (ABCD)
rax2 -S ABCD # string → hex pairs (41424344)
rax2 -Z 0111000001101001 # binary string → string (pi)
rax2 -e 0x1337 # swap endianness
# CyberChef for CHAINED conversions: stack ops in one recipe,
# e.g. From_Base64 → From_Hex → XOR → Gunzip, or drop data
# into the "Magic" op to auto-suggest the decode chain.
# CLI: cchef bake -e "From_Base64()From_Hex()" input
QUICK REFERENCE →
1 byte = 8 bits = 2 hex digits = 1 ASCII char (if printable)
· hex↔bytes: xxd -r -p / bytes.fromhex()
· raw to nc: printf '\xde\xad' | nc host port
· binary→bytes: int(bits[i:i+8], 2) per 8-bit chunk
· endian pack: struct.pack('<I', val) little / '>I' big
· pwntools: p32/p64/u32/u64 for exploit payloads