> ## Content Index
> Fetch the complete content index at: https://niklas-heringer.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# What I Learned from Bandit Wargames - Level 0-12 (And Why You Should Try It)
- URL: https://niklas-heringer.com/skills-lab/learnings-from-bandit-wargames-01/
- Published: 2025-07-27T22:00:00.000Z
- Updated: 2025-11-16T18:54:14.000Z
- Description: 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.
- Author: Niklas Heringer
- Tags: wargames, overthewire, bandit, skills-lab, bash-scripting, awk, grep, regex

Maybe you've already come across the [Bandit Wargames](https://overthewire.org/wargames/bandit/?ref=niklas-heringer.com) 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](https://www.digitalocean.com/community/tutorials/how-to-use-ssh-to-connect-to-a-remote-server?ref=niklas-heringer.com) 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:

```bash
./filename

```

### 2\. Filenames with **Spaces**

```bash
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:

```bash
cat file\ [Tab]

```

### 3\. Filenames with **Dashes (-)**

Leading dashes are interpreted as options:

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

```

(`--` tells the command: no more options)

### 4\. Filenames with **Dots (.)**

No special handling needed:

```bash
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

```bash
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](https://www.w3schools.com/bash/bash%5Fls.php?ref=niklas-heringer.com) 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

```bash
drwxr-x--- 2 root bandit5 4096 Jul 28 19:03 maybehere01

```

> Now what does that **all mean?**

---

# Linux File Permissions

This [great RedHat article](https://www.redhat.com/en/blog/linux-file-permissions-explained?ref=niklas-heringer.com) 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

```bash
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 +33c or \-33c for greater/less) |
| ! -executable     | File 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:

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

```

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

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

```

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

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

```

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

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

```

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

```bash
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:

```bash
find . -type f -iname "*.txt"

```

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

```bash
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*:

| 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>&1` means “redirect stderr (2) to wherever stdout (1) is going.”

---

# Searching a File with Regex

## Basic Syntax

```bash
grep 'PATTERN' data.txt

```

## Extended Regex

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

```bash
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](https://www.geeksforgeeks.org/linux-unix/awk-command-unixlinux-examples/?ref=niklas-heringer.com).

## Basic Syntax

```bash
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:

| 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:

```bash
awk '{ print }' data.txt

```

### Print the first column:

```bash
awk '{ print $1 }' data.txt

```

### Print the third column only on lines containing "admin":

```bash
awk '/admin/ { print $3 }' data.txt

```

### Print lines with more than 5 words:

```bash
awk 'NF > 5' data.txt

```

### Use Case: Find the Word After “millionth”

```bash
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:

```bash
base64 -d encoded.txt

```

### Encode a file to base64:

```bash
base64 original.txt > encoded.txt

```

### Decode a base64 string inline:

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

```

### Encode inline:

```bash
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

```bash
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

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

```

### 2\. Lowercase to UPPERCASE

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

```

### 3\. Remove all digits

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

```

### 4\. Replace spaces with underscores

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

```

### 5\. Squeeze repeating characters

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

```

### 6\. Keep only alphanumerics

```bash
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 tr Works Well                  |
| -------------------------- | ---------------------------------- |
| Cleanup of encoded strings | Strip padding, unwanted characters |
| Format transformations     | Spaces → underscores, case changes |
| Lightweight replacements   | No 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` → `n`, `b` → `o`, ..., `n` → `a`

### Apply ROT13 using `tr`

```bash
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

```bash
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:

```bash
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.