Reading a hexdump
Every file is just a row of bytes. A hexdump prints them in a form a human can scan. Once you can read one fluently, file formats, network captures and memory dumps stop being opaque. This post walks through one 16-byte example line by line.
Tip: every page on this site has a Hex View tab (press x) and a Strings tab (press s). Try them on this post as you read.
One line of a hexdump
This is a 16-byte file, printed with hexdump -C sample.bin (on Linux, xxd sample.bin or od -A x -t x1z sample.bin show the same thing):
00000000 48 69 21 0a 01 02 ff 00 34 12 00 00 ef be ad de |Hi!.....4.......|It has three columns:
- Offset (
00000000): where in the file this line starts, in hex. The next line would start at00000010, which is 16. - Bytes: sixteen bytes, each as two hex digits. One hex digit is 4 bits, so two digits are exactly one byte (0 to 255, written
00toff). The extra gap after the eighth byte is only there to help your eyes. - ASCII: the same bytes shown as text. Printable characters appear as themselves, everything else as a dot.
Text is just numbers
The first three bytes are 48 69 21. In ASCII, 0x48 is H, 0x69 is i, and 0x21 is !. That's why the ASCII column starts with Hi!. The fourth byte, 0a, is a newline. It isn't printable, so it shows as a dot.
A few values are worth memorising, because you'll see them everywhere:
20space,0anewline,0dcarriage return (Windows line endings are0d 0a)30to39are the digits0to941to5aareAtoZ, and61to7aareatoz; lower case is upper case plus0x2000is the NUL byte: C strings end with it, and long runs of it are usually padding
Numbers wider than one byte
Look at bytes 8 to 11: 34 12 00 00. If a program stored a 32-bit integer there, what is its value?
On x86 and most ARM systems, multi-byte numbers are stored little-endian: the least significant byte comes first. To read the number, reverse the bytes: 00 00 12 34, which is 0x1234 = 4660.
The last four bytes, ef be ad de, work the same way. Reversed, they read de ad be ef: 0xDEADBEEF, a classic marker value that programmers use precisely because it's easy to spot in a dump.
Big-endian is the other order: most significant byte first, the way we write numbers. Network protocols use it ("network byte order"), so the same value can appear in both orders within one capture.
Exercise
Go back to the line above and answer, without a calculator:
- Which byte is the NUL that ends the first "string"?
- If bytes 4 and 5 (
01 02) were a 16-bit little-endian number, what would it be? - Why does
ffshow as a dot?
Answers: the 00 at offset 7; 0x0201 = 513; and 0xff is above 0x7e, outside printable ASCII.
Tools
xxd fileorhexdump -C file: dump a filexxd -l 64 file: only the first 64 bytesxxd -s 0x100 -l 32 file: 32 bytes starting at offset0x100xxd -r: turn an edited dump back into a binary, a cheap way to patch a byte
Next: the ELF header, byte by byte, where this skill pays off immediately.