~$ skillshelf
← OverTheWire Bandit

Bandit 9 → 10: readable text in a binary file

banditlinuxshell

First level where the file isn’t meant to be read at all. Two filters, one after the other: pull out the parts that are text, then keep the ones that are marked.

the goal

The password for the next level is stored in the file data.txt in one of the few human-readable strings, preceded by several = characters.

the approach

bandit9@bandit:~$ ls
data.txt
bandit9@bandit:~$ cat data.txt

Garbage. The file is mostly binary, so cat throws a screenful of nonsense at the terminal and beeps at you. But the objective says there is readable text in there, and that it’s marked — several = characters sit in front of it.

strings is the tool for the first half. It walks a file and prints any run of printable characters long enough to look like text, ignoring everything else. So the job is: run that, then keep only the lines with the = marker. I had the AI write the loop:

bandit9@bandit:~$ strings data.txt | while read -r line; do
>   case "$line" in
>     *=*) echo "$line" ;;
>   esac
> done

That printed a handful of lines rather than one. Several of them had = signs in them and only one was the password — it was obvious which, because the others were fragments and it was a clean 32-character string.

My filter was loose and I knew it while writing it. “Contains an =” is a much weaker test than “starts with several = then a run of letters and digits”, and tightening it would have printed exactly one line instead of making me pick.

the takeaway

strings is how you look inside a file that isn’t text. Binaries, memory dumps, disk images, a file you can’t identify — strings pulls the human-readable runs out and throws the rest away. It’s the first thing to reach for when cat gives you garbage.

The pipe version of what I looped:

bandit9@bandit:~$ strings data.txt | grep '='

Same result, one line. And the tighter filter I should have written:

bandit9@bandit:~$ strings data.txt | grep -E '^=+[A-Za-z0-9]+$'

^=+ — starts with one or more =. [A-Za-z0-9]+$ — then letters and digits to the end of the line, nothing else. That describes the thing I was actually looking for instead of describing something it happens to contain, which is the whole difference between a filter that narrows and a filter that nearly narrows.