Single-Byte XOR: Decoding Hex and Reversing a One-Byte Key
The challenge
A small CTF binary stores its flag as a hex string and XORs it with one fixed byte at startup. You dumped the hex below and the byte 0x2a (the '*' character). Decode the hex, XOR it back, and submit the flag (HDNA{...}).
What you'll learn
- Recognise an all-hex string as a hex transport layer
- Decode hex to raw bytes before applying a byte-level operation
- Reverse a single-byte XOR with a known key byte
- Understand that XOR is its own inverse
- Explain why single-byte XOR has only 256 keys and protects nothing
Skills tested
Prerequisites
- Comfort reading hex
- Understanding that XOR is its own inverse
How it works
This is the smallest layered-decode there is: a flag stored as a hex string and XORed with a single byte. Hex is just a text way to write bytes - two hex characters per byte - so the first job is to turn the printable hex back into the raw bytes it represents. Those bytes are still unreadable because they were XOR-scrambled with one fixed byte.
XOR is symmetric: applying the same byte to the data a second time cancels the first, because A XOR B XOR B = A. So you XOR every byte with the key and the plaintext returns. Here the key is 0x2a, the ASCII * character. A single-byte XOR has only 256 possible keys, which is why it offers no security at all - an analyst can try every one in an instant and keep the result that reads as text.
In the workbench, add From Hex, then XOR with the key 0x2a (or the character *), and the flag resolves live in the output. The other operations (base64, ROT, atbash, reverse, Vigenere, URL-decode) are decoys - base64 is the closest trap, but the input is not valid base64, so it cannot apply.
Common mistakes
- Trying base64 instead of hex. The input is all hex characters with no padding - decode it as hex, not base64.
- XOR-ing the hex text directly. Decode the hex to bytes first, then XOR those bytes.
- Mistyping the key. 0x2a is the '*' character - enter the byte the workbench expects.
- Assuming a longer key. It is a single byte; a multi-character key will not decode it.
How to defend against it
For defenders and reverse engineers, the lesson is that single-byte XOR over hex is the floor of obfuscation - it should be the first thing you try when triaging a small binary, and it should never guard anything that matters. If your own code 'protects' a value this way, treat the value as plaintext.
- Brute-force all 256 single-byte XOR keys against short hex or byte blobs during triage.
- Decode hex and base64 wrappers automatically before scanning the underlying bytes.
- Never store real secrets as hex plus a static XOR byte - use authenticated encryption with a managed key.
- Keep flags and secrets out of the binary entirely when the threat model requires it.