Filesystem Recon & Text Extraction

Build a Linux recon lab on Windows and extract secrets using 15 core commands.

Introduction

30 Second Summary

Every file on a computer has a hiding spot. Security operators find those spots faster than anyone else because they have internalized the commands that reveal what others miss.

In this project, you will build a personal Linux recon training lab on your Windows machine, plant secrets throughout it, then systematically hunt and decode every one using core command-line tools. By the end, you will connect to a live capture-the-flag server and solve its first challenge from memory.

What You'll Build

You will type a single pipeline command in your terminal that cracks a multi-layered encoded secret, then SSH into BreachLab Ghost and solve Level 0 without opening any documentation.

By the end of this project, you'll have:

  • A working WSL Ubuntu environment where you plant secrets in hidden files, oddly-named files, and deep directory structures, then extract them all using shell commands without hesitation.
  • The ability to decode base64, reverse hex dumps, and crack ROT13 ciphers from the terminal in seconds.
  • A text-filtering pipeline you could type from memory that finds one unique line buried in a 1000-line file.
  • Secret Mission: Build and crack a triple-layered encoded payload with a single pipeline command.

Are there any prerequisites?

You need Windows 10 version 2004 or higher, or Windows 11. No prior Linux experience is required.

This project is the first in the BreachLab Prep series. It builds the command-line foundation you need to tackle Ghost Levels 0 through 11 and prepares you for networking and permissions work in later projects.

Before We Start

Before any hands-on work, let's establish what you're building and why it matters for your BreachLab progression. Clarity on the mission keeps every drill in the next steps purposeful.

Set Up WSL and Your Training Lab

BreachLab runs on Linux. Every command you will drill in this project works identically on the Ghost box. To practice locally with unlimited repetitions, you need a real Linux environment on your Windows machine.

WSL (Windows Subsystem for Linux) gives you a full Ubuntu terminal inside Windows with zero VM overhead and instant startup. In this step, you install it, verify your shell, and create the training lab folder where all your recon challenges will live.

In this step, get ready to:
  • Install WSL with Ubuntu on your Windows machine.
  • Update Ubuntu and confirm your shell environment.
  • Create the recon-lab training directory.
Install WSL with Ubuntu

WSL lets you run a full Linux distribution directly on Windows. The install command handles everything in one shot: enabling the required Windows features, downloading the Linux kernel, and installing Ubuntu.

  • Press the Windows key to open your search bar.
  • Type PowerShell and look for Windows PowerShell in the results.
  • Right-click Windows PowerShell and select Run as administrator.
  • If a User Account Control prompt appears, click Yes to allow it.
  • Install WSL and Ubuntu by running this command in the administrator PowerShell window:
wsl --install

What does this command do?

This single command enables the WSL and Virtual Machine Platform components, downloads and installs the latest Linux kernel, sets WSL 2 as the default, and downloads the Ubuntu distribution.

Your machine will need to restart to finish the installation. The command will tell you when a reboot is required.

  • When the command finishes, restart your computer as prompted.

✔️ I see it downloading and installing

The command is downloading Ubuntu and enabling Windows features. Once it finishes and tells you to restart, go ahead and reboot. After your restart, continue with the next instruction below.

ⓧ I see help text instead of an install

This means WSL is already partially installed on your system. Run this command instead:

wsl --install -d Ubuntu

If the install gets stuck at 0%, try this alternative:

wsl --update --web-download

Then run wsl --install -d Ubuntu again. Restart your computer once it completes.

After your computer restarts, Ubuntu will finish setting up. You need to launch it and create your Linux user account.

  • Press the Windows key to open your search bar.
  • Type Ubuntu and press Enter to launch it.
  • Ubuntu will open a terminal window and spend a moment unpacking files. Wait for it to ask you to create a username.
  • Type a lowercase username (like your first name) and press Enter.
  • Type a password and press Enter. Then type it again to confirm.

Why can't I see my password as I type?

Linux hides password input completely. Nothing appears on screen while you type. This is called blind typing and it is normal. Just type your password carefully and press Enter.

Once you confirm your password, you will see a command prompt ending in $. You are now inside Ubuntu.

Update the system and verify your shell

A fresh Ubuntu install needs its package lists updated. This ensures you have access to the latest software versions when you install tools later.

  • Update and upgrade all system packages by running this command:
sudo apt update && sudo apt upgrade -y

What does this command do?

The sudo prefix runs the command as an administrator. apt update refreshes the list of available packages. apt upgrade -y installs all available updates, with -y automatically confirming each one.

First time using sudo

Ubuntu will ask for the password you just created. Type it (blind typing again) and press Enter. It will not ask again for a few minutes.

The update may take a minute. Once it finishes and you see your $ prompt again, verify your shell environment.

  • Confirm you are running bash by running:
echo $SHELL

You should see /bin/bash printed.

  • Check your username by running:
whoami

This prints the username you created during setup.

  • Check your current directory by running:
pwd

You should see /home/yourname (where yourname is the username you just created). This is your home directory in Linux.

Seeing something unexpected?

  • If echo $SHELL does not print /bin/bash, you may have a different default shell. This is rare with a fresh Ubuntu install. Close the terminal and relaunch Ubuntu from the Start Menu.
  • If pwd shows /root instead of /home/yourname, you are logged in as root. Close the terminal and relaunch Ubuntu. It should log you in as your created user automatically.

help me troubleshoot my WSL Ubuntu shell setup

Create the training lab directory

Every file you create in this project lives inside a single folder called recon-lab. This keeps your practice environment contained and easy to find.

  • Create the training lab folder by running:
mkdir -p ~/recon-lab
  • Move into that folder by running:
cd ~/recon-lab
  • Verify your location by running:
pwd

You should see /home/yourname/recon-lab printed. This confirms the directory exists and you are inside it.

What does mkdir -p mean?

The mkdir command creates a directory. The -p flag tells it to create parent directories if needed and to not error if the directory already exists. The ~ symbol is a shortcut for your home directory.

Before you run the final verification, what do you expect to see when you ask Ubuntu for its distribution information?

  • Confirm your Ubuntu installation is working by running:
lsb_release -a

You should see output that includes Distributor ID: Ubuntu along with a version number and codename. This confirms you have a working Ubuntu environment on Windows.

Command not found for lsb_release?

  • If you see a command not found message, the package may not be pre-installed on your version. Run cat /etc/os-release instead. You should still see Ubuntu and a version number in the output.

help me verify my WSL Ubuntu installation

Your Linux environment is alive and your training lab folder is ready. Next up, you will fill that folder with hidden files, encoded secrets, and tricky filenames designed to teach you exactly how Ghost hides its challenges.

Build Your Target Environment

In the last step, you created an empty ~/recon-lab directory. Now you fill it with challenges that mirror exactly what BreachLab Ghost uses to hide secrets.

By building these challenges yourself, you understand WHY ls misses hidden files, WHY spaces in filenames break naive commands, and WHY file matters more than extensions. You cannot be fooled by something you built with your own hands.

In this step, get ready to:
  • Create tricky files that test shell quoting and hidden-file knowledge.
  • Create text processing challenges that require grep, sort, uniq, and strings to crack.
  • Create encoding challenges using base64, hex, and ROT13, then save everything as a reusable script.
Create tricky files that test shell quoting

Ghost hides secrets in files that naive commands cannot reach. Dotfiles are invisible to plain ls. Spaces in filenames break unquoted commands. A leading dash makes a filename look like a flag to most tools.

  • Create four files that each exploit a different shell trap by running these commands:
# A dotfile - invisible to plain ls
echo "FLAG{first_contact}" > ~/recon-lab/.hidden-secret

# Spaces in the filename - breaks unquoted commands
echo "FLAG{spaces_matter}" > ~/recon-lab/"spaces in this name"

# Leading dash - looks like a flag to most commands
echo "FLAG{dash_trap}" > ~/recon-lab/-secret

# Another dotfile for discovery practice
echo "FLAG{deep_find}" > ~/recon-lab/.buried

What do these commands do?

Each echo command writes a secret flag into a file designed to trip up careless operators.

  • The > redirects output into a new file. If the file exists, it overwrites it.
  • Dotfiles (.hidden-secret) start with a period. Linux hides them from directory listings by default.
  • Quotes around "spaces in this name" tell the shell to treat the whole string as one filename, not three separate words.
  • Now try listing the directory without any flags by running:
ls ~/recon-lab/

You should see only spaces in this name in the output. The hidden dotfiles and the dash-prefixed file are missing.

  • Run the same command with the -la flags to reveal everything:
ls -la ~/recon-lab/

Now you see all four files plus . and .. (current and parent directory entries).

Why does -la show more files?

The -a flag means "show ALL files including hidden ones." The -l flag means "long format" showing permissions, owner, size, and modification date.

Without -a, any file starting with a dot is invisible. This is exactly how Ghost hides passwords in early levels.

Only seeing . and .. in the listing?

Make sure you ran the four echo commands above without typos. Re-run them and check that the path ~/recon-lab/ is correct.

help me figure out why my files are not appearing in ls -la

Create text processing challenges

Ghost Levels 7-9 test your ability to extract signal from noise. You need a massive file with one unique line buried inside, a binary file with hidden text, and a log file with one critical entry among hundreds.

  • Generate a 1000-line file with one unique flag hidden inside by running these commands:
# Create 999 lines of repeating noise patterns
> ~/recon-lab/data.txt
for i in $(seq 1 999); do
    echo "noise_line_$((RANDOM % 50))" >> ~/recon-lab/data.txt
done

# Add one unique flag line then shuffle everything randomly
echo "FLAG{unique_signal}" >> ~/recon-lab/data.txt
shuf -o ~/recon-lab/data.txt ~/recon-lab/data.txt

What does this create?

The for loop creates 999 lines that repeat about 50 different patterns. Then one unique flag line gets appended. The shuf -o command shuffles all 1000 lines into random order so the flag is buried at an unpredictable position.

Finding it will require sort and uniq working together. You will practice that in Step 4.

  • Verify the file has 1000 lines by running:
wc -l ~/recon-lab/data.txt

You should see 1000 printed before the filename.

  • Create a binary file with an embedded secret and a server log with a buried critical line by running these commands:
# Hide text inside binary noise
echo "FLAG{binary_extraction}" | cat - /usr/bin/yes > ~/recon-lab/mystery.bin 2>/dev/null

# Create a 500-line log with one CRITICAL flag line buried inside
> ~/recon-lab/server.log
for i in $(seq 1 500); do
    echo "[$(date -d "-$i hours" 2>/dev/null || date)] INFO: routine check $i" >> ~/recon-lab/server.log
done
echo "[CRITICAL] FLAG{grep_master}" >> ~/recon-lab/server.log
shuf -o ~/recon-lab/server.log ~/recon-lab/server.log

What do these files test?

The mystery.bin file concatenates your flag with the raw bytes of /usr/bin/yes. The cat command cannot read it, but the strings command can pull readable text from binary data.

The server.log buries one critical line among 500 routine entries. Finding it requires grep pattern matching.

  • Verify both files exist by running:
ls -la ~/recon-lab/mystery.bin ~/recon-lab/server.log

You should see both files listed with their sizes. The mystery.bin file will be noticeably larger because it contains binary data from /usr/bin/yes.

Seeing an error about /usr/bin/yes?

Some Ubuntu installations may have yes in a different location. Run which yes to find the correct path and replace /usr/bin/yes in the command above.

help me create mystery.bin when /usr/bin/yes is not found

Create encoding challenges and save your lab script

Ghost Levels 10-11 test encoding. Attackers encode payloads to evade detection. You will plant secrets encoded in base64, hex dumps, and ROT13 ciphers.

  • Create the encoding challenges and a deep directory tree by running these commands:
# Base64-encoded secret
echo "FLAG{base64_decoded}" | base64 > ~/recon-lab/encoded.b64

# Hex dump of a secret
echo "FLAG{hex_reversed}" | xxd > ~/recon-lab/hexdump.txt

# ROT13 cipher (shifts letters 13 positions)
echo "FLAG{rot13_cracked}" | tr 'A-Za-z' 'N-ZA-Mn-za-m' > ~/recon-lab/rotated.txt

# Deep directory tree with a buried password file
mkdir -p ~/recon-lab/level1/level2/level3/level4
echo "FLAG{deep_discovery}" > ~/recon-lab/level1/level2/level3/level4/.password

What is each encoding?

  • base64 converts binary data into text-safe characters (A-Z, a-z, 0-9, +, /). It makes data 33% larger but safe for email and URLs.
  • xxd shows raw bytes as hex pairs. Each byte becomes two hex characters (like 46 4c 41 47 for "FLAG").
  • tr 'A-Za-z' 'N-ZA-Mn-za-m' is ROT13. It shifts every letter 13 positions in the alphabet. Apply it twice and you get back the original.
  • Before you verify, predict: how many total items will ls -la ~/recon-lab/ show? Count your tricky files, text challenges, encoding files, plus . and .. and the level1 directory.
  • Verify your full lab by running:
ls -la ~/recon-lab/

You should see at least 8 items including hidden dotfiles, the file with spaces, the -secret file, your text processing files, encoding files, and the level1 directory.

Missing some files?

If your count is lower than expected, re-run the commands from the substep that created the missing files. Each echo > command is idempotent, so running it again overwrites safely.

help me find which lab files are missing from ~/recon-lab

Now save all your setup commands as a reusable script. If you ever need to rebuild this lab from scratch, you can run the script instead of typing every command again.

  • Create the first half of your lab script by running this command:
cat > ~/recon-lab/setup_lab.sh << 'EOF'
#!/bin/bash
# BreachLab Prep 1: Recon Lab Setup Script
# Run this script to create your training environment
# Usage: chmod +x setup_lab.sh && ./setup_lab.sh

set -e

LAB_DIR="$HOME/recon-lab"

echo "[*] Creating recon lab at $LAB_DIR..."
mkdir -p "$LAB_DIR"

# === TRICKY FILES (shell quoting challenges) ===
echo "FLAG{first_contact}" > "$LAB_DIR/.hidden-secret"
echo "FLAG{spaces_matter}" > "$LAB_DIR/spaces in this name"
echo "FLAG{dash_trap}" > "$LAB_DIR/-secret"
echo "FLAG{deep_find}" > "$LAB_DIR/.buried"
EOF
  • Add the text processing, encoding, and output sections by running this command:
cat >> ~/recon-lab/setup_lab.sh << 'EOF'

# === TEXT PROCESSING CHALLENGES ===
# 1000-line file with one unique line
> "$LAB_DIR/data.txt"
for i in $(seq 1 999); do
    echo "noise_line_$((RANDOM % 50))" >> "$LAB_DIR/data.txt"
done
echo "FLAG{unique_signal}" >> "$LAB_DIR/data.txt"
shuf -o "$LAB_DIR/data.txt" "$LAB_DIR/data.txt"

# Binary file with embedded secret
echo "FLAG{binary_extraction}" | cat - /usr/bin/yes > "$LAB_DIR/mystery.bin" 2>/dev/null || true

# Server log with buried critical line
> "$LAB_DIR/server.log"
for i in $(seq 1 500); do
    echo "[2026-07-31 10:$((RANDOM % 60)):$((RANDOM % 60))] INFO: routine check $i" >> "$LAB_DIR/server.log"
done
echo "[2026-07-31 23:59:59] [CRITICAL] FLAG{grep_master}" >> "$LAB_DIR/server.log"
shuf -o "$LAB_DIR/server.log" "$LAB_DIR/server.log"
EOF
  • Append the final section with encoding challenges and the output messages:
cat >> ~/recon-lab/setup_lab.sh << 'EOF'

# === ENCODING CHALLENGES ===
echo "FLAG{base64_decoded}" | base64 > "$LAB_DIR/encoded.b64"
echo "FLAG{hex_reversed}" | xxd > "$LAB_DIR/hexdump.txt"
echo "FLAG{rot13_cracked}" | tr 'A-Za-z' 'N-ZA-Mn-za-m' > "$LAB_DIR/rotated.txt"

# === DEEP DIRECTORY TREE ===
mkdir -p "$LAB_DIR/level1/level2/level3/level4"
echo "FLAG{deep_discovery}" > "$LAB_DIR/level1/level2/level3/level4/.password"

echo ""
echo "[+] Recon lab created successfully!"
echo "[+] Files created:"
find "$LAB_DIR" -type f | wc -l
echo "[+] Start hunting from: cd $LAB_DIR"
echo ""
echo "=== YOUR MISSION ==="
echo "Find and extract every FLAG{...} hidden in this lab."
echo "Commands you will need: ls, cat, file, find, grep, strings,"
echo "sort, uniq, base64, xxd, tr, head, tail"
echo ""
EOF
  • Make the script executable and test it by running:
chmod +x ~/recon-lab/setup_lab.sh
~/recon-lab/setup_lab.sh

You should see output starting with [*] Creating recon lab followed by a file count and the mission summary. The script recreated all your lab files from scratch.

Why save a script?

If you ever need to rebuild this lab (after cleanup, on a different machine, or to reset for another practice round), you run one command instead of typing dozens. This is the operator mindset: automate everything you repeat.

Permission denied when running the script?

Make sure you ran chmod +x before executing. Without it, Linux will not allow the file to run as a program.

help me fix permission denied when running setup_lab.sh

✔️ Awesome, I've got everything!

Great. Make sure you have saved setup_lab.sh in ~/recon-lab/ and that the script ran without errors.

ⓧ I'd like to double check the full code

Your setup_lab.sh was built from three chunks above. Scroll up and confirm each chunk is present in order:

  • Chunk 1: The shebang header, set -e, LAB_DIR variable, and the tricky files section (.hidden-secret, spaces in this name, -secret, .buried).
  • Chunk 2: Text processing challenges (data.txt for loop, mystery.bin, server.log for loop).
  • Chunk 3: Encoding challenges (encoded.b64, hexdump.txt, rotated.txt), deep directory tree, and the echo output messages at the end.

You can verify the script has the correct number of lines by running:

wc -l ~/recon-lab/setup_lab.sh

You should see approximately 55-60 lines.

Your target environment is loaded with secrets. Next up, you hunt through it as if you have never seen these files before.

Hunt - File Discovery and Navigation

You built the target environment in the last step. Now you hunt through it as if you have never seen it before.

This is the operator pattern: land on a box, find secrets, extract them. The catch is that naive commands will fail. Plain ls misses hidden files. Unquoted filenames break. You will hit those failures, understand why, and fix them.

In this step, get ready to:
  • Practice ls -la vs plain ls to reveal hidden files.
  • Use find to locate files buried deep in directory trees.
  • Master quoting patterns for filenames with spaces and leading dashes.
Practice basic navigation and the "three reads" (ls, cat, file)

Every recon engagement starts with three commands: ls to see what exists, cat to read contents, and file to check what something actually is. You will drill these until they are automatic.

  • See what plain ls shows you by running:
ls ~/recon-lab/

You should see files like data.txt, mystery.bin, and server.log. But count them. Several secrets are missing from this list.

  • Now reveal everything (including hidden files) by running:
ls -la ~/recon-lab/

You should now see at least 8 items including .hidden-secret, .buried, -secret, and spaces in this name. The -a flag shows ALL files including dotfiles. The -l flag shows permissions and metadata.

Why are dotfiles hidden?

Any file starting with a dot (.) is invisible to plain ls. This is a convention from early Unix. Configuration files like .bashrc use it to stay out of the way. Attackers use it to hide payloads.

  • Read the hidden secret by running:
cat ~/recon-lab/.hidden-secret

You should see FLAG{first_contact} printed to your terminal.

  • Read the file with spaces in its name by running:
cat ~/recon-lab/"spaces in this name"

You should see FLAG{spaces_matter}. The quotes wrap the entire filename so the shell treats the spaces as part of the name, not as argument separators.

  • Now try reading the dash-prefixed file naively by running:
cat ~/recon-lab/-secret

Your terminal hangs. Nothing prints. The cat command interprets -secret as a set of flags (-s, -e, -c...) and falls back to reading from stdin.

  • Press Ctrl+C to escape the hang.
  • Read the file correctly using the double-dash signal by running:
cat -- ~/recon-lab/-secret

You should see FLAG{dash_trap}. The -- tells cat "no more flags, everything after this is a filename."

What does the file command do?

The file command reads the actual bytes of a file to determine its type. It ignores the extension entirely. A file named photo.jpg might actually be an executable. Only file tells you the truth.

  • Check the types of everything in your lab by running:
file ~/recon-lab/*

You should see each file identified. Notice that mystery.bin shows as "data" (binary), not "ASCII text". This confirms you need a different tool to extract its contents.

  • Drill the file command on the binary specifically by running:
file ~/recon-lab/mystery.bin

The output confirms it is binary data. You will extract its secret using strings in the next step.

Seeing "No such file or directory"?

Make sure you are typing the path exactly as shown, including the tilde (~) which expands to your home directory. If the lab files are missing entirely, re-run ~/recon-lab/setup_lab.sh to regenerate them.

Why can't I read my lab files?

Use find to locate files by properties

The find command searches recursively through directory trees. Unlike ls, it digs into every subdirectory automatically. This is the tool that solves Ghost Levels 5 and 6.

  • Find all hidden files (dotfiles) in your lab by running:
find ~/recon-lab -name ".*" -type f

You should see paths to .hidden-secret, .buried, and the deeply buried .password. The -name ".*" matches dot-prefixed names. The -type f restricts results to regular files only.

  • Find files larger than 1KB by running:
find ~/recon-lab -type f -size +1k

This surfaces the larger files like data.txt, server.log, and mystery.bin. Useful when you know a target is large but do not know where it lives.

  • Find the deeply buried password file by running:
find ~/recon-lab -name ".password"

You should see /home/yourname/recon-lab/level1/level2/level3/level4/.password. The find command digs four directories deep automatically. No manual cd required.

Now imagine you land on an unfamiliar system and need to find a password file somewhere. You would search from the root (/) to check everywhere.

  • Try searching the entire filesystem for .password by running:
find / -name ".password" -type f

Your terminal is flooded with "Permission denied" errors. The actual result is buried somewhere in that wall of noise. This is unusable.

Why does this happen?

When you search from /, find tries to enter every directory on the system. Most system directories block non-root users, producing one error per blocked directory.

The fix is to redirect error output (stream 2) to /dev/null, a special file that discards anything sent to it. This silences the errors while keeping the real results.

  • Run the same search with error suppression by running:
find / -name ".password" -type f 2>/dev/null

Now you see only the clean result: the path to your .password file with zero noise. The 2>/dev/null pattern is one you will use on every real engagement.

  • Combine find with an action to find all hidden files AND print their contents in one command by running:
find ~/recon-lab -name ".*" -type f -exec cat {} \;

Every hidden file's contents are printed one after another. You should see FLAG{first_contact}, FLAG{deep_find}, and FLAG{deep_discovery} in the output.

What does -exec do?

The -exec flag runs a command on each file that find discovers. The {} is a placeholder for the current filename. The \; marks the end of the command to execute. Together: "for each match, run cat on it."

Practice the quoting patterns until automatic

You have seen each quoting pattern once. Once is not enough. You need to create more tricky files on the fly and read them without hesitation.

  • Create three more tricky files to practice on by running these commands one at a time:
echo "test" > ~/recon-lab/"--help"
echo "test2" > ~/recon-lab/"-rf"
echo "test3" > ~/recon-lab/.super-hidden
  • Confirm the new files exist by running:
ls -la ~/recon-lab/

You should see --help, -rf, and .super-hidden in the listing alongside all your original lab files.

Now practice reading each one. The rules are: spaces need quotes, leading dashes need -- before the filename, and dotfiles need -a to find but read normally with cat.

  • Read the --help file (its name looks like a flag to most commands) by running:
cat -- ~/recon-lab/"--help"

You should see test. Without the --, cat would print its own help text instead of the file contents.

  • Read the -rf file by running:
cat -- ~/recon-lab/"-rf"

You should see test2. Same pattern: -- disarms the leading dash.

  • Read the hidden drill file by running:
cat ~/recon-lab/.super-hidden

You should see test3. Dotfiles need ls -a to discover, but once you know the name, cat reads them with no special handling.

The quoting cheat sheet

  • Spaces in filename: wrap in quotes (cat "file with spaces") or escape with backslash (cat file\ with\ spaces).
  • Leading dash: use -- before the filename (cat -- -secret) or prefix with ./ (cat ./-secret).
  • Dotfiles: visible with ls -a, read normally with cat .filename.

Getting cat's help text instead of file contents?

If you see usage information printed instead of your file's contents, you forgot the -- before the filename. The shell is interpreting the filename as command flags. Add -- between cat and the dash-prefixed filename.

Help me read files with weird names in Linux.

Before you run the final verification, predict: how many hidden or buried files do you think find will discover when searching for dotfiles and the .password file?

  • Verify your discovery skills by running:
find ~/recon-lab -name "FLAG*" -o -name ".hidden*" -o -name ".password" -o -name ".buried" | wc -l

You should see a count of at least 4. This confirms your find command can locate hidden and buried files across the entire lab structure.

What does this verification prove?

The -o flag means "or" in find. This command searches for files matching any of four patterns, then pipes the results to wc -l which counts the lines. A count of 4 or more means you have successfully located files that plain ls would never show you.

You can now find anything hidden on a filesystem. Next up, you will extract the signal from noisy files using text processing pipelines.

Extract - Text Processing Pipelines

You can now find any file on the system regardless of how it is hidden. That is step one of the operator pattern.

Step two is extracting the signal from noise. Your server.log has 501 lines, your data.txt has 1000 lines, and your mystery.bin is raw binary. You need tools that filter, sort, and extract the one line that matters.

In this step, get ready to:
  • Search files for patterns using grep with multiple flags.
  • Extract the one unique line from a 1000-line file using sort, uniq, and piping.
  • Pull readable secrets out of binary data using strings.
Search files with grep

grep is the single most-used command in security work. It searches file contents for a pattern and prints every line that matches. Ghost Levels 7 through 10 all require some form of grep.

  • Search your server log for the FLAG by running this command:
grep "FLAG" ~/recon-lab/server.log

You should see the single CRITICAL line containing FLAG{grep_master} printed to your terminal. One line from 501 found instantly.

  • Try a case-insensitive search by running:
grep -i "critical" ~/recon-lab/server.log

The -i flag matches CRITICAL, Critical, and critical. Same line found regardless of case.

  • Search every file in every subdirectory recursively by running:
grep -r "FLAG" ~/recon-lab/

You should see multiple lines printed, each showing a filename and the matching content. Every FLAG you planted across the entire lab appears in one shot.

What do these flags do?

Each grep flag adds a capability. -i ignores case. -r searches recursively into subdirectories.

You can combine flags too. -ri gives you recursive case-insensitive search in one go.

  • Now try the invert match flag to see lines that do NOT contain a pattern:
grep -v "noise" ~/recon-lab/data.txt | head -20

The -v flag inverts the match. This shows only lines that do NOT contain "noise". The | head -20 part pipes the output into head to limit what you see to the first 20 lines.

  • See context around a match by running:
grep -C 2 "FLAG" ~/recon-lab/server.log

The -C 2 flag shows 2 lines before and 2 lines after the match. This gives you context around the finding.

Drill your grep variations

Knowing the flags is not enough. You need to run them until your fingers do not hesitate. Try these three variations one after another.

  • List only filenames containing FLAG (not their contents) by running:
grep -rl "FLAG" ~/recon-lab/

You should see a list of file paths with no content shown. The -l flag prints filenames only.

  • Count how many matches exist per file by running:
grep -rc "FLAG" ~/recon-lab/

Each line shows a filename followed by a colon and the number of matches. Files with 0 matches appear too, confirming they hold no flags.

Seeing no output from grep?

Check that you are searching in ~/recon-lab/ not just ~/recon-lab (trailing slash ensures grep treats it as a directory path). Also confirm you are using double quotes around the pattern. Single quotes work too, but mixing them with special characters can cause issues.

Why aren't my grep commands returning results?

Chain commands with sort, uniq, head, and tail

The pipe (|) sends one command's output into the next command's input. This is how you chain multiple tools into a single pipeline. Sort, filter, count, and extract in one line.

Your data.txt has 1000 lines. 999 of them are duplicated noise. One is unique. Ghost Level 8 tests exactly this pattern.

  • Extract the one unique line from the 1000-line file by running:
sort ~/recon-lab/data.txt | uniq -u

You should see exactly one line printed: FLAG{unique_signal}. That is the only line in the entire file that does not repeat.

Why does sort come before uniq?

uniq only detects ADJACENT duplicates. If two identical lines are separated by other lines, uniq misses them.

sort groups identical lines together first. Then uniq -u can reliably find the one line that appears only once. Without sort first, this pipeline would miss duplicates scattered throughout the file.

  • View the first 5 lines of your server log by running:
head -5 ~/recon-lab/server.log
  • View the last 5 lines by running:
tail -5 ~/recon-lab/server.log

head and tail let you peek at just the beginning or end of a file. Use -n 1 to grab just a single line.

  • Count the total number of lines in your data file by running:
wc -l ~/recon-lab/data.txt

You should see 1000 printed. That confirms the file size you expected.

  • Count how many FLAG lines exist in the data file by running:
grep "FLAG" ~/recon-lab/data.txt | wc -l

You should see 1. One flag line among a thousand.

  • Now chain all three concepts into one pipeline by running:
grep -v "noise" ~/recon-lab/data.txt | sort | uniq -u

This three-command pipeline filters out noise, sorts the remainder, and finds the unique line. Same result, different approach. You now have two ways to extract the signal.

What does this pipeline do?

  • grep -v "noise" removes every line containing "noise" from the output.
  • | sort takes the remaining lines and sorts them alphabetically.
  • | uniq -u prints only lines that appear exactly once.

Each pipe hands the previous command's output to the next command's input. No temporary files needed.

Extract readable text from binary files with strings

Binary files contain data that is mostly unreadable by humans. But attackers (and defenders) often embed passwords, URLs, and keys inside compiled programs or binary payloads. The strings command pulls out every human-readable sequence from binary data.

  • Extract all readable text from your binary file by running:
strings ~/recon-lab/mystery.bin

You should see a wall of short text fragments. Somewhere in that output is your flag, buried among junk strings extracted from the binary noise.

  • Filter the output to show only the flag by piping into grep:
strings ~/recon-lab/mystery.bin | grep "FLAG"

You should see FLAG{binary_extraction} printed cleanly. Two commands, one pipe, secret found.

  • Reduce junk output by setting a minimum string length of 8 characters:
strings -n 8 ~/recon-lab/mystery.bin

The -n 8 flag only shows strings 8 or more characters long. This filters out short junk fragments and leaves meaningful content.

How does strings work?

strings ignores all non-printable bytes and only outputs sequences of 4 or more printable characters by default. This is how you find passwords, URLs, and keys embedded in compiled programs.

It works on any file type. You can run it against executables, disk images, memory dumps, or unknown blobs. If there is readable text inside, strings will find it.

  • Now practice on a real system binary to see what is hidden inside by running:
strings /usr/bin/ls | head -20

You should see text fragments from inside the actual ls binary. Library names, format strings, and internal labels.

  • Search for usage text embedded in the ls binary by running:
strings /usr/bin/ls | grep -i "usage"

You should see the usage string that ls prints when you run it incorrectly. That text lives inside the compiled binary, and strings pulled it out.

Seeing "No such file" for /usr/bin/ls?

Some WSL distributions place ls at a different path. Run which ls to find where it actually lives on your system, then substitute that path.

Help me find where ls is located on my WSL system.

Verify your extraction skills

Time to prove these commands are locked in. Before you run the next command, predict what you think the output will be.

  • Think about this: when you sort 1000 lines where 999 are duplicates and 1 is unique, what will uniq -u print? How many lines of output do you expect?
  • Confirm your prediction by running:
sort ~/recon-lab/data.txt | uniq -u

You should see exactly one line printed: FLAG{unique_signal}. If you predicted that, your understanding of the sort-uniq pipeline is solid.

Seeing more than one line of output?

If you see multiple lines, your data.txt may have been modified by earlier experiments. Regenerate it by running the setup script again: cd ~/recon-lab && bash ~/recon-lab/setup_lab.sh (if you saved it there) or re-run the creation commands from Step 2.

Help me figure out why sort | uniq -u is showing multiple lines.

You can now grep patterns from logs, extract unique lines from massive files, and pull secrets from binary data. Next up, you will decode encoded payloads and connect to the live BreachLab Ghost box to prove these skills work in the real environment.

Decode - Encoding and BreachLab Connection

You can find files and extract the signal from noise. The last major skill category Ghost tests is encoding.

Attackers encode payloads to slip past detection filters. Base64, hex dumps, and ROT13 are the three encodings you will see constantly in security work. Ghost Levels 10 and 11 test exactly these. In this step, you decode them all from your lab files, drill round-trip encoding, then connect to the live BreachLab Ghost box and prove the skills work in a real environment.

In this step, get ready to:
  • Decode base64 and hex-encoded secrets from your lab files.
  • Crack ROT13 ciphers using character translation with tr.
  • SSH into BreachLab Ghost and solve Level 0 without documentation.
Decode base64 and hex secrets

Your lab has two encoded files waiting to be cracked. The encoded.b64 file holds a secret wrapped in base64. The hexdump.txt file holds a secret as a hex dump.

  • Decode the base64 file by running this command:
base64 -d ~/recon-lab/encoded.b64

You should see FLAG{base64_decoded} printed to the terminal.

What does base64 -d do?

The -d flag means decode. Without it, base64 encodes. Base64 converts binary data into text-safe characters (A-Z, a-z, 0-9, +, /). It makes data 33% larger but safe for transmission in emails and URLs.

  • Now reverse the hex dump by running:
xxd -r ~/recon-lab/hexdump.txt

You should see FLAG{hex_reversed} printed to the terminal.

What does xxd -r do?

The xxd command shows raw bytes as hex pairs. The -r flag reverses the hex dump back to the original bytes. Think of it as undoing the translation from binary to hex-readable format.

  • Drill the round-trip for base64 by running:
echo "my_password" | base64

You see the encoded version. Now pipe it through a decode to get the original back:

  • Prove the round-trip works by running:
echo "my_password" | base64 | base64 -d

You should see my_password printed back. Encode, then decode, gives you the original.

  • Do the same round-trip drill with xxd by running:
echo "test" | xxd | xxd -r

You should see test printed back. The pattern is the same: encode forward, reverse backward.

Seeing extra characters or no output?

If base64 -d prints nothing, check that encoded.b64 exists with ls ~/recon-lab/encoded.b64. If xxd -r gives garbled output, confirm the file is a proper hex dump with cat ~/recon-lab/hexdump.txt first.

Still stuck? Help me troubleshoot my base64 or xxd decode

Crack ROT13 with the tr command

ROT13 shifts every letter 13 positions through the alphabet. Since the alphabet has 26 letters, applying ROT13 twice returns the original. The tr command translates characters one-to-one between two sets.

  • Decode the ROT13 file by running:
cat ~/recon-lab/rotated.txt | tr 'N-ZA-Mn-za-m' 'A-Za-z'

You should see FLAG{rot13_cracked} printed to the terminal.

How does tr work here?

The tr command takes two character sets. Every character from set one gets replaced by the character at the same position in set two. For ROT13, the first set is the alphabet shifted by 13 (N-ZA-M) and the second set is the normal alphabet (A-Za-z). This maps each shifted letter back to its original position.

  • Practice other tr patterns. Convert lowercase to uppercase by running:
echo "hello" | tr 'a-z' 'A-Z'

You should see HELLO printed.

  • Delete all digits from a string by running:
echo "hello 123" | tr -d '0-9'

You should see hello with the numbers stripped out.

  • Now drill ROT13 encryption. Encrypt a message by running:
echo "attack at dawn" | tr 'A-Za-z' 'N-ZA-Mn-za-m'
  • Decrypt it by running the same output through the reverse:
echo "attack at dawn" | tr 'A-Za-z' 'N-ZA-Mn-za-m' | tr 'N-ZA-Mn-za-m' 'A-Za-z'

You get attack at dawn back. Do this three times with different messages until the tr 'A-Za-z' 'N-ZA-Mn-za-m' pattern is in your fingers.

ROT13 output looks the same as input?

If your decode prints the same encoded text, check that the two character sets in tr are in the correct order. To decode, the first set must be N-ZA-Mn-za-m and the second set must be A-Za-z. Swapping them encodes instead of decoding.

Need more help? Help me debug my tr command for ROT13

Connect to BreachLab Ghost and prove your skills

Every command you drilled in this project works identically on the BreachLab Ghost box. Time to prove it. You will SSH into Ghost Level 0 and solve it without opening any documentation.

Before you run the connection command, think: what is the first thing you will do once you land on the remote machine? What commands will you reach for?

  • Connect to BreachLab Ghost Level 0 by running:
ssh ghost0@204.168.229.209 -p 2222

What happens when you run this?

SSH connects you to a remote Linux machine over the network. You will be prompted for a password. Type ghost0 and press Enter. Nothing appears on screen while you type the password. This is normal Linux behaviour for password entry.

  • When prompted for the password, type ghost0 and press Enter.
  • Read the brief that appears. Solve Level 0 using only the commands you drilled in this project. Do not open any documentation or look anything up.

How does Ghost progression work?

Each Ghost level hides a flag somewhere on the machine. That flag is the SSH password for the next level. Flags are case-sensitive with surrounding whitespace trimmed.

  • After solving Level 0, disconnect from the Ghost box by running:
exit

You are back in your local WSL terminal.

  • Now reconnect and solve it again faster. Run the SSH command a second time:
ssh ghost0@204.168.229.209 -p 2222

The goal is not "can I solve it" but "can I solve it without thinking." Repeat until the solve feels automatic.

Connection refused or timed out?

If you see a connection error, check that you are running the command from your WSL Ubuntu terminal (not PowerShell). Make sure you included -p 2222 at the end. The Ghost server runs on port 2222, not the default SSH port.

If the password is rejected, make sure you are typing ghost0 exactly (lowercase, no spaces). Remember that Linux does not show any characters while you type a password.

Still stuck? Help me connect to BreachLab Ghost via SSH

Secret mission

Triple-Layer Payload Extraction

Ghost Level 11 tests multi-layer extraction. Real-world attackers wrap payloads in multiple encoding layers to evade detection. Can you build a triple-encoded payload and crack it with a single pipeline command?

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely locally inside WSL, so there are no ongoing cloud costs or subscription charges. Decide whether to keep your resources running, pause them to come back later, or delete them entirely.

Resources you used:

  • WSL Ubuntu distribution (your Linux environment on Windows).
  • ~/recon-lab directory and all files inside it (hidden files, encoded payloads, binary challenges, deep directory tree).
  • setup_lab.sh script.

Keep everything running

No action needed. Choose this if you are still actively building or plan to continue with BreachLab Prep 2.

  • Your WSL Ubuntu distribution stays installed and ready to launch from the Start Menu.
  • Your ~/recon-lab directory stays intact for continued drill practice.
  • You can re-run setup_lab.sh at any time to regenerate the lab from scratch.

Pause - I'll come back to this later

Shut down WSL to free up memory. Your files and configuration remain on disk for when you return.

  • Open PowerShell on Windows and run the following command to shut down all WSL instances:
  • Your files inside ~/recon-lab will still be there the next time you launch Ubuntu.
wsl --shutdown

When you are ready to resume, launch Ubuntu from the Start Menu and run cd ~/recon-lab to pick up where you left off.

Delete - I don't want to use this again

Remove all project resources and start fresh. This permanently deletes your lab files and optionally removes WSL Ubuntu entirely.

  • Delete the recon lab directory. Open Ubuntu and run:
  • Confirm the directory is gone by running ls ~/recon-lab. You should see a "No such file or directory" message.
rm -rf ~/recon-lab

If you also want to remove WSL Ubuntu entirely from your system, open PowerShell (not Ubuntu) and run:

wsl --unregister Ubuntu

This is permanent

Running wsl --unregister Ubuntu permanently deletes the entire Ubuntu distribution, including all data, settings, and software you installed inside it.

Only do this if you are certain you do not need WSL Ubuntu for any other projects. You can always reinstall later with wsl --install in an administrator PowerShell window.

Nice Work!

Nice Work!

You just built a Linux recon training lab from scratch and hunted through it like an operator. Every command you drilled is now muscle memory, ready for BreachLab Ghost and beyond.

Here's what you accomplished:

  • Installed WSL Ubuntu on Windows and built a recon training lab packed with hidden files, tricky filenames, encoded secrets, and binary payloads.
  • Internalized 15 core Linux commands through repeated drill-based practice, chaining them into pipelines with piping and redirection to extract signals from noise.
  • Connected to BreachLab Ghost and solved Level 0 without opening any documentation.
  • Secret Mission: cracked a triple-layer encoded payload with a single pipeline command.

Ready to quiz yourself?