 
  
    
    
    
 
  
What I Learned from Bandit Wargames - Level 0-12 (And Why You Should Try It)
Table of Contents
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)
- \ backslashescapes single characters
6. Tab Completion
Use Tab to autocomplete weird names:
- Type start of name → hit Tab
- If ambiguous: hit Tabtwice to list options
Pro Tip: Use
ls -bto 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. Adat the start means it’s a directory.
- Hard links: Usually 2for 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]
| Component | Purpose | 
|---|---|
| find . | Start search in current directory | 
| -type f | Only include files | 
| -size 33c | File is exactly 33 bytes (use +33cor-33cfor greater/less) | 
| ! -executable | File is not executable | 
| -exec file {} + | Describe file contents ( filecommand) | 
| 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
- fileis better than- catfor quickly checking what a file is.
- Use -inameto 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/nullwill come in handy - but what about this2>/dev/nullfun?
File Descriptors in Linux
In Unix-like systems, every process has three default file descriptors:
| FD | Name | Purpose | Symbol | 
|---|---|---|---|
| 0 | stdin | Standard input (e.g. keyboard) | < | 
| 1 | stdout | Standard output (e.g. screen) | > | 
| 2 | stderr | Standard error (error messages) | 2> | 
How to Use Them in Shell
| Goal | Command Example | 
|---|---|
| Redirect output to a file | echo hello > out.txt | 
| Append output to a file | echo again >> out.txt | 
| Redirect only errors | somecmd 2> errors.txt | 
| Redirect both output and errors | somecmd > all.txt 2>&1 | 
| Suppress error messages | somecmd 2>/dev/null | 
| Provide input from a file | somecmd < input.txt | 
Tip:
2>&1means “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
| Goal | Command Example | 
|---|---|
| Lines starting with “pass” | grep '^pass' data.txt | 
| Lines ending in “.txt” | grep '\.txt$' data.txt | 
| Lines containing digits | grep '[0-9]' data.txt | 
| Match “abc”, “def”, or “ghi” | grep -E 'abc | def | ghi' data.txt | 
| Word with exactly 5 letters | grep -E '\b[a-zA-Z]{5}\b' data.txt | 
| Lines that are only numbers | grep -E '^[0-9]+$' data.txt | 
Other Tips
- Case-insensitive search: grep -i 'pattern' data.txt
- Show line numbers: grep -n 'pattern' data.txt
- Count matches: grep -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- actionis 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:
| Variable | Meaning | 
|---|---|
| $0 | The entire line | 
| $1 | First word (field) | 
| $2 | Second word | 
| ... | And so on | 
| NF | Number of fields | 
Common Examples
Print entire file:
awk '{ print }' data.txt
Print the first column:
awk '{ print $1 }' data.txt
Print the third column only on lines containing “admin”:
awk '/admin/ { print $3 }' data.txt
Print lines with more than 5 words:
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
| Trick | Explanation | 
|---|---|
| -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 grep, cut, sed
  
  
    
 
  
| Tool | Best For | 
|---|---|
| grep | Matching simple patterns | 
| cut | Extracting fixed columns (by delimiter) | 
| sed | Stream edits, substitution | 
| awk | Pattern-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
file,grep -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 translate, squeeze, or delete characters. Great for quick text cleanup, lowercasing, or working with encoded messages.
🔧 Basic Syntax
tr [OPTIONS] SET1 [SET2]
| Option | Meaning | 
|---|---|
| -d | Delete characters in SET1 | 
| -s | Squeeze repeated characters | 
| -c | Complement: 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 base64,cut,awk, etc., in pipelines
- Use [:upper:],[:lower:],[:digit:]for portability
  When to Use tr
  
  
    
 
  
| Use Case | Why trWorks Well | 
|---|---|
| Cleanup of encoded strings | Strip padding, unwanted characters | 
| Format transformations | Spaces → underscores, case changes | 
| Lightweight replacements | No need for sedor 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 → n, b → o, …, n → a
  Apply ROT13 using tr
  
  
    
 
  
echo "uryyb jbeyq" | tr 'a-zA-Z' 'n-za-mN-ZA-M'
# Output: hello world
trmaps 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.