HackBlue

Tools · Forensics tools · 19 / 25

CyberChef: decode with a key the case already recovered

When a note, a config, or a memory string already holds the key, XOR and similar operations are just another recipe step. The check is whether the output is the format you expected.

16 min read · practice only with authorization

The key has to already be an exhibit

Some files in a case are scrambled with a short repeating key that also sits in the case: a config next to the blob, a command-line argument, a string from the same process in memory. XOR in CyberChef takes that known key and applies it. This is the same shape as From Base64. You are reversing a transform you can name, with material you already collected. You are not searching a space of keys, and you are not recovering a password from a hash. Those are different jobs, and they are not this lesson.

Write the key’s source next to the recipe. “ASCII key northline-lab, taken from config.json in the same Temp directory, SHA-256 of the config recorded in the manifest.” A key you typed from memory is a guess. A key copied from an exhibit is a step. If the config and the blob came from different hosts, say that too. The recipe does not know they belong together. You decided they do, and the note should show the decision.

Apply it once, then look at the structure

A repeating XOR key is applied from the start of the slice. If you include a header that was not encrypted, the output shifts into nonsense. Slice to the field the note describes. Bake once. The output should match a format you predicted: JSON, a URL, a path. The lab blob in this lesson is the hex 154d1a1b1b184b5447491e0e12400313164609110f085d00044013, and the key from the fictional config is northline-lab. XOR yields {"host":"drop.lab.example"}. That is a check you can see. A pile of punctuation means the key, the slice, or the operation is wrong. Stop and re-read the exhibit.

ROT13 and similar fixed alphabets are the same idea with a key that is the alphabet itself. They appear in casual obfuscation of text you already have. Apply the operation once. If the result is the hostname you already saw in netscan, you have corroborated the text. If it is a different story, keep both the input and the output and do not quietly prefer the dramatic one.

Snippet
Key exhibit: northline-lab
Input hex: 154d1a1b1b184b5447491e0e12400313164609110f085d00044013
Operation: XOR
Check: {"host":"drop.lab.example"}

A failed check ends the chain

If the output is not the format you predicted, the chain stops. You do not flip the key, try a second key from an unrelated case, or run a brute-force operation across a range. A failed check is a logged negative: “XOR with the config key did not yield JSON; blob left as hex in the export.” The blob stays evidence. It does not become a mandate to keep transforming until it looks like a URL.

Partial readability is a trap. English-looking fragments show up in random bytes. Require the check you wrote down before you baked, not a check you invent after you see the output. Changing the success criterion after the fact is how a wrong key survives into the report.

Cite the key and the output as a pair

The report sentence names both exhibits. “XOR of temp-blob.bin with the ASCII key in config.json produced a JSON object whose host field is drop.lab.example, consistent with the netscan address’s name.” The consistency is allowed because the hostname and the earlier address are the same lab pair. You still do not claim the JSON was transmitted. You claim the file decodes to that object with that key.

Store the key file’s hash. If the key is short text, store the text and the path. Future you will not remember which config you meant, and a second XOR with a different “northline” string will not reproduce the JSON. The recipe file locks the key in as a parameter. Save it.

Worked case: the config key and the host field

Autopsy already extracted Temp\config.json, and one field is the ASCII string northline-lab. Beside it, temp-blob.bin is 27 bytes of binary. You XOR the blob with that key in a local CyberChef. The output is the JSON object naming drop.lab.example. The check matches the destination name you saw next to 203.0.113.44 in the memory note. You save input, key path, recipe, and output.

You do not try a second key. You do not run a search over key lengths. The log line says the config key worked and the output is the host object. The workbook contents are not inside this blob. You leave them in the hashed xlsx exhibits.

Diagram

From a key you already have to a checked output

  1. Key exhibit

    Point at the config, the command line, or the memory string that contains the key. Hash or path it.

  2. Slice

    Feed XOR only the bytes that were transformed. Leave headers and hashes out of the slice.

  3. Check

    Compare the output to the format you named beforehand. JSON with the known host is a pass.

  4. Stop

    A pass is saved as a triple. A fail is a logged negative. You do not search for a different key.

    Pass on the lab blob
    XOR key: northline-lab
    Output: {"host":"drop.lab.example"}
    Consistent with the name used for 203.0.113.44

Check yourself

1. XOR with the key from config.json produces punctuation that is not the JSON you predicted. What belongs in the case log?