kavklaw@llm $ cat encoding-decoding.md
Base64, hex, URL encoding, ROT13, JWT, ASCII tables, and every CLI one-liner you need for CTFs.
Encodes binary data as ASCII text using 64 characters (A-Z, a-z, 0-9, +, /) with = padding.
# Encode
echo -n "Hello World" | base64
# SGVsbG8gV29ybGQ=
# Decode
echo "SGVsbG8gV29ybGQ=" | base64 -d
# Hello World
# Encode a file
base64 file.bin > file.b64
cat file.bin | base64 -w 0 # No line wrapping
# Decode a file
base64 -d file.b64 > file.bin
# Python
python3 -c "import base64; print(base64.b64encode(b'Hello World').decode())"
python3 -c "import base64; print(base64.b64decode('SGVsbG8gV29ybGQ=').decode())"
# Base64 URL-safe variant (used in JWTs)
python3 -c "import base64; print(base64.urlsafe_b64encode(b'Hello World').decode())"
# Uses - and _ instead of + and /
# OpenSSL
echo -n "Hello" | openssl base64
echo "SGVsbG8=" | openssl base64 -d
Detect Base64:
- Charset: A-Za-z0-9+/=
- Length is multiple of 4
- Ends with 0-2 '=' padding characters
- No spaces or special chars (unless line-wrapped)
# String to hex
echo -n "Hello" | xxd -p
# 48656c6c6f
# Hex to string
echo "48656c6c6f" | xxd -r -p
# Hello
# Full hex dump with offsets
echo -n "Hello World" | xxd
# 00000000: 4865 6c6c 6f20 576f 726c 64 Hello World
# Hex dump of a file
xxd file.bin | head -20
# Python hex
python3 -c "print(bytes.fromhex('48656c6c6f').decode())"
python3 -c "print('Hello'.encode().hex())"
# Hex to decimal
printf "%d\n" 0x41 # 65
echo "ibase=16; 41" | bc # 65
# Decimal to hex
printf "%x\n" 65 # 41
printf "0x%02x\n" 65 # 0x41
# Using od (octal dump) for hex
echo -n "Hello" | od -A x -t x1z
# 000000 48 65 6c 6c 6f >Hello<
Dec Hex Char Dec Hex Char Dec Hex Char
βββββββββββββββββββββββββββββββββββββββββββββββββββ
32 20 (space) 64 40 @ 96 60 `
33 21 ! 65 41 A 97 61 a
34 22 " 66 42 B 98 62 b
35 23 # 67 43 C 99 63 c
36 24 $ 68 44 D 100 64 d
37 25 % 69 45 E 101 65 e
38 26 & 70 46 F 102 66 f
39 27 ' 71 47 G 103 67 g
40 28 ( 72 48 H 104 68 h
41 29 ) 73 49 I 105 69 i
42 2a * 74 4a J 106 6a j
43 2b + 75 4b K 107 6b k
44 2c , 76 4c L 108 6c l
45 2d - 77 4d M 109 6d m
46 2e . 78 4e N 110 6e n
47 2f / 79 4f O 111 6f o
48 30 0 80 50 P 112 70 p
49 31 1 81 51 Q 113 71 q
50 32 2 82 52 R 114 72 r
51 33 3 83 53 S 115 73 s
52 34 4 84 54 T 116 74 t
53 35 5 85 55 U 117 75 u
54 36 6 86 56 V 118 76 v
55 37 7 87 57 W 119 77 w
56 38 8 88 58 X 120 78 x
57 39 9 89 59 Y 121 79 y
58 3a : 90 5a Z 122 7a z
59 3b ; 91 5b [ 123 7b {
60 3c < 92 5c \ 124 7c |
61 3d = 93 5d ] 125 7d }
62 3e > 94 5e ^ 126 7e ~
63 3f ? 95 5f _ 127 7f DEL
Key Control Characters:
0 00 NUL (null byte β string terminator in C)
9 09 TAB (horizontal tab)
10 0a LF (line feed β Unix newline)
13 0d CR (carriage return β Windows newline = CR+LF)
27 1b ESC (escape)
# Quick lookup
man ascii
python3 -c "print(ord('A'))" # char β decimal: 65
python3 -c "print(chr(65))" # decimal β char: A
printf "\\x41\n" # hex β char: A
Character Encoded Purpose / Notes
βββββββββββββββββββββββββββββββββββββββββββββββ
(space) %20 (or + in form data)
! %21 Sometimes reserved
" %22 HTML attribute delimiter
# %23 Fragment identifier
$ %24 Reserved
% %25 Encoding escape character itself
& %26 Parameter separator
' %27 XSS vector
( %28 Grouping
) %29 Grouping
+ %2B Space in form data
, %2C List delimiter
/ %2F Path separator
: %3A Port / scheme separator
; %3B Parameter delimiter
< %3C HTML tag β XSS
= %3D Key-value separator
> %3E HTML tag β XSS
? %3F Query string start
@ %40 Userinfo separator
[ %5B IPv6 / bracket
] %5D IPv6 / bracket
\ %5C Directory traversal
{ %7B Template injection
| %7C Command injection
} %7D Template injection
# CLI encode/decode
python3 -c "from urllib.parse import quote; print(quote('hello world&foo=bar'))"
# hello%20world%26foo%3Dbar
python3 -c "from urllib.parse import unquote; print(unquote('hello%20world%26foo%3Dbar'))"
# hello world&foo=bar
# Double URL encoding (bypass WAFs)
< β %3C β %253C
' β %27 β %2527
Character Named Entity Numeric Hex Entity
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
< < < <
> > > >
& & & &
" " " "
' ' ' '
(space)    
/ (none) / /
XSS Bypass via HTML Entities:
<script>alert(1)</script>
<img src=x onerror=alert(1)>
# Python encode/decode
python3 -c "import html; print(html.escape('<script>alert(1)</script>'))"
python3 -c "import html; print(html.unescape('<script>'))"
ROT13: Shift each letter 13 positions. Applying twice returns original.
AβN BβO CβP DβQ EβR FβS GβT
HβU IβV JβW KβX LβY MβZ
# ROT13 in CLI
echo "Hello World" | tr 'A-Za-z' 'N-ZA-Mn-za-m'
# Uryyb Jbeyq
# ROT13 decode (same command β it's symmetric!)
echo "Uryyb Jbeyq" | tr 'A-Za-z' 'N-ZA-Mn-za-m'
# Hello World
# Python ROT13
python3 -c "import codecs; print(codecs.encode('Hello', 'rot_13'))"
# General Caesar cipher (shift N)
# ROT-N: replace 13 with desired shift
echo "Hello" | tr 'A-Za-z' 'D-ZA-Cd-za-c' # ROT3 (classic Caesar)
# Brute force all 26 rotations
for i in $(seq 0 25); do echo "ROT-$i: $(echo 'Uryyb' | python3 -c "
import sys; s=sys.stdin.read().strip()
print(''.join(chr((ord(c)-97+$i)%26+97) if c.islower() else chr((ord(c)-65+$i)%26+65) if c.isupper() else c for c in s))
")"; done
Structure: HEADER.PAYLOAD.SIGNATURE
xxxxx.yyyyy.zzzzz
Each part is Base64URL-encoded JSON (no padding =).
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β HEADER (algorithm & type) β
β {"alg": "HS256", "typ": "JWT"} β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β PAYLOAD (claims / data) β
β {"sub": "1234567890", "name": "admin", "iat": ...} β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β SIGNATURE β
β HMACSHA256(base64url(header) + "." + β
β base64url(payload), secret) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Common Claims:
iss Issuer
sub Subject (user ID)
aud Audience
exp Expiration time (Unix timestamp)
iat Issued at
nbf Not before
jti JWT ID (unique identifier)
# Decode JWT (without verification)
echo "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0In0.xxx" | \
cut -d. -f2 | base64 -d 2>/dev/null; echo
# Python decode
python3 -c "
import base64, json, sys
token = sys.argv[1]
for part in token.split('.')[:2]:
padded = part + '=' * (4 - len(part) % 4)
print(json.dumps(json.loads(base64.urlsafe_b64decode(padded)), indent=2))
" "YOUR_JWT_HERE"
JWT Attack Vectors:
alg:none Set algorithm to "none" β skip signature verification
alg:HS256βRS256 Confusion: sign with public key as HMAC secret
Weak secret Brute force HMAC key: hashcat -m 16500 jwt.txt wordlist
kid injection Key ID header β path traversal / SQL injection
jwk injection Embed attacker's key in JWT header
exp bypass Modify expiration claim
# jwt_tool (all-in-one JWT testing)
python3 jwt_tool.py JWT_TOKEN -T # Tamper mode
python3 jwt_tool.py JWT_TOKEN -C -d wordlist.txt # Crack secret
# Unicode code point to character
python3 -c "print('\u0041')" # A
python3 -c "print('\U0001F600')" # π
# Character to code point
python3 -c "print(hex(ord('A')))" # 0x41
python3 -c "print(f'U+{ord(\"A\"):04X}')" # U+0041
# UTF-8 encoding (bytes)
python3 -c "print('A'.encode('utf-8'))" # b'A' (1 byte)
python3 -c "print('Γ©'.encode('utf-8').hex())" # c3a9 (2 bytes)
python3 -c "print('β¬'.encode('utf-8').hex())" # e282ac (3 bytes)
python3 -c "print('π'.encode('utf-8').hex())" # f09f9880 (4 bytes)
Unicode Security Issues:
Homoglyph attacks β Π°dmin (Cyrillic 'Π°') vs admin (Latin 'a')
Right-to-left override β U+202E reverses text display
Null byte β %00 / \x00 truncation
Overlong UTF-8 β Encode / as C0 AF to bypass filters
Case mapping β Γ β SS (German sharp S), Δ± β I (Turkish)
Normalization β NFC vs NFD β bypasses that compare strings
# Detect non-ASCII in a file
grep -P "[^\x00-\x7F]" file.txt
# Show Unicode info
python3 -c "import unicodedata; print(unicodedata.name('β¬'))"
# EURO SIGN
Typical multi-layer encodings found in CTFs:
1. Base64 β Hex β ROT13
Decode: ROT13 β hex decode β base64 decode
2. Hex β Base64 β URL encoding
Decode: URL decode β base64 decode β hex decode
3. Binary β Decimal β Hex β Base64
Decode: base64 β hex β decimal β binary
4. Base32 β Base64 β Reverse string
Decode: reverse β base64 β base32
# Detection hints:
Base64 Charset A-Za-z0-9+/= , length % 4 == 0
Base32 Charset A-Z2-7= , length % 8 == 0
Hex Charset 0-9a-fA-F, even length
Binary Only 0 and 1, groups of 8
Octal Only 0-7, groups of 3
URL Contains %XX patterns
HTML ent. Contains &# or &name;
Morse Contains . - / spaces
Decimal Space-separated numbers 0-127 (ASCII range)
Base85 Charset 0-9A-Za-z!#$%&()*+-;<=>?@^_`{|}~
# Quick decode chain (Python one-liner)
python3 -c "
import base64
s = 'VlhCaGJHbGtJVDA9' # double base64
s = base64.b64decode(s).decode() # first decode
s = base64.b64decode(s).decode() # second decode
print(s)
"
CyberChef: https://gchq.github.io/CyberChef/
Essential Operations (drag into Recipe):
ββββββββββββββββββββββββββββββββββββββββββββββββββββββ
From Base64 / To Base64 Standard base64
From Hex / To Hex Hex encode/decode
URL Decode / URL Encode Percent encoding
HTML Entity decode/encode Named and numeric entities
ROT13 Caesar shift 13
ROT47 Shifts printable ASCII
XOR XOR with key (brute force option)
AES Decrypt / AES Encrypt Symmetric crypto
From Binary / To Binary Binary strings
From Decimal / To Decimal Decimal values
From Morse Code Dots and dashes
Magic Auto-detect encoding (try this first!)
Entropy Measure randomness
Strings Extract printable strings
Gunzip / Gzip Compression
JWT Decode Parse JWT tokens
Parse X.509 certificate Examine SSL certs
Regular expression Grep/extract patterns
Find / Replace String manipulation
Fork / Merge Split input, process separately
Pro Tips:
- Use "Magic" operation first β it auto-detects encoding layers
- Chain operations: drag multiple into Recipe
- Use "Fork" to split on delimiter and process each piece
- Save recipes for reuse
- Breakpoint: pause recipe mid-chain to inspect
- Input can be file, text, or URL
# ββββββββ Base64 ββββββββ
echo -n "text" | base64 # Encode
echo "dGV4dA==" | base64 -d # Decode
openssl base64 -in file.bin # Encode file
openssl base64 -d -in file.b64 # Decode file
# ββββββββ Hex ββββββββ
echo -n "text" | xxd -p # Encode (plain hex)
echo "74657874" | xxd -r -p # Decode
echo -n "text" | od -A n -t x1 | tr -d ' \n' # Alternative encode
printf '\x74\x65\x78\x74' # Hex bytes to string
# ββββββββ URL Encoding ββββββββ
python3 -c "from urllib.parse import quote; print(quote('<script>'))"
python3 -c "from urllib.parse import unquote; print(unquote('%3Cscript%3E'))"
curl -s -o /dev/null -w "%{url_effective}" --get --data-urlencode "q=hello world" ""
# ββββββββ HTML Entities ββββββββ
python3 -c "import html; print(html.escape('<b>test</b>'))"
python3 -c "import html; print(html.unescape('<b>test</b>'))"
php -r 'echo htmlspecialchars_decode("<b>");'
# ββββββββ ROT13 ββββββββ
echo "text" | tr 'A-Za-z' 'N-ZA-Mn-za-m'
python3 -c "import codecs; print(codecs.encode('text','rot_13'))"
# ββββββββ Binary ββββββββ
echo -n "A" | xxd -b | awk '{print $2}' # Char to binary
echo "01000001" | perl -lpe '$_=pack"B*",$_' # Binary to char
python3 -c "print(bin(65))" # Decimal to binary: 0b1000001
python3 -c "print(int('1000001',2))" # Binary to decimal: 65
# ββββββββ Hash Generation ββββββββ
echo -n "password" | md5sum # MD5
echo -n "password" | sha1sum # SHA-1
echo -n "password" | sha256sum # SHA-256
echo -n "password" | sha512sum # SHA-512
openssl dgst -md5 file.bin # File hash
echo -n "password" | openssl dgst -sha256 -hmac "key" # HMAC
# ββββββββ XOR ββββββββ
python3 -c "
data = b'Hello'
key = b'K'
xored = bytes([b ^ key[0] for b in data])
print(xored.hex())
# Decode: XOR again with same key
print(bytes([b ^ key[0] for b in xored]).decode())
"
# ββββββββ String Conversions ββββββββ
echo -n "Hello" | rev # Reverse string
echo "SGVsbG8=" | base64 -d | rev # Decode then reverse
echo "48 65 6c 6c 6f" | tr -d ' ' | xxd -r -p # Spaced hex to string
# ββββββββ File Type Detection ββββββββ
file unknown_file # Detect file type
xxd unknown_file | head -5 # Check magic bytes
binwalk unknown_file # Find embedded files
Pattern Likely Encoding
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Ends with = or == Base64
Only A-Z, 2-7, = Base32
Only 0-9, a-f (even length) Hex
Only 0 and 1 (groups of 8) Binary
Contains %XX URL encoded
Contains & < &#xx; HTML entities
Starts with eyJ JWT (base64 of {"...)
Three dot-separated base64 chunks JWT
Looks readable but shifted ROT13 / Caesar
Has . - and spaces/slashes Morse code
Starts with PK ZIP archive (hex: 504B)
Starts with MZ Windows PE (hex: 4D5A)
Starts with \x89PNG PNG image
Starts with \xff\xd8\xff JPEG image
Starts with GIF8 GIF image
Starts with %PDF PDF document
Starts with \x1f\x8b Gzip compressed