You Cracked the WiFi Password – Now What?

A beginner’s guide to network reconnaissance after gaining WiFi access to the ctf-lab wifi network!


Engage: Celebrate Your First Win

You did it. You captured that WPA2 handshake, ran it through your wordlist, and now you’re connected to the target network. Maybe you brute forced the password. Maybe you social engineered it! That rush you’re feeling? That’s the satisfaction of your first real hack.

But here’s the thing: cracking the WiFi password was just picking the lock on the front door. You’re standing in the lobby now. The real exploration begins here.

So what’s next?


Explore: Understanding Your Position

Before you start poking around, you need to understand where you are on this network. Your device just received some critical information when it connected.

Find Your IP Address

Your IP address is your identity on this network. Find it:

  • iPhone/iPad: Settings → Wi-Fi → tap the network name → look for “IP Address”
  • Android: Settings → Network & Internet → Wi-Fi → tap the gear icon → IP address
  • Mac: System Preferences → Network → Wi-Fi → look for IP Address
  • Windows: Open Command Prompt, type ipconfig
  • Linux: Open terminal, type ip addr or hostname -I

You’ll see something like 192.168.4.47. Write this down.

Find the Default Gateway

The default gateway is even more interesting. This is the network’s router – the device that controls traffic flow and often hosts services. It’s typically the first target worth investigating.

Find it in the same location as your IP address. On this network, it’s likely 192.168.4.1.

Why does this matter? The gateway is almost always running something. Web interfaces. Admin panels. Sometimes vulnerable services that were never meant to be exposed.


Explain: What Can You Do With This Information?

You now know two things:

  1. Your address on the network (your IP)
  2. The “center” of the network (the gateway)

But networks aren’t just two devices. There could be servers, other users, printers, IoT devices, cameras – all potential targets. How do you find them?

Network scanning.

A network scanner sends packets to IP addresses and ports, listening for responses. When something responds, you’ve discovered a live host. When you probe its ports, you discover what services it’s running.

Think of it like this: your IP tells you what apartment building you’re in. Scanning tells you which apartments have their lights on and what’s happening inside.

The Scan Strategy

  1. Host discovery – Find all live devices on the network (typically 192.168.4.1-254)
  2. Port scanning – For each live host, discover which ports are open
  3. Service identification – Determine what’s running on those ports

Common ports to watch for:

  • 22 – SSH (remote shell access)
  • 80/443 – Web servers
  • 21 – FTP (file transfer)
  • 3306 – MySQL database
  • 5000-5002 – Often custom web applications

Elaborate: Tools for Network Discovery

Mobile Apps (Great for Learning)

iOS:

  • Fing – Excellent free network scanner, shows all devices and open ports
  • iNet – Network scanner with port detection
  • Network Analyzer – Comprehensive tool with ping, traceroute, and port scanning

Android:

  • Fing – Same great tool, available on Android
  • Net Analyzer – Free network discovery and diagnostics
  • PortDroid – Dedicated port scanner

Command Line (More Powerful)

Nmap is the gold standard. Install it on any laptop:

# Discover all hosts on the network
nmap -sn 192.168.4.0/24

# Scan common ports on the gateway
nmap 192.168.4.1

# Aggressive scan with service detection
nmap -sV -sC 192.168.4.1

Netcat for quick port checks:

nc -zv 192.168.4.1 80
nc -zv 192.168.4.1 22

Evaluate: Your Reconnaissance Checklist

Before moving to exploitation, confirm you’ve gathered:

  • [ ] Your assigned IP address
  • [ ] The default gateway IP
  • [ ] List of all live hosts on the network
  • [ ] Open ports on each discovered host
  • [ ] Services identified on interesting ports
  • [ ] Any web interfaces found (try opening IPs in your browser!)

Pro tip: Open your browser and navigate directly to the gateway IP. Then try adding port numbers: http://192.168.4.1:5000http://192.168.4.1:5002. Web applications often hide on non-standard ports.


What’s Next?

You’ve mapped the terrain. You know what’s out there. Now the real challenges begin:

  • Can you find hidden web pages?
  • Are there login forms you can test?
  • What happens if you try default credentials?
  • Are there services running that shouldn’t be exposed?

Every open port is a potential entry point. Every web form is a potential vulnerability.

Your reconnaissance is complete. Time to start probing.


Remember: Only practice these techniques on networks you own or have explicit permission to test. Happy hacking.

Preview: WifiCTF Participant Docs- Level 2:

Reconnaissance – The Art of Seeing What’s Hidden

Security Domain: Network Reconnaissance & Service Discovery 

Learner Level: Beginner 

Estimated Time: 30-45 minutes 

Prerequisites: Basic networking concepts (IP addresses, ports), command-line comfort


What You’ll Learn (The Concepts)

In concrete terms, you’ll understand:

  • Network reconnaissance – What it means to gather information without exploitation
  • Service enumeration – How systems advertise what they’re running (often unintentionally)
  • Port scanning mechanics – The difference between “listening” and “attacking”
  • The reconnaissance mindset – Why attackers spend 80% of their time just looking

Why This Matters (The Stakes)

Real-world impact: In the 2017 Equifax breach, attackers spent weeks mapping internal systems before exploiting a single vulnerability. The reconnaissance phase revealed what was vulnerable and where the valuable data lived. The actual exploitation took minutes—the reconnaissance took weeks.

When reconnaissance is possible, attackers learn:

  • What services are running (and their versions, which have known vulnerabilities)
  • What the network topology looks like (where to go next)
  • What’s supposed to be hidden but isn’t (security through obscurity failures)

The Story Arc

You’ve successfully connected to the CTF_LAB WiFi network. You’re now “inside the perimeter”—but what’s here?

In this level, you’re playing the role of an initial access operator who needs to map the terrain before attempting any exploitation. By the end, you’ll understand why security professionals say: “Attackers don’t need to exploit everything—they just need to find the one thing you forgot to lock down.”


🧠 Conceptual Foundation: The Metaphor

What Reconnaissance Really Is

The Core Metaphor:

“Network reconnaissance is like being a detective casing a building before a heist—but with one critical difference: the building is actively telling you where all the doors and windows are if you just know how to ask.”

In a physical building:

  • You walk the perimeter, noting doors, windows, cameras, guards
  • You look for open windows, unlocked doors, or hiding spots
  • You try door handles gently to see if they’re locked (without actually entering)
  • You note patterns: “The back door is always propped open at 2pm”
  • The building doesn’t tell you what’s inside—you have to observe

In network reconnaissance:

  • You “walk the network” by scanning IP addresses
  • You “try door handles” by sending packets to ports to see if services respond
  • Open ports are like unlocked doors—something is actively listening there
  • Services often identify themselves (“Hi, I’m SSH version 2.0!”)—like a door with a sign saying “Break Room – No Lock”
  • You’re not breaking in yet—you’re just cataloging what’s available

Why the analogy matters:

Most beginners think hacking is about “breaking through walls”—brute force, password cracking, sophisticated exploits. In reality, 80% of security compromises start with reconnaissance that reveals a system that was never meant to be accessible but is.

The metaphor breaks down when: Unlike physical buildings that don’t actively respond, network services announce themselves when probed. A door doesn’t shout “I’m unlocked!” when you walk by—but an HTTP server on port 8000 literally sends back “HTTP/1.1 200 OK” when you knock. This is both a feature (for legitimate users) and a security risk (for attackers).

Mental Models: What Might Mislead You

Misconception 1: “Port scanning is hacking/attacking a system”

  • Why it’s tempting: It feels aggressive. You’re probing something. Surely that’s an attack?
  • Why it’s wrong: Port scanning is like checking if a store is open by looking through the window. The system is designed to respond to connection attempts. You’re not exploiting a vulnerability—you’re just asking “Is anyone listening here?” The system chooses to answer.
  • Correction: Reconnaissance is passive information gathering. You’re observing what the system willingly tells you. Exploitation (which comes later) is when you abuse that information to make the system do something it shouldn’t.
  • Legal nuance: While technically not an “attack,” unauthorized port scanning can be illegal in some jurisdictions because it’s interpreted as “attempted unauthorized access.” Always get permission. In this CTF, you have permission.

Misconception 2: “Services on non-standard ports are hidden”

  • Why it’s tempting: If port 80 is for HTTP and something is running on port 8000, it must be “hidden” right? The developer must have intended it to be secret.
  • Why it’s wrong: Ports are just numbers. There’s nothing technically hidden about port 8000 vs. port 80. The service is listening publicly—it will respond to anyone who asks. “Security through obscurity” (hiding things in non-standard places) fails the moment someone does thorough enumeration.
  • Correction: Think of ports as doors in a hallway numbered 1-65535. Just because you usually enter through door 80 doesn’t mean door 8000 is locked. It’s just a different entrance. Any listening service is discoverable with thorough scanning.

Misconception 3: “If I can’t see it in a browser, it’s not there”

  • Why it’s tempting: Browsers are how we experience the web. If I go to 192.168.4.1 and see a page, that’s what exists, right?
  • Why it’s wrong: A web browser makes assumptions about what you want (typically port 80 for HTTP, port 443 for HTTPS). But systems run dozens of services on different ports: SSH (22), database servers (3306), streaming servers (8000), etc. Your browser isn’t looking for those—but they’re still there.
  • CorrectionWeb browsers are opinionated clients that only show you HTTP/HTTPS on standard ports by default. To see the full attack surface, you need tools that systematically check all possible doors (ports 1-65535). That’s where tools like nmap come in.

📖 The Case: A Real-World Scenario

Context & Setup

The System: You’ve gained access to CTF_LAB, a WiFi network for a fictional “Secure Research Facility.” According to the welcome portal (192.168.4.1:80), the network hosts:

  • A registration system (publicly advertised)
  • A scoreboard dashboard (publicly advertised)
  • Backend infrastructure (not mentioned)

The Vulnerability: The network administrators assumed participants would only access the advertised services. They didn’t consider that running additional services on other ports makes them discoverable.

The Stakes: One of those “background services” is an Icecast streaming server on port 8000 running chiptune music—an easter egg. In a real scenario, this could be an unsecured admin panel, a debug endpoint, or a legacy service the team forgot about.

Your Role: You’re a penetration tester contracted to assess the network’s attack surface. Your job isn’t to exploit vulnerabilities yet—just to enumerate what exists. The defenders will be surprised by what you find.


🔍 The Reconnaissance Process: Seeing What’s Really There

Challenge 1: Service Enumeration (50 pts)

The Mission

Objective: Identify all publicly accessible services running on 192.168.4.1

What you’re testing: Whether the network administrators are aware of everything they’re running

Expected discovery:

  • Port 22: SSH (secure shell – remote access)
  • Port 80: HTTP (registration portal)
  • Port 5000: HTTP (vulnerable Flask application)
  • Port 8000: Icecast (streaming server – THE SURPRISE)
  • Port 8080: HTTP (dashboard)

The Detective Work

What we’re doing and why:

# Run service version detection scan
nmap -sV 192.168.4.1

Breaking down this command:

  • nmap: Network Mapper – the industry-standard reconnaissance tool
  • -sV: “Service Version detection” – not just “is port open?” but “what’s running there?”
  • 192.168.4.1: The target IP

What’s actually happening (TCP three-way handshake):

When nmap scans a port, it’s performing a “knock and listen” operation:

  1. SYN packet sent: “Hello, is anyone listening on port 80?”
  2. SYN-ACK received: “Yes! I’m here! Let’s establish a connection.”
  3. RST packet sent: “Actually, never mind.” (nmap politely closes the connection)

The service volunteered that information. You didn’t exploit anything—you just asked.

Why services identify themselves:

When you connect to port 5000, the Flask app sends back an HTTP response header:

HTTP/1.1 200 OK
Server: Werkzeug/2.3.0 Python/3.9.2

This is intentional behavior to help legitimate clients know what they’re talking to. But it also tells attackers exactly what version is running (and whether it has known vulnerabilities).

What You’ll Observe

Expected nmap output:

Starting Nmap 7.94 ( https://nmap.org )
Nmap scan report for 192.168.4.1
Host is up (0.0023s latency).

PORT     STATE SERVICE    VERSION
22/tcp   open  ssh        OpenSSH 8.4p1 Debian 5+deb11u1
80/tcp   open  http       nginx 1.18.0
5000/tcp open  http       Werkzeug/2.3.0 Python/3.9.2
8080/tcp open  http       nginx 1.18.0

Nmap done: 1 IP address (1 host up) scanned in 12.45 seconds

Reading the Results Like a Pro

Port 22 – SSH:

  • What it is: Secure Shell – remote terminal access
  • Why it’s here: Legitimate administrative access
  • Risk level: Medium – if credentials are weak or default, this is an entry point
  • What you learned: The system is running Debian 11 (from OpenSSH version)

Port 80 – HTTP (nginx):

  • What it is: Web server hosting the registration portal
  • Why it’s here: Publicly advertised – expected
  • Risk level: Low – this is meant to be accessed
  • What you learned: nginx reverse proxy is in front (probably routing to backend apps)

Port 5000 – HTTP (Werkzeug/Python):

  • What it is: Flask development server (Python web framework)
  • Why it’s here: Backend application
  • Risk level: HIGH – Werkzeug is Flask’s development server, not meant for production
  • What you learned: This app is probably the intentionally vulnerable CTF target
  • Red flag: Development servers often have debug features enabled

Port 8080 – HTTP (nginx):

  • What it is: Dashboard application
  • Why it’s here: Publicly advertised scoreboard
  • Risk level: Low – expected public service

The Security Flaw Being Demonstrated

The vulnerabilityUnnecessary services with excessive exposure

The Flask app on port 5000 shouldn’t be directly accessible. In a properly designed architecture:

  • Public users hit nginx on port 80
  • nginx proxies to Flask internally (not exposed to the network)
  • Port 5000 would be filtered/firewalled from external access

Why this matters: Every exposed service is an additional attack surface. The Flask app on 5000 is now:

  1. Discoverable by anyone on the network
  2. Directly accessible (bypassing any protections nginx might provide)
  3. Running a development server (which likely has debug features)

The design flaw: Developers often expose services for “convenience” during development, then forget to lock them down in production. This is exactly how real breaches happen.


Challenge 2: Hidden Chiptune Server (100 pts)

The Mission

Objective: Find the hidden easter egg service that’s not on standard ports

What you’re testing: Whether “security through obscurity” (hiding services on non-standard ports) actually works

Expected discovery: Icecast streaming server on port 8000

The Thorough Detective

Why the first scan missed it:

By default, nmap scans only the 1,000 most common ports (80, 443, 22, 3306, etc.). This is fast and catches 95% of services. But it misses non-standard ports.

The comprehensive approach:

# Scan ALL possible ports (1-65535)
nmap -p1-65535 192.168.4.1

# Or focus on a likely range for streaming services
nmap -p 8000-8010 192.168.4.1

Why this takes longer:

  • 1,000 ports: ~10-30 seconds
  • 65,535 ports: ~5-10 minutes (depending on network speed)

The trade-off: Speed vs. thoroughness. Professional penetration testers do both:

  1. Fast scan first (find the obvious stuff)
  2. Comprehensive scan overnight (find the obscure stuff)

What You’ll Discover

PORT     STATE SERVICE
8000/tcp open  http-alt

Visiting http://192.168.4.1:8000 reveals:

  • An Icecast streaming server playing chiptune music
  • Complete with web interface and stream metadata
  • Totally functional, totally undocumented

The “Security Through Obscurity” Fallacy

What the administrator thought: “I’ll put the streaming server on port 8000 instead of 80. No one will find it unless they know it’s there.”

Why this failed:

  1. Ports are not secret compartments: They’re just numbers. Scanning all 65,535 takes minutes.
  2. Services still respond: When you connect to port 8000, Icecast says “Hello! I’m Icecast!”
  3. Obscurity ≠ Security: Hiding something non-obviously is not the same as protecting it.

The lesson:

Security through obscurity is not security—it’s hope.

Real security uses:

  • Authentication: Require credentials
  • Firewall rules: Block access from untrusted networks
  • Encryption: Protect data in transit
  • Least privilege: Don’t run services you don’t need

Not:

  • Running something on port 8000 instead of 80 and hoping no one notices

The Easter Egg Significance

In this CTF, the chiptune server is harmless fun. But in real penetration tests, this exact pattern reveals:

  • Forgotten admin panels on port 8443
  • Debug interfaces on port 9000
  • Database servers on non-standard ports (thinking they’re “hidden”)
  • Legacy applications no one remembered deploying

Real case study: In 2020, a major university breach occurred because a MongoDB database was running on port 27018 (one number off the standard 27017). The sysadmin thought changing the port was security. Attackers found it in 3 minutes with a port scan.


🛡️ The Defense: How To Do This Right

Root Cause vs. Symptom Fix

Symptom Fix (Band-aid):

  • “Let’s move the service to an even more obscure port!”
  • Why this fails: Obscurity is not security. It only delays discovery by minutes.

Root Cause Fix (Proper architecture):

1. Principle of Least Exposure

# Don't expose services that don't need to be public
# Use firewall rules to restrict access
sudo ufw deny 5000  # Block Flask app from network
sudo ufw deny 8000  # Block Icecast from network
sudo ufw allow 80   # Only expose the public web server

2. Proper Service Architecture

[User] → [Port 80: nginx (public)]
              ↓ (internal proxy)
         [Port 5000: Flask (localhost only)]

The Flask app should only listen on 127.0.0.1:5000 (localhost), not 0.0.0.0:5000 (all interfaces). This makes it invisible to network scans.

3. Disable Unnecessary Services

# If you don't need it, don't run it
sudo systemctl stop icecast2
sudo systemctl disable icecast2

Every running service is a potential attack vector. Turn off anything you don’t actively need.

Defense in Depth (Layered Security)

To prevent reconnaissance from revealing your attack surface:

Layer 1: Minimize services

  • Only run what’s necessary
  • Turn off debug/development features in production

Layer 2: Firewall/Network segmentation

  • Use firewall rules to block unauthorized access
  • Segment internal services from public-facing ones

Layer 3: Disable banner grabbing

# In nginx config
server_tokens off;  # Hides version numbers

This prevents nmap from seeing “nginx 1.18.0” – it just sees “nginx”

Layer 4: Intrusion detection

  • Monitor for port scans (excessive connection attempts)
  • Alert when scanning patterns are detected

Layer 5: Honeypots

  • Run fake services that log anyone who connects
  • Serves as an early warning system

Why layers matter: Even if an attacker bypasses one defense, the others catch them.


🧑‍🔬 Practice: Transfer Your Learning

Challenge 1: Same Vulnerability, Different System

Scenario: You’re auditing a corporate network. You scan the web server (10.0.1.50) and find:

PORT     STATE SERVICE    VERSION
80/tcp   open  http       Apache 2.4.41
443/tcp  open  https      Apache 2.4.41
3389/tcp open  ms-wbt-server Microsoft Terminal Services

Questions:

  1. What services are running?
  2. Which one is unusual for a web server?
  3. What does its presence suggest?
  4. How would you verify if it’s intentionally exposed?

Solution:

  • Port 3389 is Remote Desktop Protocol (RDP) – Windows remote access
  • Unusual because: Web servers don’t typically need RDP exposed to the public internet
  • Suggests: Either poor network segmentation OR this server has multiple roles (web + admin workstation)
  • Verification: Check if RDP is firewalled from external IPs but allowed internally (proper), or wide open (problem)
  • Risk: RDP is a high-value target – brute force attacks, exploits, credential theft

Challenge 2: Detecting the Vulnerability in Code

Scenario: You’re reviewing a Flask application’s configuration:

# app.py
from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return "Hello World"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

Questions:

  1. What’s the security problem here?
  2. How would you fix it for production?
  3. What’s the difference between ‘0.0.0.0’ and ‘127.0.0.1’?

Solution:

  1. Problems:
    • host='0.0.0.0' – Listens on ALL network interfaces (discoverable from network)
    • debug=True – Enables debug mode (exposes code, allows code execution via console)
    • Using Flask’s development server (not production-ready)
  2. Fixes:
# Production configuration
if __name__ == '__main__':
    # For local development only
    app.run(host='127.0.0.1', port=5000, debug=False)

# In production, use proper WSGI server:
# gunicorn -w 4 -b 127.0.0.1:5000 app:app
  1. host parameter:
    • '0.0.0.0' = “listen on ALL network interfaces” (WiFi, ethernet, localhost) – discoverable via network scan
    • '127.0.0.1' = “listen on localhost only” – only accessible from the machine itself (invisible to network scans)

Challenge 3: Attack Variation

Scenario: A system administrator read about port scanning and implemented this defense:

# Block nmap scans
iptables -A INPUT -p tcp --tcp-flags ALL SYN,ACK -j DROP

Question: Does this effectively hide services? Why or why not?

Solution:

  • No, this is easily bypassed
  • This rule blocks standard SYN scans, but nmap has multiple scan types:
    • -sT (TCP connect scan) – completes full handshake
    • -sF (FIN scan) – sends FIN packets instead of SYN
    • -sN (NULL scan) – sends packets with no flags
    • -sX (Xmas scan) – sends FIN, PSH, URG flags

Better approach: Don’t try to hide services from scans—actually secure them with authentication, firewalls, and proper architecture.


📚 Building Your Mental Model: Key Takeaways

You Now Understand

  • Reconnaissance: The phase where attackers gather information without exploiting vulnerabilities. It’s about discovery, not intrusion.
  • Service enumeration: The process of identifying what services are running on which ports by systematically probing and observing responses.
  • Attack surface: The sum of all exposed services and interfaces. More services = larger attack surface = more opportunities for vulnerabilities.
  • Security through obscurity: The flawed practice of hiding things (changing default ports, obscure filenames) instead of properly securing them. It delays discovery, but doesn’t prevent it.
  • Banner grabbing: The technique of extracting version information from services (they volunteer this in response headers). Critical for attackers to identify vulnerable versions.

You Can Now Reason About

When you encounter a system, you can now:

  1. Systematically enumerate what services are exposed (using tools like nmap)
  2. Distinguish between expected/public services and unexpected/hidden ones
  3. Assess risk based on what’s discoverable (development servers, unnecessary services)
  4. Understand why “hiding” services on non-standard ports is ineffective security
  5. Propose defenses based on reducing exposure, firewalling, and proper architecture

The Bigger Picture

Reconnaissance is one phase of the Cyber Kill Chain:

  1. Reconnaissance ← YOU ARE HERE – gather information about the target
  2. Weaponization – prepare exploits for discovered vulnerabilities
  3. Delivery – transmit the exploit to the target
  4. Exploitation – execute code/commands on the target
  5. Installation – install backdoors/persistence
  6. Command & Control – establish remote control
  7. Actions on Objectives – steal data, cause damage, etc.

Understanding reconnaissance teaches you:

  • Why minimizing attack surface matters: Every exposed service is a potential entry point
  • Why network segmentation works: Limiting what’s discoverable from untrusted networks
  • Why intrusion detection matters: Catching reconnaissance early stops the kill chain before exploitation

🔗 Connect to Prior Knowledge

This Builds On:

  • Basic networking (Level 1): You learned how to connect to a network. Now you’re learning what’s on that network.
  • TCP/IP fundamentals: Understanding how ports, services, and protocols work
  • Client-server architecture: Recognizing that servers listen and clients connect

This Enables:

  • Web exploitation (Level 3): Now that you know what services exist (HTTP on 5000), you can test them for vulnerabilities
  • System access (Level 4): The SSH service you discovered is how you’ll gain a shell
  • Privilege escalation (Level 5): Understanding running services helps identify escalation vectors
  • Vulnerability scanning (next step after reconnaissance)
  • CVE databases (how to look up known vulnerabilities in discovered services)
  • Network mapping (creating visual maps of discovered infrastructure)

🚨 Common Pitfalls & Misconceptions (Specific to This Lab)

Pitfall 1: “I don’t see anything else on port 80, so there’s nothing else running”

Why it happens: Browsers only show HTTP/HTTPS. If you type 192.168.4.1 into a browser, you only see port 80.

What to watch for: The assumption that “what I see in a browser = everything that exists”

The correction: Browsers are opinionated clients that default to port 80/443. To see the full picture, you need systematic scanning of all ports and protocols.


Pitfall 2: “nmap didn’t find port 8000, so I’m done”

Why it happens: Default nmap scans only check the 1,000 most common ports. Port 8000 is common, but not in the top 1,000 by default for all nmap configurations.

What to watch for: Stopping after the first quick scan without doing comprehensive enumeration

The correction: Professional reconnaissance uses multiple passes:

  1. Quick scan (top 1000 ports) – fast initial view
  2. Full scan (all 65,535 ports) – comprehensive enumeration
  3. Targeted scans (specific services, UDP, etc.)

Pitfall 3: “This port scan is taking forever, I’ll just cancel it”

Why it happens: Scanning 65,535 ports takes time (5-10 minutes). It feels like waiting.

What to watch for: Impatience leading to incomplete reconnaissance

The correction: Real penetration testing requires patience. Attackers don’t rush—they systematically explore. That hidden service on port 8000 is worth the wait.

Pro tip: Run comprehensive scans in the background while working on other challenges:

nmap -p1-65535 192.168.4.1 -oN fullscan.txt &

The & runs it in the background. Check results later with cat fullscan.txt


📖 Conceptual Glossary: Key Terms & Their Meanings

Port: A numbered endpoint (1-65535) where a service can listen for connections. Think of it as a numbered door in a building—each service gets its own door.

Service: A program that listens on a port and responds to network requests. Examples: web servers (HTTP), SSH servers, databases.

Banner: The identification information a service sends when you connect. Example: “OpenSSH 8.4p1” or “nginx/1.18.0”. Services do this to help legitimate clients, but it also helps attackers.

Attack surface: The total of all exposed services, ports, and interfaces that could potentially be exploited. Larger surface = more opportunities for attackers.

Enumeration: The systematic process of identifying what exists on a network (services, users, shares, etc.). Not exploitation—just discovery.

Service version detection (-sV in nmap): The process of connecting to services and identifying not just what port is open but what service is running and what version.

Security through obscurity: The flawed practice of “hiding” things (e.g., running a service on port 8000 instead of 80) as a security measure. It fails because hidden ≠ secure.

Reconnaissance vs Exploitation:

  • Reconnaissance: Gathering information (port scanning, service enumeration) – asking questions
  • Exploitation: Using discovered information to compromise a system (SQL injection, buffer overflow) – taking action

🎓 Self-Assessment: Did You Master This?

You’ve mastered this lab when you can:

  • [ ] Explain what port scanning does and why it’s not the same as “hacking” (in your own words, using the detective metaphor)
  • [ ] Run an nmap scan and interpret the results (identify services, versions, and which ones are unusual)
  • [ ] Identify why the Flask app on port 5000 shouldn’t be directly exposed to the network
  • [ ] Explain why security through obscurity (port 8000 for Icecast) failed
  • [ ] Propose how the system should be properly architected (firewall rules, localhost binding, minimal services)
  • [ ] Recognize the same pattern in a different scenario (like the RDP on web server example)
  • [ ] Distinguish between reconnaissance (discovery) and exploitation (compromise)

🧵 The Thread Onward

Now that you understand reconnaissance, you’re ready for the natural next step:

Level 3: Web Exploitation – You’ve discovered services. Now you’ll test them for vulnerabilities. The Flask app on port 5000 is intentionally vulnerable to SQL injection, command injection, and XSS. But you wouldn’t even know it existed without this reconnaissance phase.

The principle you’re learningattack surface reduction through exposure minimization—applies to:

  • Cloud security: Only opening necessary ports in security groups
  • Container security: Not exposing internal service ports
  • API security: Not exposing debug/admin endpoints in production
  • IoT security: Minimizing network-facing services on embedded devices

The broader lesson: Security isn’t just about “making things harder to exploit”—it’s about reducing what’s discoverable in the first place. You can’t exploit what you can’t find.


Key Insight: You didn’t “hack” anything in this level. You just looked. And yet you discovered things the defenders didn’t want you to know. That’s the power—and the danger—of reconnaissance.

Ready to move on? In Level 3, you’ll start actually testing these services for vulnerabilities. The discovery phase is over. The exploitation phase begins.

Reproducible Sneaky Wifi Part 2

Last week I left you with a nail-biter. I ran a sneaky wifi network near a weird marathon in 2018 and I captured close to 200 devices. I reproduced the experiment this fall- how’d it go in 2025? Terrible in some regards, but awesome in terms of prototyping acceleration. An experiment that took 2 months in 2018 took me 4 days in 2025.

Time lapse of runners

The Bad

In the 2025 experiment, I caught a grand total of 18 devices.

Does this mean mobile phones are more secure? Was it the exact same experiment? No!

Low Participant Turnout: My Wifi Hotspot was active starting at 7 am. The marathon was scheduled to start at 8 am. We didn’t see a single runner till ~9:15 am. When runners did start arriving, the quantity of runners was limited compared to past years. The 2018 marathon spanned two days. The race was only one day this year. The participant cohort of runners was significantly smaller than in years past.

Bad SSID choices: This attack depends upon your ability to anticipate a wifi ssid that your targets have an affinity for. The wifi SSID i used in 2018 wasn’t going to work because it has been deprecated. I went with “Starbucks WiFi” initially, but this only caught 2 devices. The lack of “Starbucks WiFi” tuned devices is an interesting indicator of how times have changed. It used to be that mobile phone owners needed to attach to wifi to use email/browse the web with their phones. This was because cellular networks did not have unlimited data, and so you either ran out of data for the month or you were hit with a large cellphone bill if you used cellular for data. People used to go to coffee shops to “work” on their phones and laptops. Now you’re really there to socialize or caffinate. I also wonder if Starbucks’ popularity has declined. In the last 10 years, I’ve only drank Starbucks out of necessity.

So after a couple of hours of watching only 2 attaches, I yielded to temptation and changed the SSID to “xfinitywifi.” The xfinitywifi ssid is a controversial wifi network vended by Comcast, exclusive to comcast customers.

You can use wigle.net to see the most popular active SSIDs:

Changing to use xfinitywifi felt like desperation! Comcast does not have much presence in Snoqualmie valley. I reasoned that most of the runners were probably coming from cities where Comcast is dominant- e.g. Bellevue, Issaquah and Redmond. I managed to catch 16 more devices over the next 4 hours. The count was so small I didn’t bother to keep my logs. But here are some screenshots to give you a feel for what I experienced:

Raspberry Pi with AWUS036ACH WiFi adapter & home built dual yagis
Paperwhite display
Custom status monitor


This experiment agitated me greatly. I know there are still problems related to wifi offloading- but I only caught 18 devices. I didn’t spend enough time researching SSIDs and the end result was low attaches.

Despite my grumpiness about the data, this experiment was a major success.

Did you notice the external Wifi Adapter above? How about the nice Paperwhite display presenting status of the device. My monitoring script was far more sophisticated than a tail of a hostapd logs. I didn’t have to write this code or fiddle with hostapd configurations or nftables rules. I didn’t have to find the right kernel headers and compile wifi drivers. I didn’t have to flex my terrible design skills. I knew the features I wanted and I gave my agents direction on how to deploy the features.

I was able to successfully produce an IoT prototype with complex hardware dependencies in 4 days.

The Good:


I implemented a working prototype of a custom wifi hotspot with a paperwhite display, an external wifi adapter & a Yagi wifi antenna in 4 days.

Methodology

Claude Code & Pre-prompting strategies

I leveraged Claude code for most of my work. I created a working directory invoked Claude with a 1,500 line pre-prompt for requirements analysis and planning. This pre-prompt produced ansible playbooks that take advantage of my Firmware Development caching containers. The pre-prompt addresses topics related to Requirement Exploration, Architecture Safety, Known Good Deployment Patterns, Domain Specific Knowledge and Documentation & Maintenance. I’ve been iterating on this prompt for about 6 weeks through applications on about 5 other projects. I constructed a separate pre-prompt of 166 lines that handles Deploying code, Code analysis, system access, frameworks for deploying code & systematic troubleshooting and refactoring the code to address discovered defects.

Development Loop

The normal lifecycle of developing a reliable working prototype seems to take about 3-4 build cycles.

My agent would serially perform the following operations during the build process:

  • Initiate a build
  • Discover defects during build process
  • Troubleshoot them on the recipient system
  • Make corrections to the original build playbooks
  • Resume the build at the corrected defect
  • Complete a working build.

If the build experienced errors, I waited to get a complete build and then started again on fresh recipient image. I kept seeing improvements until the build process ran reliably without errors.

Throttling

My biggest challenge was rate limiting:

My agents hit my 5 hour Anthropic token limit on the $20 plan in about 2 hours. During this 4 day period, I scheduled my day around throttling limits. I tried to make sure that some building happened while I slept. Two days before the marathon, I upgraded to the $200 plan. My iOS screen time report was 1 hour during that week.

I didn’t have to write any code to make this project work. That’s not to suggest that anybody could do this experiment. I was successful because I knew exactly what software libraries I wanted to see deployed and how I wanted them tuned. I regularly had to intervene when the agents proposed bad plans. But I’m now approaching a point where my single board computer development processes are automated. It felt like having a mildly competent apprentice.

Over the last few years, I’ve been able to build a range of Raspberry Pi Prototypes. All of them were a labor of large effort. My build process made prototyping faster, but it still took me several months to work out the details of various project:

Making reproducible builds was expensive and typically took 2-3 months. I’d steal spare time on evenings or weekends to work on projects. The greatest costs come from the testing & validation needed to create durable, reproducible firmware images.  With a combination of tasteful pre-prompts, custom agents & an automated build process I can turn around reproducible firmware builds in less than a week.



1. Software & Hardware Testing Houses

You need repeatable, cost-effective environments to validate new software and hardware under real-world conditions, but setting up and tearing down test rigs is slow, inconsistent, and prone to configuration drift.


2. Managed Security Service Providers (MSSPs)
You need deployable, trusted network nodes inside customer environments for monitoring, detection, and incident response — but sourcing, configuring, and reproducing reliable hardware platforms across dozens of clients eats up valuable engineering time.


3. IoT Manufacturers

You want to prove out your next device concept quickly, with working prototypes that demonstrate connectivity, edge processing, and security — but your in-house teams are bottle-necked by long development cycles and unpredictable integration issues.

4. Agricultural & Rural Networking Providers

You need rugged, affordable devices to extend connectivity into fields, barns, and remote communities — but commercial gear is overpriced, hard to customize, and not designed for rapid prototyping or deployment in challenging environments.

5. Telecom & Network Operators
You need cost-effective, rapidly deployable edge devices for monitoring network performance, testing bandwidth in rural or urban environments, or validating new customer premises equipment—but traditional hardware procurement cycles are too slow and expensive.

6. Smart City & Infrastructure Providers
You’re deploying IoT devices to manage traffic lights, utilities, or environmental sensors across a city, but you need quick, low-cost prototypes to validate integrations before scaling to tens of thousands of units.

7. Educational & Research Institutions
Your students or researchers need reproducible, documented environments for experimentation with hardware, networking, or AI, but setting up reliable builds consumes valuable teaching and research time.

8. Healthcare & MedTech Device Innovators
You’re exploring connected health devices—remote patient monitors, smart diagnostic tools, or secure data collection endpoints—but you need a prototype that proves functionality while meeting strict reliability and security requirements.

9. Defense & Public Safety Contractors
You’re tasked with rapidly developing ruggedized, secure edge devices for field communication, surveillance, or sensor fusion, but your internal teams can’t keep pace with the prototyping demands.

10. Environmental & Energy Monitoring Firms
You need distributed, low-power devices to collect data in harsh or remote environments—forests, farms, offshore rigs, or mines—but your current prototypes fail due to durability or reproducibility issues.

11. Media & Event Production Companies
You want portable, reliable devices for live-streaming, crowd analytics, or on-site Wi-Fi provisioning at concerts and sporting events, but consumer gear isn’t flexible enough and enterprise hardware is overkill.

12. Transportation & Logistics Providers
You’re experimenting with fleet tracking, warehouse automation, or smart inventory systems, but you need a way to test edge hardware integrations quickly before committing to full-scale rollouts.

13. Industrial Automation & Robotics
You need controllers and monitoring systems for robots, conveyors, or factory IoT sensors, but the cost and time of custom PLCs and proprietary systems make it hard to experiment quickly.

14. Consultancies & Systems Integrators
You’re responsible for stitching together hardware and software for your clients, but you lack a streamlined way to spin up reproducible prototypes that demonstrate proof-of-concept value quickly and reliably.

Guidelines for getting better at GIT

I’ve struggled with my git workflows. In the past, I found that I have a bad habit of dramatically editing my projects when I really should fork them. I’ve been putting some effort into building better git habits to help me avoid these situations. I started off being familiar with git init, git commit and git push, but stash and other commands were beyond my grasp. I’ve done some prompt engineering to develop guardrails for the types of development decisions that should be handled with some of the more advanced git use cases. Maybe these will help you!

A couple of safety nets for immediate use:

  • Always be able to undo:
    • See anything you’ve done: git reflog
    • Lightweight “save point”: git tag backup-$(date +%Y%m%d-%H%M%S)
      Portable snapshot (off-repo backup): git bundle create backup.bundle --all
  • WIP parking lot: prefer WIP commits on a throwaway branch over stash when work will last more than a few minutes. You can do this with the following command:
# from anywhere with uncommitted changes
b="wip/$(date +%Y%m%d-%H%M%S)"; \
git switch -c "$b" && git add -A && git commit -m "WIP: parked" --no-verify && git switch -

1. “Am I rewriting the product?” → Fork vs Branch

  • Use a fork (new repo) when:
    • You’re changing project direction, licensing, or governance.
    • You’ll diverge long-term from upstream (different roadmap) and want to pull upstream occasionally but not merge back regularly.
    • You need independent release cadence and issue tracking.
    • ✨ Tools: git remote add upstream <url>, then git fetch upstream and selective cherry-picks back.
  • Use a new branch (same repo) when:
    • It’s still the same product, just a big feature or refactor.
    • You want CI, PR review, and discoverability to stay in the same place.
    • ✨ Tools: git switch -c feature/refactor-auth, maybe behind a feature flag.

Quick rule: If you’d be uncomfortable merging it back “as-is,” consider a fork. If you’d merge it behind a flag after review, it’s a branch.


2) “Am I about to experiment wildly?” → Throwaway branch + worktree

  • Create a scratch branch you can nuke anytime: git switch -c spike/new-idea # or keep working tree separate so you don't juggle unstaged changes: git worktree add ../proj-spike spike/new-idea
  • If it works, cherry-pick useful commits onto a clean feature branch: git log --oneline # find hashes git switch feature/refactor git cherry-pick <hash1> <hash2>
  • If it fails: git switch main && git branch -D spike/new-idea && git worktree remove ../proj-spike

When to prefer git worktree: When you want two branches checked out simultaneously (e.g., bugfix and main) without stashing.


3) “My working tree is messy, I need to hop branches” → Stash vs WIP commit

  • Use stash for quick context switches and truly throwaway partial work: git stash push -m "WIP: parser tweak" # saves staged+unstaged git switch main && git pull git switch feature/parser git stash pop # apply and drop (use `apply` to keep in stash)
    • Keep it organized: git stash list, git stash show -p stash@{2}
    • Partial stash: git stash -p
  • Use a WIP commit if:
    • Work spans hours/days or you need team visibility & CI.
    • You want history and easy recovery: git add -A && git commit -m "WIP: parser spike (not for merge)"
    • Later clean history with an interactive rebase (see §7).

Rule of thumb: Minutes → stash. Hours/days → WIP commit.


4) “I’ve started a big refactor on top of stale main” → Rebase early, merge late

  • Keep your feature branch fresh to minimize painful conflicts later: git fetch origin git rebase origin/main # replay your commits onto latest main # if conflicts: resolve, then git rebase --continue
  • Prefer rebase for private branches; prefer merge for shared/history-sensitive branches.

Guardrail: If the branch is already public and teammates might have based work on it, avoid rebasing it; use git merge origin/main.


5) “I need to land part of a large change safely” → Split & cherry-pick

  • Break work into small, reviewable commits and land enabling changes first:
    • Extract a pure “rename/move” commit (no logic change).
    • Land new interfaces behind feature flags with no callers.
  • Use git cherry-pick to move those low-risk commits into separate PRs: git cherry-pick <hash> # keep author/date and exact diff

6) “I must keep risky code from reaching users” → Feature flags + release branches

  • Main stays releasable; incomplete work guarded by flags.
  • Release branches cut from main when stabilizing: git switch -c release/1.4.0
    • Only bug fixes cherry-picked into release branch.
    • Tag final release: git tag -a v1.4.0 -m "Release 1.4.0" && git push --tags

7) “My history is noisy; I want it clean before merging” → Interactive rebase

  • Squash fixups, rename messages, reorder commits: git fetch origin git rebase -i origin/main # Use: pick / reword / squash / fixup
  • Use --autosquash with fixup! commits: git commit --fixup <hash> git rebase -i --autosquash origin/main

Guardrail: Only rewrite history on branches no one else has pulled.


8) “I need to find where a bug was introduced” → Bisect

git bisect start
git bisect bad HEAD
git bisect good v1.3.2     # or a known-good commit
# Git checks out midpoints; you run tests and mark them:
git bisect good | bad
git bisect reset

Automate with a test script: git bisect run ./ci/test.sh


9) “I want to share part of the repo or vendor another repo” → Subtree vs submodule

  • Subtree (simple, self-contained code copy you occasionally sync):
    • Pros: no extra checkout step for consumers; normal commits.
    • Cons: merges can be larger; history mixed.
  • Submodule (true nested repo):
    • Pros: clean separation, track exact external revisions.
    • Cons: extra steps for users/CI (--recurse-submodules), more footguns.

Guardrail: If your consumers shouldn’t think about extra steps, prefer subtree.


10) “Repo is huge; I only need a slice” → Sparse checkout

git sparse-checkout init --cone
git sparse-checkout set src/api docs

Great for monorepos or to focus on one component.


11) Everyday branch hygiene (golden rules)

  1. Create a branch early for any work > 15 minutes.
    git switch -c feature/<short-purpose>
  2. Sync daily: git fetch && git rebase origin/main (if private).
  3. Commit small, purposeful changes with present-tense messages.
  4. Keep main green; hide incomplete features behind flags.
  5. Use throwaway spikes for experiments; keep or delete sans guilt.
  6. Tag releases and cut release branches for stabilization.
  7. Never rebase shared branches; merge instead.

Minimal command playbook (copy/paste friendly)

# Start a feature
git switch -c feature/login-oauth
# Work... then sync with latest main (private branch)
git fetch origin
git rebase origin/main

# Park work temporarily
git stash push -m "WIP: oauth redirect"
# or (longer): WIP commit
git add -A && git commit -m "WIP: oauth redirect not wired"

# Create a spike in a separate working directory
git worktree add ../proj-oauth-spike spike/oauth
# ...experiment...
git worktree remove ../proj-oauth-spike && git branch -D spike/oauth

# Prepare a clean history before PR
git rebase -i origin/main   # squash/fixup

# Split out a safe helper into a separate PR
git cherry-pick <hash-of-helper-commit>

# Release flow
git switch -c release/1.5.0
git tag -a v1.5.0 -m "Release 1.5.0"
git push origin release/1.5.0 --tags

# Disaster recovery
git reflog                  # find the good state
git reset --hard <hash>

Helpful .gitconfig aliases (speeds up the guardrails)

[alias]
  co = checkout
  sw = switch
  br = branch
  st = status -sb
  lg = log --oneline --decorate --graph --all
  rb = rebase
  rbi = rebase -i
  fp = fetch --prune
  pop = stash pop
  ap = stash apply
  aa = add -A
  cm = commit -m
  fix = commit --fixup
  autosquash = !git rebase -i --autosquash
  unstage = reset HEAD --
  wip = !git add -A && git commit -m 'WIP'

What to do when you “feel the drift”

Use this quick decision tree:

  • “This is becoming a different product/vision.”Fork.
  • “This is a big refactor or feature but same product.”Feature branch, guard with flags.
  • “I want to try something risky fast.”Spike branch (ideally via worktree), later cherry-pick.
  • “I must context-switch now.”
    • Short: stash
    • Long: WIP commit
  • “History is messy before merge.”Interactive rebase (private only).
  • “Need to ship, but not everything is ready.”Release branch + cherry-pick fixes.
  • “Bug appeared somewhere in history.”bisect.

Post-Defcon Notes

Defcon Achievements and some notes on the phreakme.ctf

  • HAM! I passed my technician’s license exam. I put in about 2.5 hours worth of practice using ham.study. I could have shortened this practice time by exclusively practicing using Study Mode on HAMstudy.org. ~ 2 runs through of reading each of the questions with corresponding answers, plus a practice run on the exam should be sufficient for a pass.
  • Phreaking. I did ok at the phreakme ctf. I didn’t put in heavy effort- most of my points were acquired on my mobile phone while going through the airport for my defcon departure. I completed the 2600 blueboxing challenge with my daughter at home using my mobile phone and an iPad hosting a tone generator. Unfortunately I ran out of time to do significant competing on the other challenges. I loved the bbs for the phreakme challenge- the defcon badge trading game was cute & absurd. I found a couple of entertaining resources to follow up on…
  • Text Filez!
    • Knowledge: In the 90s, text filez were a big thing. I’ve found it hard to find resources from this era- somewhere in my attic I have a 3 ring binder with hacking material I printed up while in highschool/college. I didn’t have my binder in Vegas- but I managed to locate some fun material at www.textfiles.com. They have an archive of blueboxing files at http://textfiles.com/phreak/BLUEBOXING/. Sadly- I didn’t find what I needed from that resource before the end of the CTF. The objective I understood: I needed to be on an idle line to blast the 2600 tone. The challenge in front of me: I was unclear on what the meaning of an “idle” line was. It turns out that it was just a connected line. Lame. The connections museum had some great material that has helped me understand the concepts:
  • Hacking Trunks!
    • In phreakme bluebox challenge 400– it is asserted that we should take control of a trunk line. My current understanding of this concept is as follows:
      • Trunking Basics: When you make a phone call, a connection is established between your home and the local central office of your neighborhood- this is the 000-NXX-0000 part of your phone number- called the Central Office Code.
      • https://youtube.com/clip/UgkxmmDOj-icN8_-y-cv_B5eIdngOhtVZpTc?si=RHNAIUhAeoXVvQ2h
      • Between Central offices are connections called “Trunk Lines.” Trunk lines are precious assets- you can only have one connection active per call on a trunk.
        • In this challenge- our objective is to manipulate the connection from our central office to another central office. In the modern internet- this would be like persuading a router in a traceroute path to use a different route for sending traffic. My unsolved question in the modern era: how do you capture an “Idle” line to blast the 2600 tone into and take control of the trunk?
        • I think the basics of capturing an idle line are as follows:
          • Call an 800 number/terminating number.
          • Once the connection to the 800 number is made, Play the 2600 tone
          • The terminating end thinks that the connection has been closed- but my local CO keeps the call to the 800 number open. This creates a kind of race condition where the CO near the 800 number will now respond to DMTF tones as if they’re from a system that’s connected to the local central office.
          • Executing the attack: Dialing DMTF tones while on the seized trunk will look to the “terminating CO” like a new call is being initiated. This enables the call routing from the terminating CO to a long distance target.
        • One part of the challenge I got stuck on was finding the phone number for the NEX executive. I did some google searching to see if I could find a number- but I was concerned that a google result likely wasn’t being operated by the CTF folks and I succumbed to analysis paralysis. I didn’t want to blast some target that wasn’t operated by the CTF & I wimped out on probing the target.
          • Now that the CTF is completed- I see that the “phone number” for the NEX Executive was somewhere on the BBS. Good thing I trusted my gut. I’ll have to try this challenge next year while it’s running.

If you are like me- an external observer aware of the phreaking era- but having missed out on the opportunity to play- these three videos are nourishing:

Trunks Demystified

Seizing a Trunk:

Making the call after seizing a trunk: