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.
- package/AGENTS.md +131 -0
- package/Dockerfile +192 -0
- package/README.md +522 -0
- package/agents/ctf-analyzer.md +58 -0
- package/agents/ctf-controller.md +151 -0
- package/agents/ctf-speedrun.md +74 -0
- package/bin/ctf-agent.js +119 -0
- package/docker-compose.yml +13 -0
- package/mcp_config.json +19 -0
- package/package.json +44 -0
- package/references/ctf-triage-ladder.md +68 -0
- package/references/exploit-databases.md +575 -0
- package/references/llm-safety-and-policy-compliance.md +173 -0
- package/references/multi-agent-orchestration-and-policy-routing.md +278 -0
- package/references/security-events-and-intelligence.md +566 -0
- package/references/version-matrix.md +59 -0
- package/rules/ctf-execution-rules.md +44 -0
- package/rules/ctf-safety-framing-rules.md +140 -0
- package/rules/flag-validation-rules.md +25 -0
- package/scripts/__init__.py +1 -0
- package/scripts/ctf-tools.lock +205 -0
- package/scripts/ctf_init.py +1026 -0
- package/scripts/ctf_update.py +583 -0
- package/scripts/ctfd_client.py +81 -0
- package/scripts/cve_lookup.py +453 -0
- package/scripts/extract_flags.py +155 -0
- package/scripts/install_as_agent.py +278 -0
- package/scripts/install_ctf_tools.sh +603 -0
- package/scripts/parallel_triage.py +395 -0
- package/scripts/prompt_policy_sanitizer.py +283 -0
- package/scripts/scope_guard.py +444 -0
- package/scripts/skill_validator.py +504 -0
- package/scripts/workspace_cleaner.py +141 -0
- package/skills/ctf-ai-ml/SKILL.md +120 -0
- package/skills/ctf-ai-ml/adversarial-ml.md +623 -0
- package/skills/ctf-ai-ml/llm-attacks.md +487 -0
- package/skills/ctf-ai-ml/model-attacks.md +422 -0
- package/skills/ctf-crypto/SKILL.md +320 -0
- package/skills/ctf-crypto/advanced-math.md +798 -0
- package/skills/ctf-crypto/classic-ciphers.md +651 -0
- package/skills/ctf-crypto/ecc-attacks.md +347 -0
- package/skills/ctf-crypto/exotic-crypto-2.md +380 -0
- package/skills/ctf-crypto/exotic-crypto.md +528 -0
- package/skills/ctf-crypto/historical.md +113 -0
- package/skills/ctf-crypto/lattice-and-lwe.md +524 -0
- package/skills/ctf-crypto/modern-ciphers-2.md +563 -0
- package/skills/ctf-crypto/modern-ciphers-3.md +453 -0
- package/skills/ctf-crypto/modern-ciphers.md +649 -0
- package/skills/ctf-crypto/prng-attacks.md +257 -0
- package/skills/ctf-crypto/prng.md +664 -0
- package/skills/ctf-crypto/rsa-attacks-2.md +792 -0
- package/skills/ctf-crypto/rsa-attacks.md +487 -0
- package/skills/ctf-crypto/stream-ciphers.md +390 -0
- package/skills/ctf-crypto/zkp-and-advanced.md +456 -0
- package/skills/ctf-forensics/3d-printing.md +121 -0
- package/skills/ctf-forensics/SKILL.md +379 -0
- package/skills/ctf-forensics/disk-advanced.md +497 -0
- package/skills/ctf-forensics/disk-and-memory.md +491 -0
- package/skills/ctf-forensics/disk-recovery.md +699 -0
- package/skills/ctf-forensics/linux-forensics.md +511 -0
- package/skills/ctf-forensics/network-advanced.md +583 -0
- package/skills/ctf-forensics/network.md +645 -0
- package/skills/ctf-forensics/peripheral-capture.md +287 -0
- package/skills/ctf-forensics/signals-and-hardware.md +713 -0
- package/skills/ctf-forensics/steganography.md +694 -0
- package/skills/ctf-forensics/stego-advanced-2.md +475 -0
- package/skills/ctf-forensics/stego-advanced.md +481 -0
- package/skills/ctf-forensics/stego-image.md +691 -0
- package/skills/ctf-forensics/windows.md +625 -0
- package/skills/ctf-malware/SKILL.md +181 -0
- package/skills/ctf-malware/c2-and-protocols.md +274 -0
- package/skills/ctf-malware/pe-and-dotnet.md +108 -0
- package/skills/ctf-malware/scripts-and-obfuscation.md +449 -0
- package/skills/ctf-misc/SKILL.md +498 -0
- package/skills/ctf-misc/bashjails.md +323 -0
- package/skills/ctf-misc/ctfd-navigation.md +465 -0
- package/skills/ctf-misc/dns.md +255 -0
- package/skills/ctf-misc/encodings-advanced.md +504 -0
- package/skills/ctf-misc/encodings.md +431 -0
- package/skills/ctf-misc/games-and-vms-2.md +254 -0
- package/skills/ctf-misc/games-and-vms-3.md +690 -0
- package/skills/ctf-misc/games-and-vms-4.md +229 -0
- package/skills/ctf-misc/games-and-vms.md +529 -0
- package/skills/ctf-misc/linux-privesc.md +333 -0
- package/skills/ctf-misc/pyjails.md +671 -0
- package/skills/ctf-misc/rf-sdr.md +91 -0
- package/skills/ctf-osint/SKILL.md +198 -0
- package/skills/ctf-osint/geolocation-and-media.md +464 -0
- package/skills/ctf-osint/social-media.md +312 -0
- package/skills/ctf-osint/web-and-dns.md +341 -0
- package/skills/ctf-pwn/SKILL.md +214 -0
- package/skills/ctf-pwn/advanced-exploits-2.md +579 -0
- package/skills/ctf-pwn/advanced-exploits-3.md +598 -0
- package/skills/ctf-pwn/advanced-exploits-4.md +590 -0
- package/skills/ctf-pwn/advanced-exploits-5.md +119 -0
- package/skills/ctf-pwn/advanced-exploits.md +773 -0
- package/skills/ctf-pwn/advanced.md +326 -0
- package/skills/ctf-pwn/field-notes.md +245 -0
- package/skills/ctf-pwn/format-string.md +694 -0
- package/skills/ctf-pwn/heap-fsop.md +285 -0
- package/skills/ctf-pwn/heap-techniques-2.md +333 -0
- package/skills/ctf-pwn/heap-techniques.md +513 -0
- package/skills/ctf-pwn/kernel-bypass.md +421 -0
- package/skills/ctf-pwn/kernel-techniques.md +366 -0
- package/skills/ctf-pwn/kernel.md +636 -0
- package/skills/ctf-pwn/overflow-basics.md +611 -0
- package/skills/ctf-pwn/rop-advanced.md +725 -0
- package/skills/ctf-pwn/rop-and-shellcode.md +659 -0
- package/skills/ctf-pwn/sandbox-escape.md +313 -0
- package/skills/ctf-reverse/SKILL.md +163 -0
- package/skills/ctf-reverse/anti-analysis-ctf.md +204 -0
- package/skills/ctf-reverse/anti-analysis.md +693 -0
- package/skills/ctf-reverse/field-notes.md +376 -0
- package/skills/ctf-reverse/languages-compiled.md +666 -0
- package/skills/ctf-reverse/languages-platforms.md +592 -0
- package/skills/ctf-reverse/languages.md +553 -0
- package/skills/ctf-reverse/patterns-ctf-2.md +397 -0
- package/skills/ctf-reverse/patterns-ctf-3.md +797 -0
- package/skills/ctf-reverse/patterns-ctf.md +670 -0
- package/skills/ctf-reverse/patterns-runtime.md +274 -0
- package/skills/ctf-reverse/patterns.md +572 -0
- package/skills/ctf-reverse/platforms-hardware.md +387 -0
- package/skills/ctf-reverse/platforms.md +664 -0
- package/skills/ctf-reverse/tools-advanced-2.md +421 -0
- package/skills/ctf-reverse/tools-advanced.md +407 -0
- package/skills/ctf-reverse/tools-dynamic.md +679 -0
- package/skills/ctf-reverse/tools-emulation.md +319 -0
- package/skills/ctf-reverse/tools.md +573 -0
- package/skills/ctf-web/SKILL.md +153 -0
- package/skills/ctf-web/auth-and-access-2.md +82 -0
- package/skills/ctf-web/auth-and-access.md +783 -0
- package/skills/ctf-web/auth-infra.md +321 -0
- package/skills/ctf-web/auth-jwt.md +186 -0
- package/skills/ctf-web/client-side-advanced.md +739 -0
- package/skills/ctf-web/client-side.md +529 -0
- package/skills/ctf-web/cves.md +373 -0
- package/skills/ctf-web/field-notes.md +482 -0
- package/skills/ctf-web/node-and-prototype.md +200 -0
- package/skills/ctf-web/server-side-2.md +337 -0
- package/skills/ctf-web/server-side-advanced-2.md +559 -0
- package/skills/ctf-web/server-side-advanced-3.md +125 -0
- package/skills/ctf-web/server-side-advanced-4.md +480 -0
- package/skills/ctf-web/server-side-advanced.md +378 -0
- package/skills/ctf-web/server-side-deser.md +443 -0
- package/skills/ctf-web/server-side-exec-2.md +799 -0
- package/skills/ctf-web/server-side-exec.md +457 -0
- package/skills/ctf-web/server-side.md +629 -0
- package/skills/ctf-web/sql-injection.md +790 -0
- package/skills/ctf-web/web3.md +374 -0
- package/skills/ctf-writeup/SKILL.md +90 -0
- package/skills/solve-challenge/SKILL.md +269 -0
- package/skills.json +16 -0
|
@@ -0,0 +1,625 @@
|
|
|
1
|
+
# CTF Forensics - Windows
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
- [Windows Event Logs (.evtx)](#windows-event-logs-evtx)
|
|
5
|
+
- [Registry Analysis](#registry-analysis)
|
|
6
|
+
- [OEMInformation Backdoor Detection](#oeminformation-backdoor-detection)
|
|
7
|
+
- [SAM Database Analysis](#sam-database-analysis)
|
|
8
|
+
- [Recycle Bin Forensics](#recycle-bin-forensics)
|
|
9
|
+
- [Browser History](#browser-history)
|
|
10
|
+
- [Windows Telemetry (imprbeacons.dat)](#windows-telemetry-imprbeaconsdat)
|
|
11
|
+
- [Hosts File Hidden Data](#hosts-file-hidden-data)
|
|
12
|
+
- [Contact Files (.contact)](#contact-files-contact)
|
|
13
|
+
- [WinZip AES Encrypted Archives](#winzip-aes-encrypted-archives)
|
|
14
|
+
- [NTFS Alternate Data Streams](#ntfs-alternate-data-streams)
|
|
15
|
+
- [NTFS MFT Analysis](#ntfs-mft-analysis)
|
|
16
|
+
- [USN Journal ($J) Analysis](#usn-journal-j-analysis)
|
|
17
|
+
- [SAM Account Creation Timing](#sam-account-creation-timing)
|
|
18
|
+
- [Impacket wmiexec.py Artifacts](#impacket-wmiexecpy-artifacts)
|
|
19
|
+
- [PowerShell History as Timeline](#powershell-history-as-timeline)
|
|
20
|
+
- [User Profile Creation as First Login Indicator](#user-profile-creation-as-first-login-indicator)
|
|
21
|
+
- [RDP Session Event IDs](#rdp-session-event-ids)
|
|
22
|
+
- [Windows Defender MPLog Analysis](#windows-defender-mplog-analysis)
|
|
23
|
+
- [Anti-Forensics Detection Checklist](#anti-forensics-detection-checklist)
|
|
24
|
+
- [Windows Memory Forensics: certutil Base64 ZIP Recovery (SEC-T CTF 2017)](#windows-memory-forensics-certutil-base64-zip-recovery-sec-t-ctf-2017)
|
|
25
|
+
- [NTFS EFSTMPWP Folder as cipher.exe Wipe Artifact (Security Fest CTF 2018)](#ntfs-efstmpwp-folder-as-cipherexe-wipe-artifact-security-fest-ctf-2018)
|
|
26
|
+
- [Volatility clipboard Plugin for Copy-Paste Secret Recovery (OtterCTF 2018)](#volatility-clipboard-plugin-for-copy-paste-secret-recovery-otterctf-2018)
|
|
27
|
+
- [Volatility Credential Recovery Toolkit (OtterCTF 2018)](#volatility-credential-recovery-toolkit-otterctf-2018)
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Windows Event Logs (.evtx)
|
|
32
|
+
|
|
33
|
+
**Key Event IDs:**
|
|
34
|
+
|
|
35
|
+
| Event ID | Description |
|
|
36
|
+
|----------|-------------|
|
|
37
|
+
| 1001 | Bugcheck/reboot |
|
|
38
|
+
| 41 | Unclean shutdown |
|
|
39
|
+
| 4720 | User account created |
|
|
40
|
+
| 4722 | User account enabled |
|
|
41
|
+
| 4724 | Password reset attempted |
|
|
42
|
+
| 4726 | User account deleted |
|
|
43
|
+
| 4738 | User account changed |
|
|
44
|
+
| 4781 | Account name changed (renamed) |
|
|
45
|
+
|
|
46
|
+
**Parse with python-evtx:**
|
|
47
|
+
```python
|
|
48
|
+
import Evtx.Evtx as evtx
|
|
49
|
+
import xml.etree.ElementTree as ET
|
|
50
|
+
|
|
51
|
+
with evtx.Evtx("Security.evtx") as log:
|
|
52
|
+
for record in log.records():
|
|
53
|
+
xml_str = record.xml()
|
|
54
|
+
root = ET.fromstring(xml_str)
|
|
55
|
+
ns = {'ns': 'http://schemas.microsoft.com/win/2004/08/events/event'}
|
|
56
|
+
|
|
57
|
+
event_id = root.find('.//ns:EventID', ns).text
|
|
58
|
+
if event_id == '4720':
|
|
59
|
+
data = {}
|
|
60
|
+
for d in root.findall('.//ns:Data', ns):
|
|
61
|
+
data[d.get('Name')] = d.text
|
|
62
|
+
print(f"User created: {data.get('TargetUserName')}")
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Registry Analysis
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# RegRipper
|
|
71
|
+
rip.pl -r NTUSER.DAT -p all
|
|
72
|
+
|
|
73
|
+
# Key hives
|
|
74
|
+
NTUSER.DAT # User settings
|
|
75
|
+
SAM # User accounts
|
|
76
|
+
SYSTEM # System config
|
|
77
|
+
SOFTWARE # Installed software
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### OEMInformation Backdoor Detection
|
|
81
|
+
|
|
82
|
+
**Location:** `SOFTWARE\Microsoft\Windows\CurrentVersion\OEMInformation`
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
from Registry import Registry
|
|
86
|
+
|
|
87
|
+
reg = Registry.Registry("SOFTWARE")
|
|
88
|
+
key = reg.open("Microsoft\\Windows\\CurrentVersion\\OEMInformation")
|
|
89
|
+
for val in key.values():
|
|
90
|
+
print(f"{val.name()}: {val.value()}")
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Malware indicator:** Modified `SupportURL` pointing to C2.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## SAM Database Analysis
|
|
98
|
+
|
|
99
|
+
**Required files:**
|
|
100
|
+
- `Windows/System32/config/SAM` - Password hashes
|
|
101
|
+
- `Windows/System32/config/SYSTEM` - Boot key
|
|
102
|
+
|
|
103
|
+
**Extract hashes with impacket:**
|
|
104
|
+
```python
|
|
105
|
+
from impacket.examples.secretsdump import LocalOperations, SAMHashes
|
|
106
|
+
|
|
107
|
+
localOps = LocalOperations('SYSTEM')
|
|
108
|
+
bootKey = localOps.getBootKey()
|
|
109
|
+
sam = SAMHashes('SAM', bootKey)
|
|
110
|
+
sam.dump() # username:RID:LM:NTLM:::
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Verify/Crack NTLM:**
|
|
114
|
+
```python
|
|
115
|
+
from Crypto.Hash import MD4
|
|
116
|
+
|
|
117
|
+
def ntlm_hash(password):
|
|
118
|
+
h = MD4.new()
|
|
119
|
+
h.update(password.encode('utf-16-le'))
|
|
120
|
+
return h.hexdigest()
|
|
121
|
+
|
|
122
|
+
# Crack with hashcat
|
|
123
|
+
# hashcat -m 1000 hashes.txt wordlist.txt
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Common RIDs:**
|
|
127
|
+
- 500 = Administrator
|
|
128
|
+
- 501 = Guest
|
|
129
|
+
- 1000+ = User accounts
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Recycle Bin Forensics
|
|
134
|
+
|
|
135
|
+
**Location:** `$Recycle.Bin\<SID>\`
|
|
136
|
+
|
|
137
|
+
**File structure:**
|
|
138
|
+
- `$R<random>.<ext>` - Actual deleted content
|
|
139
|
+
- `$I<random>.<ext>` - Metadata (original path, timestamp)
|
|
140
|
+
|
|
141
|
+
**Parse $I metadata:**
|
|
142
|
+
```python
|
|
143
|
+
# strings shows original path
|
|
144
|
+
# C.:.\.U.s.e.r.s.\.U.s.e.r.4.\.D.o.c.u.m.e.n.t.s.\.file.docx
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Hex-encoded flag fragments:**
|
|
148
|
+
```bash
|
|
149
|
+
cat '$R_InternSecret.txt'
|
|
150
|
+
# Output: 4B4354467B72656330...
|
|
151
|
+
echo "4B4354467B72656330..." | xxd -r -p
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Browser History
|
|
157
|
+
|
|
158
|
+
**Edge/Chrome (SQLite):**
|
|
159
|
+
```python
|
|
160
|
+
import sqlite3
|
|
161
|
+
|
|
162
|
+
history = "Users/<user>/AppData/Local/Microsoft/Edge/User Data/Default/History"
|
|
163
|
+
conn = sqlite3.connect(history)
|
|
164
|
+
cur = conn.cursor()
|
|
165
|
+
cur.execute("SELECT url, title FROM urls ORDER BY last_visit_time DESC")
|
|
166
|
+
for url, title in cur.fetchall():
|
|
167
|
+
print(f"{title}: {url}")
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Windows Telemetry (imprbeacons.dat)
|
|
173
|
+
|
|
174
|
+
**Location:** `Users/<user>/AppData/Local/Packages/Microsoft.Windows.ContentDeliveryManager_*/LocalState/`
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
strings imprbeacons.dat | tr '&' '\n' | grep -E "CIP|geo_|COUNTRY"
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
**Key fields:** `CIP` (client IP), `geo_lat/long`, `COUNTRY`, `SMBIOSDM`
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Hosts File Hidden Data
|
|
185
|
+
|
|
186
|
+
**Location:** `Windows/System32/drivers/etc/hosts`
|
|
187
|
+
|
|
188
|
+
Attackers hide data with excessive whitespace:
|
|
189
|
+
```bash
|
|
190
|
+
# Detect hidden content
|
|
191
|
+
xxd hosts | tail -20
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Contact Files (.contact)
|
|
197
|
+
|
|
198
|
+
**Location:** `Users/<user>/Contacts/*.contact`
|
|
199
|
+
|
|
200
|
+
**Hidden data in Notes:**
|
|
201
|
+
```xml
|
|
202
|
+
<c:Notes>h1dden_c0ntr4ct5</c:Notes>
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## WinZip AES Encrypted Archives
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
# Extract hash
|
|
211
|
+
zip2john encrypted.zip > zip_hash.txt
|
|
212
|
+
|
|
213
|
+
# Crack with hashcat (mode 13600)
|
|
214
|
+
hashcat -m 13600 zip_hash.txt wordlist.txt
|
|
215
|
+
|
|
216
|
+
# Hybrid: word + 4 digits
|
|
217
|
+
hashcat -m 13600 zip_hash.txt wordlist.txt -a 6 '?d?d?d?d'
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## NTFS Alternate Data Streams
|
|
223
|
+
|
|
224
|
+
**Pattern:** NTFS supports multiple data streams per file. The default stream stores normal file content, but additional named streams (Alternate Data Streams / ADS) can hide arbitrary data invisibly. `dir`, Explorer, and most tools only show the default stream.
|
|
225
|
+
|
|
226
|
+
**Detection and enumeration:**
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
# On a mounted NTFS volume (Linux):
|
|
230
|
+
getfattr -R -n ntfs.streams.list /mnt/ntfs/ # List all streams on all files
|
|
231
|
+
|
|
232
|
+
# Using Sleuth Kit on a raw NTFS image (best for forensics):
|
|
233
|
+
fls -r ntfs_image.dd # Recursive file listing
|
|
234
|
+
fls -r ntfs_image.dd | grep -i ":" # ADS entries contain ":"
|
|
235
|
+
# Output: r/r 66-128-4: Documents/credentials.txt:hidden_flag.jpg
|
|
236
|
+
|
|
237
|
+
# Extract ADS by inode — find inode first:
|
|
238
|
+
istat ntfs_image.dd 66 # Show all attributes for inode 66
|
|
239
|
+
# Look for $DATA attributes with names (e.g., $DATA "hidden_flag.jpg")
|
|
240
|
+
|
|
241
|
+
icat ntfs_image.dd 66-128-4 > hidden_flag.jpg # Extract ADS by full address
|
|
242
|
+
|
|
243
|
+
# Using ntfsstreams (part of ntfs-3g):
|
|
244
|
+
ntfs_streams_list /dev/sda1
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**On Windows (live analysis):**
|
|
248
|
+
|
|
249
|
+
```powershell
|
|
250
|
+
# List ADS on a file
|
|
251
|
+
Get-Item -Path C:\file.txt -Stream *
|
|
252
|
+
|
|
253
|
+
# Read ADS content
|
|
254
|
+
Get-Content -Path C:\file.txt -Stream hidden_data
|
|
255
|
+
|
|
256
|
+
# dir /r shows ADS (Windows Vista+)
|
|
257
|
+
dir /r C:\Users\suspect\Documents\
|
|
258
|
+
|
|
259
|
+
# Common ADS names to check:
|
|
260
|
+
# Zone.Identifier — marks files downloaded from the internet
|
|
261
|
+
# (contains ZoneId, ReferrerUrl, HostUrl)
|
|
262
|
+
Get-Content -Path C:\file.exe -Stream Zone.Identifier
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**Python extraction from raw NTFS image:**
|
|
266
|
+
|
|
267
|
+
```python
|
|
268
|
+
# Using pytsk3 (Python bindings for Sleuth Kit)
|
|
269
|
+
import pytsk3
|
|
270
|
+
|
|
271
|
+
img = pytsk3.Img_Info("ntfs_image.dd")
|
|
272
|
+
fs = pytsk3.FS_Info(img)
|
|
273
|
+
|
|
274
|
+
# Walk all files and check for ADS
|
|
275
|
+
for entry in fs.open_dir("/"):
|
|
276
|
+
for attr in entry:
|
|
277
|
+
if attr.info.type == pytsk3.TSK_FS_ATTR_TYPE_NTFS_DATA:
|
|
278
|
+
name = attr.info.name or "(default)"
|
|
279
|
+
if name != "(default)":
|
|
280
|
+
print(f"ADS found: {entry.info.name.name}/{name} "
|
|
281
|
+
f"(size: {attr.info.size})")
|
|
282
|
+
# Read ADS content
|
|
283
|
+
data = entry.read_random(0, attr.info.size, attr.info.type, attr.info.id)
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**Key insight:** ADS are invisible to `dir` (without `/r`), Explorer, and most forensic tools that only check default data streams. The Sleuth Kit's `fls` with the colon notation (`inode-type-id`) is the most reliable way to enumerate and extract ADS from images. Malware uses ADS to hide payloads; CTF challenges use them to hide flags. The `Zone.Identifier` stream is the most common ADS — it's automatically added by browsers and email clients to downloaded files.
|
|
287
|
+
|
|
288
|
+
**When to recognize:** Challenge provides an NTFS image, mentions "hidden data", "hidden in plain sight", or "alternate streams". Credentials files or documents that seem too simple may have ADS attached. Always run `fls -r image.dd | grep ":"` on any NTFS forensics challenge.
|
|
289
|
+
|
|
290
|
+
**References:** Google CTF 2019 "Home Computer", TCP1P CTF 2023 "hide and split", De1CTF 2019 "DeeplnReal"
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## NTFS MFT Analysis
|
|
295
|
+
|
|
296
|
+
**Location:** `C:\$MFT` (Master File Table)
|
|
297
|
+
|
|
298
|
+
**Key techniques:**
|
|
299
|
+
- Filenames are stored in UTF-16LE in the MFT
|
|
300
|
+
- Each file has two timestamp sets: `$STANDARD_INFORMATION` (user-modifiable) and `$FILE_NAME` (system-controlled)
|
|
301
|
+
- Timestomping detection: Compare SI vs FN timestamps; if SI dates are much older than FN dates, the file was timestomped
|
|
302
|
+
|
|
303
|
+
```python
|
|
304
|
+
# Search MFT for filenames (binary file, use strings)
|
|
305
|
+
# ASCII:
|
|
306
|
+
# strings $MFT | grep -i "suspicious"
|
|
307
|
+
# UTF-16LE:
|
|
308
|
+
# strings -el $MFT | grep -i "suspicious"
|
|
309
|
+
|
|
310
|
+
# MFT record structure (1024 bytes each, starting at offset 0):
|
|
311
|
+
# - Offset 0x00: "FILE" signature
|
|
312
|
+
# - Attribute 0x30 ($FILE_NAME): Contains FN timestamps (reliable)
|
|
313
|
+
# - Attribute 0x10 ($STANDARD_INFORMATION): Contains SI timestamps (modifiable)
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## USN Journal ($J) Analysis
|
|
319
|
+
|
|
320
|
+
**Location:** `C:\$Extend\$J` (Update Sequence Number Journal)
|
|
321
|
+
|
|
322
|
+
Tracks all file system changes. Critical when event logs are cleared.
|
|
323
|
+
|
|
324
|
+
```python
|
|
325
|
+
import struct, datetime
|
|
326
|
+
|
|
327
|
+
def parse_usn_record(data, offset):
|
|
328
|
+
"""Parse USN_RECORD_V2 at given offset"""
|
|
329
|
+
rec_len = struct.unpack_from('<I', data, offset)[0]
|
|
330
|
+
major = struct.unpack_from('<H', data, offset + 4)[0] # Must be 2
|
|
331
|
+
file_ref = struct.unpack_from('<Q', data, offset + 8)[0] & 0xFFFFFFFFFFFF
|
|
332
|
+
parent_ref = struct.unpack_from('<Q', data, offset + 16)[0] & 0xFFFFFFFFFFFF
|
|
333
|
+
timestamp = struct.unpack_from('<Q', data, offset + 32)[0]
|
|
334
|
+
reason = struct.unpack_from('<I', data, offset + 40)[0]
|
|
335
|
+
file_attr = struct.unpack_from('<I', data, offset + 52)[0]
|
|
336
|
+
fn_len = struct.unpack_from('<H', data, offset + 56)[0]
|
|
337
|
+
fn_off = struct.unpack_from('<H', data, offset + 58)[0] # Usually 60
|
|
338
|
+
filename = data[offset + fn_off:offset + fn_off + fn_len].decode('utf-16-le')
|
|
339
|
+
dt = datetime.datetime(1601, 1, 1) + datetime.timedelta(microseconds=timestamp // 10)
|
|
340
|
+
return dt, filename, reason, file_attr, parent_ref
|
|
341
|
+
|
|
342
|
+
# USN Reason flags:
|
|
343
|
+
# 0x1=DATA_OVERWRITE, 0x2=DATA_EXTEND, 0x4=DATA_TRUNCATION
|
|
344
|
+
# 0x100=FILE_CREATE, 0x200=FILE_DELETE, 0x1000=NAMED_DATA_OVERWRITE
|
|
345
|
+
# 0x80000000=CLOSE
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
**Key forensic uses:**
|
|
349
|
+
- Find file creation/deletion times even when logs are cleared
|
|
350
|
+
- Track wmiexec.py output files (`__<timestamp>.<random>`)
|
|
351
|
+
- Determine when PowerShell history was written (timeline of commands)
|
|
352
|
+
- Detect user profile creation (first interactive login time)
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## SAM Account Creation Timing
|
|
357
|
+
|
|
358
|
+
When Security event logs (EventID 4720) are cleared, determine account creation time from the SAM registry:
|
|
359
|
+
|
|
360
|
+
```python
|
|
361
|
+
from regipy.registry import RegistryHive
|
|
362
|
+
|
|
363
|
+
sam = RegistryHive('SAM')
|
|
364
|
+
# Navigate to: SAM\Domains\Account\Users\Names\<username>
|
|
365
|
+
# The key's last_modified timestamp = account creation time
|
|
366
|
+
names_key = sam.get_key('SAM\\Domains\\Account\\Users\\Names')
|
|
367
|
+
for subkey in names_key.iter_subkeys():
|
|
368
|
+
print(f"{subkey.name}: created {subkey.header.last_modified}")
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## Impacket wmiexec.py Artifacts
|
|
374
|
+
|
|
375
|
+
**wmiexec.py** is a popular remote command execution tool using WMI. Key artifacts:
|
|
376
|
+
|
|
377
|
+
1. **Output files:** Creates `__<unix_timestamp>.<random>` in `C:\Windows\` (ADMIN$ share)
|
|
378
|
+
- File is created, written with command output, read back, then deleted
|
|
379
|
+
- Each command execution creates a new cycle
|
|
380
|
+
- USN journal preserves create/delete timestamps even after file deletion
|
|
381
|
+
|
|
382
|
+
2. **WMI Provider Host:** `WMIPRVSE.EXE` prefetch file confirms WMI usage
|
|
383
|
+
|
|
384
|
+
3. **Timeline reconstruction:** Count USN create-delete cycles for the output file to determine number of commands executed
|
|
385
|
+
|
|
386
|
+
```python
|
|
387
|
+
# Search for wmiexec output files in MFT
|
|
388
|
+
# strings -el $MFT | grep -E '^__[0-9]{10}'
|
|
389
|
+
# The unix timestamp in the filename = approximate execution start time
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
## PowerShell History as Timeline
|
|
395
|
+
|
|
396
|
+
**Location:** `C:\Users\<user>\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txt`
|
|
397
|
+
|
|
398
|
+
PSReadLine writes commands incrementally. **USN journal DATA_EXTEND events on this file correspond to individual command executions:**
|
|
399
|
+
|
|
400
|
+
```text
|
|
401
|
+
08:05:19 - FILE_CREATE + DATA_EXTEND → First command entered
|
|
402
|
+
08:05:50 - DATA_EXTEND → Second command entered
|
|
403
|
+
08:09:57 - DATA_EXTEND → Third command entered
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
This provides exact execution timestamps for each command even when PowerShell logs are cleared.
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
## User Profile Creation as First Login Indicator
|
|
411
|
+
|
|
412
|
+
When event logs are cleared, the user profile directory creation in USN journal reveals the first interactive login:
|
|
413
|
+
|
|
414
|
+
```python
|
|
415
|
+
# Search USN journal for username directory creation
|
|
416
|
+
# Reason flag 0x100 (FILE_CREATE) with parent ref matching C:\Users (MFT ref 512)
|
|
417
|
+
# Example: ithelper DIR FILE_CREATE parent=512 at 08:03:51
|
|
418
|
+
# → First login (RDP/console) was at approximately 08:03
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
**Key insight:** User profiles are only created on first interactive logon (RDP or console), not via WMI/wmiexec remote execution.
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
## RDP Session Event IDs
|
|
426
|
+
|
|
427
|
+
**TerminalServices-LocalSessionManager\Operational:**
|
|
428
|
+
|
|
429
|
+
| Event ID | Description |
|
|
430
|
+
|----------|-------------|
|
|
431
|
+
| 21 | Session logon succeeded |
|
|
432
|
+
| 22 | Shell start notification received |
|
|
433
|
+
| 23 | Session logoff succeeded |
|
|
434
|
+
| 24 | Session disconnected |
|
|
435
|
+
| 25 | Session reconnection succeeded |
|
|
436
|
+
| 40 | Session created |
|
|
437
|
+
| 41 | Session begin (user notification) |
|
|
438
|
+
| 42 | Shell start (user notification) |
|
|
439
|
+
|
|
440
|
+
**TerminalServices-RemoteConnectionManager\Operational:**
|
|
441
|
+
|
|
442
|
+
| Event ID | Description |
|
|
443
|
+
|----------|-------------|
|
|
444
|
+
| 261 | Listener received connection |
|
|
445
|
+
| 1149 | RDP user authentication succeeded (contains source IP) |
|
|
446
|
+
|
|
447
|
+
**RemoteDesktopServices-RdpCoreTS\Operational:**
|
|
448
|
+
|
|
449
|
+
| Event ID | Description |
|
|
450
|
+
|----------|-------------|
|
|
451
|
+
| 131 | Connection accepted (TCP, contains ClientIP:port) |
|
|
452
|
+
| 102 | Connection from client |
|
|
453
|
+
| 103 | Disconnected (check ReasonCode) |
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
## Windows Defender MPLog Analysis
|
|
458
|
+
|
|
459
|
+
**Location:** `C:\ProgramData\Microsoft\Windows Defender\Support\MPLog-*.log`
|
|
460
|
+
|
|
461
|
+
Rich source of threat detection timeline, even when other logs are cleared:
|
|
462
|
+
|
|
463
|
+
```bash
|
|
464
|
+
# Find threat detections
|
|
465
|
+
grep -i "DETECTION\|THREAT\|QUARANTINE" MPLog*.log
|
|
466
|
+
|
|
467
|
+
# Find ASR (Attack Surface Reduction) rule activity
|
|
468
|
+
grep -i "ASR\|Process.*Block" MPLog*.log
|
|
469
|
+
|
|
470
|
+
# Key ASR rules (indicators of attack attempts):
|
|
471
|
+
# - "Block Process Creations originating from PSExec & WMI commands"
|
|
472
|
+
# - "Block credential stealing from lsass.exe"
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
**Detection History files:** `C:\ProgramData\Microsoft\Windows Defender\Scans\History\Service\DetectionHistory\`
|
|
476
|
+
- Binary files containing SHA256, file paths, and detection names
|
|
477
|
+
- Parse with `strings` to extract IOCs
|
|
478
|
+
|
|
479
|
+
---
|
|
480
|
+
|
|
481
|
+
## Anti-Forensics Detection Checklist
|
|
482
|
+
|
|
483
|
+
When event logs are cleared (attacker used `wevtutil cl` or `Clear-EventLog`):
|
|
484
|
+
|
|
485
|
+
1. **USN Journal** - Survives log clearing; shows file operations timeline
|
|
486
|
+
2. **SAM registry** - Account creation timestamps preserved
|
|
487
|
+
3. **PowerShell history** - ConsoleHost_history.txt often survives
|
|
488
|
+
4. **Prefetch files** - Shows executed programs (C:\Windows\Prefetch\)
|
|
489
|
+
5. **MFT** - File metadata preserved even for deleted files
|
|
490
|
+
6. **Defender MPLog** - Separate from Windows event logs, often not cleared
|
|
491
|
+
7. **RDP event logs** - TerminalServices logs are separate from Security.evtx
|
|
492
|
+
8. **WMI repository** - C:\Windows\System32\wbem\Repository\OBJECTS.DATA
|
|
493
|
+
9. **Browser history** - SQLite databases in user AppData
|
|
494
|
+
10. **Registry timestamps** - Key last_modified times reveal activity
|
|
495
|
+
|
|
496
|
+
**Security.evtx EventID 1102** = "The audit log was cleared" (ironically logged even during clearing)
|
|
497
|
+
|
|
498
|
+
---
|
|
499
|
+
|
|
500
|
+
## Windows Memory Forensics: certutil Base64 ZIP Recovery (SEC-T CTF 2017)
|
|
501
|
+
|
|
502
|
+
Volatility memory dump analysis where `psxview` reveals hidden cmd/powershell processes. A malware batch script uses `bitsadmin` to download and `certutil -decode` to base64-decode payloads. Search memory for `UEsD` (the base64 encoding of ZIP magic `PK\x03`) to find in-transit base64 archives, then decode to recover ZIP contents including registry entries.
|
|
503
|
+
|
|
504
|
+
```bash
|
|
505
|
+
# Step 1: Find hidden processes (psxview compares multiple process lists)
|
|
506
|
+
vol.py -f dump.raw --profile=Win7SP1x64 psxview
|
|
507
|
+
|
|
508
|
+
# Step 2: Dump suspicious process memory
|
|
509
|
+
vol.py -f dump.raw --profile=Win7SP1x64 procdump -p <PID> -D ./dumps/
|
|
510
|
+
|
|
511
|
+
# Step 3: Scan raw memory for base64-encoded ZIP archives
|
|
512
|
+
# UEsD = base64("PK\x03") — ZIP magic bytes encoded in base64
|
|
513
|
+
strings dump.raw | grep -o 'UEsD[A-Za-z0-9+/=]*' > candidates.txt
|
|
514
|
+
|
|
515
|
+
# Step 4: Decode each candidate
|
|
516
|
+
python3 -c "
|
|
517
|
+
import base64, sys
|
|
518
|
+
with open('candidates.txt') as f:
|
|
519
|
+
for line in f:
|
|
520
|
+
line = line.strip()
|
|
521
|
+
# Pad to valid base64 length
|
|
522
|
+
padded = line + '=' * (-len(line) % 4)
|
|
523
|
+
try:
|
|
524
|
+
data = base64.b64decode(padded)
|
|
525
|
+
if data[:4] == b'PK\x03\x04':
|
|
526
|
+
with open('recovered.zip', 'wb') as out:
|
|
527
|
+
out.write(data)
|
|
528
|
+
print('ZIP recovered')
|
|
529
|
+
break
|
|
530
|
+
except Exception:
|
|
531
|
+
pass
|
|
532
|
+
"
|
|
533
|
+
|
|
534
|
+
# Step 5: Extract ZIP contents
|
|
535
|
+
unzip recovered.zip
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
**Malware indicators to look for:**
|
|
539
|
+
- `bitsadmin /transfer` — background download without browser
|
|
540
|
+
- `certutil -decode input.b64 output.exe` — base64 decode abuse
|
|
541
|
+
- Batch files (`.bat`, `.cmd`) in unusual locations (`%TEMP%`, `%APPDATA%`)
|
|
542
|
+
- Registry exports (`.reg` files) inside ZIP payloads
|
|
543
|
+
|
|
544
|
+
**Key insight:** `certutil` is commonly abused by malware for base64 decoding as a living-off-the-land technique. `UEsD` is the base64 encoding of ZIP magic bytes `PK\x03` — use it as a memory scanning signature to find in-transit ZIP archives before they are written to disk or after they are deleted.
|
|
545
|
+
|
|
546
|
+
---
|
|
547
|
+
|
|
548
|
+
## NTFS EFSTMPWP Folder as cipher.exe Wipe Artifact (Security Fest CTF 2018)
|
|
549
|
+
|
|
550
|
+
**Pattern (Mr.reagan):** An NTFS image contains `$RECYCLE.BIN` but also a sparsely-used hidden directory named `EFSTMPWP`. This directory is created by `cipher.exe /w` — Windows' built-in tool for overwriting the free space of a volume — to hold the temporary files used for the multi-pass wipe. Its presence means the suspect ran a secure-erase command, so file recovery of deleted data is unlikely to succeed.
|
|
551
|
+
|
|
552
|
+
**Detection:**
|
|
553
|
+
```bash
|
|
554
|
+
# Mount the NTFS image read-only
|
|
555
|
+
sudo mount -o ro,loop,show_sys_files image.dd /mnt/ntfs
|
|
556
|
+
|
|
557
|
+
# Look for the wipe artifact
|
|
558
|
+
find /mnt/ntfs -maxdepth 2 -iname 'EFSTMPWP' -o -iname '$Recycle.Bin'
|
|
559
|
+
|
|
560
|
+
# MFT entry also records the directory with `cipher.exe` as the creator process
|
|
561
|
+
mft_parser -i image.dd -o mft.csv
|
|
562
|
+
grep -i 'EFSTMPWP' mft.csv
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
**Implications:**
|
|
566
|
+
- Do not waste time on carving for deleted user data in the free space; it has been overwritten.
|
|
567
|
+
- Switch focus to alternate persistence paths: `$Recycle.Bin` contents, NTFS journal ($LogFile / $UsnJrnl), Volume Shadow Copies, and MFT resident data.
|
|
568
|
+
- Check `Event Log` (`Security.evtx`, `Microsoft-Windows-Application-Experience%4Program-Inventory.evtx`) for `cipher.exe` execution timestamps — they anchor the anti-forensics timeline.
|
|
569
|
+
|
|
570
|
+
**Key insight:** Secure-erase tools leave their own filesystem fingerprints. `cipher.exe /w` creates `EFSTMPWP`; `sdelete` creates files named after the wiped target with a `.ZZZ`-style extension; BleachBit leaves `~BleachBit*.tmp`. Grep for these artifact names before launching any recovery job — they tell you whether recovery is even worth attempting.
|
|
571
|
+
|
|
572
|
+
**References:** Security Fest CTF 2018 — writeup 10206
|
|
573
|
+
|
|
574
|
+
---
|
|
575
|
+
|
|
576
|
+
## Volatility clipboard Plugin for Copy-Paste Secret Recovery (OtterCTF 2018)
|
|
577
|
+
|
|
578
|
+
**Pattern:** Users copy passwords / keys / flags into the clipboard. Windows keeps clipboard data live in memory even after the source application closes. Volatility's `clipboard` plugin enumerates `CF_UNICODETEXT` / `CF_TEXT` buffers and prints the most recent copy-paste content verbatim.
|
|
579
|
+
|
|
580
|
+
```bash
|
|
581
|
+
vol.py -f memory.vmem --profile=Win7SP1x64 clipboard
|
|
582
|
+
# Volatility 3:
|
|
583
|
+
vol -f memory.vmem windows.clipboard
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
**Key insight:** Before spending hours carving LSASS or walking process heaps, run `clipboard` — CTF challenges about "Silly Rick copied his password" always surface here. Combine with `cmdline`, `consoles`, and `filescan` for full user-activity reconstruction.
|
|
587
|
+
|
|
588
|
+
**References:** OtterCTF 2018 — Silly Rick, writeup 12596
|
|
589
|
+
|
|
590
|
+
---
|
|
591
|
+
|
|
592
|
+
## Volatility Credential Recovery Toolkit (OtterCTF 2018)
|
|
593
|
+
|
|
594
|
+
**Pattern:** One memory dump, a shopping list of Volatility plugins to try in order:
|
|
595
|
+
|
|
596
|
+
```bash
|
|
597
|
+
# 1. Recent copy-pasted passwords
|
|
598
|
+
vol.py -f dump.vmem --profile=Win7SP1x64 clipboard
|
|
599
|
+
|
|
600
|
+
# 2. Loaded plugins: mimikatz (third-party) — plaintext wdigest creds
|
|
601
|
+
vol.py --plugins=./plugin/ -f dump.vmem --profile=Win7SP1x64 mimikatz
|
|
602
|
+
|
|
603
|
+
# 3. NTLM / LM hashes from SAM hive
|
|
604
|
+
vol.py -f dump.vmem --profile=Win7SP1x64 hivelist # find SAM offset
|
|
605
|
+
vol.py -f dump.vmem --profile=Win7SP1x64 hashdump -y SYSTEM_off -s SAM_off
|
|
606
|
+
|
|
607
|
+
# 4. Registry values (computer name, policies)
|
|
608
|
+
vol.py -f dump.vmem --profile=Win7SP1x64 printkey \
|
|
609
|
+
-K 'ControlSet001\Control\ComputerName\ComputerName'
|
|
610
|
+
|
|
611
|
+
# 5. Process memory carving: dump and grep for patterns
|
|
612
|
+
vol.py -f dump.vmem --profile=Win7SP1x64 memdump -p 3720 -D out/
|
|
613
|
+
strings out/3720.dmp | grep -iE 'pass|flag'
|
|
614
|
+
|
|
615
|
+
# 6. Network connection artifacts
|
|
616
|
+
vol.py -f dump.vmem --profile=Win7SP1x64 netscan
|
|
617
|
+
|
|
618
|
+
# 7. Process tree and loaded DLLs for malware triage
|
|
619
|
+
vol.py -f dump.vmem --profile=Win7SP1x64 pstree
|
|
620
|
+
vol.py -f dump.vmem --profile=Win7SP1x64 dlllist -p PID
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
**Key insight:** Don't hunt with `strings` alone. The Volatility plugin suite has a plugin for every artifact: clipboard, mimikatz (plaintext), hashdump (hashes), printkey (registry), memdump (per-process memory), netscan (sockets), pstree (process hierarchy), dlllist (loaded modules). Run them in order from cheapest to most expensive.
|
|
624
|
+
|
|
625
|
+
**References:** OtterCTF 2018 — multiple challenges, writeups 12569–12572, 12596
|