What I Learned from Bandit Wargames - Level 0-12 (And Why You Should Try It)

Learn practical Linux skills and command-line thinking through the first 12 levels of OverTheWire's Bandit wargame. Sharing lessons, strategies, and powerful command-line tools without spoiling solutions; perfect for aspiring ethical hackers, CTF players, and curious beginners.

Maybe you've already come across the Bandit Wargames from OverTheWire, an awesome, game-style approach to teaching linux and problem-solving thinking basics.

I'd greatly recommend that you try them out for yourself. Use Google but not ChatGPT, only if you already have an idea but are not making progress on how to execute it.

All war games are divided into levels, with Bandit being the "basics" to all other wargames. It consists of 34 levels, where you hop from container to container with ssh.

I won't spoiler solutions, just go over what i've learned, how to approach problems of similar styles and the essence of what they'll teach you too!

If you're not familiar with SSH and how to use it, a quick read will greatly help.


Starting Tips: referencing files

Let's say you want to use cat FILE to read out the next password. What if the filename's a bit special? Containing whitespaces, . or starting with - special?

Dealing with Tricky Filenames in Linux

1. Current Directory Executables

If the file isn’t in $PATH, run it with:

./filename

2. Filenames with Spaces

cat "file with spaces.txt"
# or
cat file\ with\ spaces.txt
Tab completion works: Type first few chars, hit Tab, shell autocompletes and escapes it:
cat file\ [Tab]

3. Filenames with Dashes (-)

Leading dashes are interpreted as options:

cat -- -filename
# or
./--script.sh

(-- tells the command: no more options)

4. Filenames with Dots (.)

No special handling needed:

cat file.name.txt
./script.sh

5. Quoting vs Escaping

  • "double quotes" preserve whitespace and allow variable expansion
  • 'single quotes' are literal (no expansion)
  • \ backslash escapes single characters

6. Tab Completion

Use Tab to autocomplete weird names:

  • Type start of name → hit Tab
  • If ambiguous: hit Tab twice to list options
Pro Tip: Use ls -b to show escape sequences (\) for non-printable or special characters.

Bash Basics - Always Worth a Revisit

No extended magic needed here, something as simple as

for file in *; do
  echo "Looking into $file"
  cat "$file"
done

can save you quite some time.

If you use such on foreign systems such as wargames, make sure to delete them after you finish!

Understanding Directory Content

Understanding ls and it's Options

ls -la: How often have you used that command without exactly knowing what it does?

You'll most likely know that ls serves to display directory content, but the options?

Read all about them if you want, for now let's use

  • l: long listing format (more details babyy)
  • a: Include hidden files (starting with a .)

Understanding the Output of ls -la

Run ls -la somewhere and you'll see something along the lines of

drwxr-x--- 2 root bandit5 4096 Jul 28 19:03 maybehere01
Now what does that all mean?

Linux File Permissions

This great RedHat article is really worth a read, i greatly recommend it.

  • Permissions: Indicate read (r), write (w), and execute (x) rights for user, group, and others. A d at the start means it's a directory.
  • Hard links: Usually 2 for directories (the directory itself and its internal . entry).
  • Ownership: Shows which user and group owns the directory.
  • Size: Typically 4096 bytes for an empty or nearly empty directory in Linux filesystems like ext4.
  • Modification timestamp: Reflects the last time contents were changed.
  • Name: The actual name of the file or directory.

Applying What We've Learned

With all that, we can tell what drwxr-x--- 2 root bandit5 4096 Jul 28 19:03 maybehere01 means:

We're dealing with the directory maybehere01, owned by bandit5 who has rwx permissions on the file, r-x writes for the user group of bandit5 and then no rights for all others (---). It is 4096 bytes and was last modified Jul 28 at 19:03.


Using find for Systematic File Searches in Linux

Sometimes you're looking for files with specific properties: size, readability, executability, or content type. Here's how to build powerful find one-liners to help you zero in.

Core Logic Pattern

find [STARTING-DIR] -type f [SIZE-FLAGS] [PERM-FLAGS] -exec file {} + | grep [CONTENT-TYPE]
ComponentPurpose
find .Start search in current directory
-type fOnly include files
-size 33cFile is exactly 33 bytes (use +33c or -33c for greater/less)
! -executableFile is not executable
-exec file {} +Describe file contents (file command)
grep 'ASCII text'Narrow to human-readable text

Practical One-Liners

1. Find all files of exactly 1033 bytes and not executable:

find . -type f -size 1033c ! -executable

2. Find human-readable (ASCII) files under 200 bytes:

find . -type f -size -200c -exec file {} + | grep 'ASCII text'

3. Find non-executable text files of any size:

find . -type f ! -executable -exec file {} + | grep 'ASCII text'

4. Find scripts (shell script) in current dir:

find . -type f -exec file {} + | grep 'shell script'

5. Combine with grep content search (e.g., contains "password"):

find . -type f -exec grep -l 'password' {} +

Tips

  • file is better than cat for quickly checking what a file is.
  • Use -iname to search for specific filename patterns, case-insensitively:
find . -type f -iname "*.txt"

Use -perm /111 to find files with any executable bit set (useful in CTFs):

find . -type f -perm /111

At some point, a command like find / -type f -user [USER] -group [GROUP] -size [SIZE]c 2>/dev/null will come in handy - but what about this 2>/dev/null fun?

File Descriptors in Linux

In Unix-like systems, every process has three default file descriptors:

FDNamePurposeSymbol
0stdinStandard input (e.g. keyboard)<
1stdoutStandard output (e.g. screen)>
2stderrStandard error (error messages)2>

How to Use Them in Shell

GoalCommand Example
Redirect output to a fileecho hello > out.txt
Append output to a fileecho again >> out.txt
Redirect only errorssomecmd 2> errors.txt
Redirect both output and errorssomecmd > all.txt 2>&1
Suppress error messagessomecmd 2>/dev/null
Provide input from a filesomecmd < input.txt
Tip: 2>&1 means “redirect stderr (2) to wherever stdout (1) is going.”

Searching a File with Regex

Basic Syntax

grep 'PATTERN' data.txt

Extended Regex

Use -E to enable extended regex (e.g., +|?()):

grep -E 'your-regex-pattern' data.txt

Example Patterns

GoalCommand Example
Lines starting with "pass"grep '^pass' data.txt
Lines ending in ".txt"grep '\.txt$' data.txt
Lines containing digitsgrep '[0-9]' data.txt
Match "abc", "def", or "ghi"`grep -E 'abc \def \ghi' data.txt`
Word with exactly 5 lettersgrep -E '\b[a-zA-Z]{5}\b' data.txt
Lines that are only numbersgrep -E '^[0-9]+$' data.txt

Other Tips

  • Case-insensitive searchgrep -i 'pattern' data.txt
  • Show line numbersgrep -n 'pattern' data.txt
  • Count matchesgrep -c 'pattern' data.txt
  • Invert match (show lines not matching): grep -v 'pattern' data.txt

Introducing awk

awk is a powerful text-processing language built right into most Unix systems. It's made for scanning files line by line, breaking them into fields (columns), and acting on patterns.

Whether you’re parsing logs, extracting passwords, or slicing structured data, awk is your lightweight weapon.

You can read more about it here.

Basic Syntax

awk options 'selection _criteria {action }' input-file > output-file
  • pattern: When this matches a line, the action is performed
  • action: Code block in {} (e.g., print $1)
  • file: Input file or stream

Field Structure

By default, awk splits each line into fields based on whitespace:

VariableMeaning
$0The entire line
$1First word (field)
$2Second word
...And so on
NFNumber of fields

Common Examples

awk '{ print }' data.txt
awk '{ print $1 }' data.txt
awk '/admin/ { print $3 }' data.txt
awk 'NF > 5' data.txt

Use Case: Find the Word After “millionth”

awk '{for (i=1;i<NF;i++) if ($i=="millionth") print $(i+1)}' data.txt
Loops through all fields; if a field is millionth, it prints the word after it.

Tips and Tricks

TrickExplanation
-F":"Change field delimiter to :
BEGIN {}Code to run before processing input
END {}Code to run after all input is read
awk '{ print $NF }'Print the last word in each line
awk '{print $(NF-1)}'Print second to last word
awk 'length($0) > 50'Print lines longer than 50 characters
awk '{count++} END {print count}'Count lines in a file

When to Use awk vs grepcutsed

ToolBest For
grepMatching simple patterns
cutExtracting fixed columns (by delimiter)
sedStream edits, substitution
awkPattern-based logic, field parsing, conditions, inline scripting

Think of awk as a lightweight scripting language for text. It’s one of the best tools to learn early, especially when you find yourself needing conditional parsing or data extraction without writing a full script.


Encoding and Decoding with base64

Sometimes you’ll find that a file looks like gibberish — a long string of letters, numbers, and slashes. That’s often base64 encoding, used to hide or safely transmit data.

What Is It?

Base64 is not encryption — just a way to encode binary data into readable text. It's easily reversible.

How to Use It

Decode base64 from a file:

base64 -d encoded.txt

Encode a file to base64:

base64 original.txt > encoded.txt

Decode a base64 string inline:

echo 'c2VjcmV0' | base64 -d
# Output: secret

Encode inline:

echo 'password123' | base64
Tip: Always double-check if a weird-looking string is base64: Use filegrep -E '^[A-Za-z0-9+/=]{10,}$', or just try decoding and see.

Translating and Cleaning Text with tr

The tr command is a small but powerful tool to translatesqueeze, or delete characters. Great for quick text cleanup, lowercasing, or working with encoded messages.

Basic Syntax

tr [OPTIONS] SET1 [SET2]
OptionMeaning
-dDelete characters in SET1
-sSqueeze repeated characters
-cComplement: use all except SET1

Useful Examples

1. Convert UPPERCASE to lowercase

echo "HELLO" | tr 'A-Z' 'a-z'

2. Lowercase to UPPERCASE

echo "bandit" | tr 'a-z' 'A-Z'

3. Remove all digits

echo "pass123word" | tr -d '0-9'

4. Replace spaces with underscores

echo "some file name" | tr ' ' '_'

5. Squeeze repeating characters

echo "aaaabbbcccc" | tr -s 'a-c'
# Output: abc

6. Keep only alphanumerics

cat file.txt | tr -cd '[:alnum:]\n'
This deletes everything except letters, numbers, and line breaks.

Pro Tips

  • Combine with base64cutawk, etc., in pipelines
  • Use [:upper:][:lower:][:digit:] for portability

When to Use tr

Use CaseWhy tr Works Well
Cleanup of encoded stringsStrip padding, unwanted characters
Format transformationsSpaces → underscores, case changes
Lightweight replacementsNo need for sed or scripting

ROT Ciphers with tr (e.g., ROT13)

ROT ciphers are simple substitution ciphers where each letter is rotated by n positions in the alphabet. ROT13 is the most common.

ROT13 example: a → nb → o, ..., n → a

Apply ROT13 using tr

echo "uryyb jbeyq" | tr 'a-zA-Z' 'n-za-mN-ZA-M'
# Output: hello world
tr maps a-z to n-z followed by a-m → neat and fast.

Test ROT13 interactively

echo "hello world" | tr 'a-z' 'n-za-m'
Repeating tr 'a-z' 'n-za-m' twice returns the original!

DIY ROT with other shifts

To ROT5 digits:

echo 12345 | tr '0-9' '5-90-4'
# Output: 67890

ROTX ≈ shift-X on the alphabet. But tr is static, so ROT7 etc. needs scripting or tools like python -c.


The Bandit war games are teaching me a lot about commands i didn't know before. I'm excited to see what part 2 will bring about in learnings! See you soon. Drink enough water and be kind.
Subscribe to my monthly newsletter

No spam, no sharing to third party. Only you and me.

Member discussion