ImHex Turns Mystery Bytes Into Structs

Stop squinting at hex dumps. ImHex's C-like pattern language paints fields directly onto the bytes as you describe them.

Share

Every team has a drawer with a .dat file in it. Ours came from a dead vendor's machine controller: no schema, no docs, nobody left to ask. The reflex is a Python REPL, struct.unpack, print, squint, repeat.

That loop is the problem. ImHex — its author just posted a new walkthrough of file format reverse engineering — inverts it: you describe the structure, and the editor paints each field onto the bytes as you type.

Why this matters

Undocumented binary formats find every developer eventually: legacy exports, firmware images, save files, sensor logs. Blind parsing isn't hard, it's slow — every hypothesis costs a write-run-print cycle. Interactive annotation collapses that cycle to keystrokes, and the description you end up with is documentation you can hand to the next person.

How it works

Open the file and let the built-in magic database tell you if it's a known format. Then check the entropy view: flat high entropy means compressed or encrypted, while periodic dips usually mark record boundaries. Select any bytes and the data inspector shows every plausible interpretation live.

The real weapon is the pattern language. It reads like C: structs, fixed arrays, and a placement operator that pins a struct to an offset. Fields you've already parsed become variables — read count from the header, then declare entries[header.count]. Edit the pattern and annotations update instantly. Big-endian? be_u32. And check the community pattern store first — PNG, ELF, SQLite and dozens more are already done.

Where this helps

  • Vendor exports with no schema. Map enough fields to write a real converter in whatever language your pipeline uses.
  • Firmware dumps. Entropy dips point at config and calibration tables; pattern one and read values instead of hex-squinting.
  • Save-file migrations. When the original developers are gone and users still need their data moved.
  • IR triage. Pull config tables out of suspicious samples in a sandbox without writing a throwaway parser.

Watch out

It's a DSL shaped like C, not C. Length-prefixed strings, bitfields, and conditional sections are supported but get fiddly — budget an afternoon for fluency. Encrypted or compressed regions defeat it until you decode them elsewhere. Multi-gigabyte files can lag, so carve a representative sample first. And know your legal position: analyzing a format for interop is usually fine, but shipping a product around someone's proprietary format can violate their terms.

Try it yourself

# build a tiny "unknown" format
printf 'STRK'                        >  save.dat
printf '\x01\x00'                    >> save.dat  # version (u16 LE)
printf '\x02\x00\x00\x00'            >> save.dat  # count   (u32 LE)
printf '\x2a\x00\x00\x00ITEM_01\x00' >> save.dat  # entry 1
printf '\x2b\x00\x00\x00ITEM_02\x00' >> save.dat  # entry 2

cat > pattern.hexpat <<'EOF'
struct Header {
    char magic[4];
    u16  version;
    u32  count;
} header @ 0x00;

struct Entry {
    u32  id;
    char name[8];
} entries[header.count] @ 0x0A;
EOF

imhex save.dat  # then load pattern.hexpat in the Patterns view

TL;DR

  • What: ImHex's pattern language annotates raw bytes live from a C-like struct description — the pattern file doubles as format documentation.
  • Why: Undocumented binaries stop being guess-and-check; iteration drops from code-run-print to typing.
  • Try: Run the snippet, load the pattern, then point it at a mystery file you've been avoiding.