CTF challenge triage and solve methodology — category detection, tool selection, and multi-step solve chains across pwn/rev/crypto/forensics/web/misc.
62
73%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./packages/decepticon/decepticon/skills/standard/reverser/ctf-triage/SKILL.mdAuthorized-use caveat: This skill is for legal CTF competitions, security education, and authorized research environments only. Never apply these techniques to systems without explicit written authorization.
Identify challenge category before touching any tool.
# Universal file fingerprint
file challenge_file
xxd challenge_file | head -4 # magic bytes
strings -n 8 challenge_file | head -30
binwalk challenge_file # embedded files / compression layers
exiftool challenge_file # metadata (images, PDFs)| Magic bytes / extension | Category | Next phase |
|---|---|---|
| ELF / PE / Mach-O | Pwn / Rev | Phase 1a / 1b |
| PNG / JPG / BMP / WAV | Steganography / Forensics | Phase 2 |
| PCAP / PCAPNG | Network forensics | Phase 3 |
Memory dump (.raw, .vmem, .dmp) | Memory forensics | Phase 4 |
| Ciphertext / hex blob / base64 | Crypto | Phase 5 |
| Web URL / source | Web | Use exploit/web/ skills |
| Archive / unknown binary | Misc / forensics | Phase 6 |
checksec --file=./binary
# Key outputs: RELRO, Stack Canary, NX, PIE, RUNPATH| Property | Absent = exploitable via... |
|---|---|
| Stack canary | Stack overflow → ret2libc / ROP |
| NX (No-Execute) | Shellcode injection to stack/heap |
| PIE | Fixed address assumptions for ROP gadgets |
| Full RELRO | GOT overwrite |
objdump -d ./binary | grep -A 20 "<main>"
strings ./binary | grep -E "(flag|CTF|pass|secret|/bin/sh)"
readelf -s ./binary | grep -E "(sym|FUNC)"
# Heavy analysis
ghidra ./binary # or: r2 -A ./binary# GDB with GEF/PEDA
gdb -q ./binary
# Inside GDB:
# pattern create 200
# run < <(python3 -c "print('A'*200)")
# pattern offset $rsp
# Pwntools skeleton
python3 - <<'EOF'
from pwn import *
context.binary = elf = ELF('./binary')
p = process('./binary')
# or: p = remote('challenge.host', 1337)
offset = cyclic_find(0x61616161) # replace with crashing value
payload = b'A' * offset + p64(elf.sym['win'])
p.sendline(payload)
p.interactive()
EOFROPgadget --binary ./binary --rop | grep "pop rdi"
# or: ropper -f ./binary --search "pop rdi"
python3 - <<'EOF'
from pwn import *
elf = ELF('./binary')
libc = ELF('./libc.so.6')
rop = ROP(elf)
rop.call('puts', [elf.got['puts']])
rop.call(elf.sym['main'])
# Leak libc base, then ret2libc
EOF# Identify libc from leaked addresses
python3 -m one_gadget libc.so.6
# or: libc-database lookup# Strings for quick wins (flag format, hardcoded keys)
strings ./binary | grep -iE "(flag\{|ctf\{|[A-Z0-9_]{10,}\})"
# Ghidra headless (no GUI)
analyzeHeadless /tmp/ghidra_proj ChalProj \
-import ./binary \
-postScript PrintASM.java \
-scriptPath /opt/ghidra/Ghidra/Features/Decompiler/ghidra_scripts \
2>/dev/null
# radare2 (faster for known binary formats)
r2 -A ./binary
# Inside r2: afl (functions), pdf @ sym.main, VV (visual)# Detect packers
upx -t ./binary # UPX packed?
die ./binary # Detect-It-Easy
# If packed: upx -d ./binary
# Entropy analysis (high entropy sections = packed/encrypted)
binwalk -E ./binaryIf packed, see reverser/packer-unpacking/SKILL.md.
# Angr — solve unknown input to reach target state
python3 - <<'EOF'
import angr, claripy
proj = angr.Project('./binary', auto_load_libs=False)
flag_chars = [claripy.BVS(f'flag_{i}', 8) for i in range(32)]
flag = claripy.Concat(*flag_chars)
state = proj.factory.full_init_state(stdin=flag)
for c in flag_chars:
state.add_constraints(c >= 0x20, c <= 0x7e)
sm = proj.factory.simulation_manager(state)
sm.explore(find=lambda s: b'Correct' in s.posix.dumps(1),
avoid=lambda s: b'Wrong' in s.posix.dumps(1))
if sm.found:
print(sm.found[0].solver.eval(flag, cast_to=bytes))
EOF# 1. Metadata
exiftool challenge.png
# Look for: Comment field, GPS coords, Software, hidden IPTC/XMP data
# 2. Appended data after EOF marker
xxd challenge.jpg | tail -20
# JPEG ends at FF D9; anything after = appended content
# 3. LSB steganography (most common CTF technique)
zsteg challenge.png # PNG/BMP LSB
stegsolve challenge.png # GUI — bit plane analysis (run with: java -jar stegsolve.jar)
steghide extract -sf challenge.jpg -p "" # try empty passphrase first
steghide extract -sf challenge.jpg -p "password"
# 4. Outguess (JPEG)
outguess -r challenge.jpg output.txt
# 5. Audio steganography
sox challenge.wav -n stat # audio properties
spectral view in Audacity or Sox spectrogramstegseek challenge.jpg /usr/share/wordlists/rockyou.txt# Quick summary
capinfos challenge.pcap
tshark -r challenge.pcap -q -z io,phs # protocol hierarchy
tshark -r challenge.pcap -q -z conv,tcp # TCP conversations
# Extract HTTP objects (images, files)
tshark -r challenge.pcap --export-objects http,/tmp/pcap_http/
# Extract credentials
tshark -r challenge.pcap -Y "ftp || http.request.method==POST" -T fields \
-e frame.number -e ip.src -e tcp.payload
# Follow TCP stream (stream index from Wireshark or tshark)
tshark -r challenge.pcap -q -z follow,tcp,ascii,0
# DNS exfiltration
tshark -r challenge.pcap -Y dns -T fields -e dns.qry.name | sort -u | grep -v "\.arpa"# Identify OS profile
vol3 -f memory.raw windows.info 2>/dev/null || vol3 -f memory.raw linux.info
# Windows
vol3 -f memory.raw windows.pslist
vol3 -f memory.raw windows.cmdline
vol3 -f memory.raw windows.netscan
vol3 -f memory.raw windows.malfind # injected code
vol3 -f memory.raw windows.dumpfiles --pid <PID> --output-dir /tmp/
# Linux
vol3 -f memory.raw linux.pslist
vol3 -f memory.raw linux.bash
# Carve files
foremost -i memory.raw -o /tmp/foremost_out/# Encoding layers (base64, hex, rot13, etc.)
echo "encoded_string" | base64 -d
echo "encoded_string" | xxd -r -p # hex to binary
echo "encoded_string" | tr 'A-Za-z' 'N-ZA-Mn-za-m' # ROT13
# CyberChef magic function: https://gchq.github.io/CyberChef/#recipe=Magic(3,false,false,'')
# Hash identification
hash-identifier <hash>
hashid <hash># Frequency analysis (substitution ciphers)
python3 - <<'EOF'
from collections import Counter
ct = "YOUR_CIPHERTEXT_HERE"
freq = Counter(c for c in ct.upper() if c.isalpha())
for char, count in freq.most_common(10):
print(f"{char}: {count} ({count/len([c for c in ct if c.isalpha()])*100:.1f}%)")
# English: E=12.7%, T=9%, A=8.2%, O=7.5%
EOF# Factor small/weak modulus
python3 - <<'EOF'
from sympy import factorint
n = <modulus>
factors = factorint(n)
print(factors) # p, q
# If factored: phi=(p-1)*(q-1), d=pow(e,-1,phi), m=pow(c,d,n)
EOF
# Wiener's attack (small private exponent)
# RsaCtfTool covers common attacks:
python3 RsaCtfTool.py --publickey pub.pem --attack all --uncipherfile cipher.bin
# Common primes / known factors
# Check factordb.com for nhashcat -m <mode> hash.txt /usr/share/wordlists/rockyou.txt
# -m 0=MD5, 1000=NTLM, 1800=sha512crypt, 13000=RAR5
john --wordlist=/usr/share/wordlists/rockyou.txt --format=<format> hash.txt# Multi-layer extraction
binwalk -eM challenge_file # recursive extraction
7z l archive.7z # list contents without extracting
zip2john archive.zip > zip.hash && john zip.hash
# QR codes / barcodes
zbarimg image.png
# or: zxing online decoder
# PDF analysis
pdfinfo document.pdf
pdf-parser.py -o 1 document.pdf # extract object
peepdf document.pdf -i # interactive analysis1. file + strings + xxd (30 seconds) → category decision
2. Category-specific triage (Phases 1-6 above)
3. Quick wins first: hardcoded strings, empty passphrase, default creds
4. If stuck > 15 min: try adjacent technique (encoding layer, nested file)
5. Note flag format from challenge description (e.g., FLAG{...}, ctf{...})
6. Validate flag matches expected format before submitting| Phase | Technique |
|---|---|
| Binary exploitation | T1059.004 (Unix Shell), T1203 (Exploit for Client Exec) |
| Packer analysis | T1027.002 (Obfuscated Files - Software Packing) |
| Crypto decoding | T1140 (Deobfuscate/Decode Files), T1027 (Obfuscated Files) |
| Stego extraction | T1564.003 (Hidden in Files/Images) |
| Memory forensics | T1055 (Process Injection detection), T1070 (Indicator Removal) |
strings first-eM (recursive) is essential — CTF files routinely nest 3-4 compression layerse34afba
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.