{"uuid": "fc0fffa6-3cfe-4557-b876-474783da9463", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2017-11882", "type": "seen", "source": "https://gist.github.com/bbrk364/d58600b6c87aa8873c8ea55be27029ca", "content": "# **Cyber Forensics Expert \u2013 Complete Professional Edition**\n\nThis Guide is written for a **deep technical reference + practical lab manual + legal guide**, suitable for advanced learners and professionals.\n\n---\n\n# PART I \u2013 FOUNDATIONS OF CYBER FORENSICS \n\n---\n\n## **Chapter 1 \u2013 Introduction to Cyber Forensics**\n\n### 1.1 Evolution of Digital Forensics\n\n* Early computer crime investigations\n* Rise of internet crimes\n* Modern cyber threat landscape\n* Impact of ransomware &amp; APT groups\n\n### 1.2 Types of Digital Forensics\n\n* Computer forensics\n* Network forensics\n* Mobile forensics\n* Cloud forensics\n* Memory forensics\n* Database forensics\n\n### 1.3 Cybercrime Categories\n\n* Financial fraud\n* Insider threats\n* Cyber terrorism\n* Child exploitation investigations\n* Intellectual property theft\n\n### 1.4 Legal &amp; Regulatory Frameworks\n\n* Digital evidence laws\n* Search and seizure procedures\n* Jurisdiction challenges\n* International cooperation (MLAT)\n* Privacy regulations (GDPR concepts)\n\n### 1.5 Chain of Custody Deep Dive\n\n* Documentation standards\n* Evidence tracking systems\n* Courtroom challenges\n* Real case failure examples\n\n---\n\n## **Chapter 2 \u2013 Computer Architecture &amp; Storage Internals**\n\n### 2.1 CPU Architecture &amp; Registers\n\n### 2.2 Memory Hierarchy\n\n### 2.3 Storage Media Types\n\n* HDD magnetic structure\n* SSD NAND flash structure\n* Wear leveling &amp; forensic impact\n\n### 2.4 Disk Partitioning Systems\n\n* MBR internals\n* GPT internals\n* Hidden partitions\n\n### 2.5 File Systems Deep Analysis\n\n* FAT32 structure\n* NTFS deep internals\n\n  * MFT structure\n  * $LogFile\n  * $UsnJrnl\n* EXT4 journal system\n* APFS snapshots\n\n### 2.6 RAID Forensics\n\n* RAID 0, 1, 5, 6, 10 reconstruction\n* Data carving from RAID\n\n---\n\n## **Chapter 3 \u2013 Operating System Artifacts *\n\n### 3.1 Windows Internals\n\n* Boot process\n* Registry hive structure\n* System32 artifacts\n* Event logs deep dive\n\n### 3.2 Linux Internals\n\n* Init systems (systemd)\n* /proc filesystem\n* Authentication logs\n\n### 3.3 macOS Internals\n\n* Unified logs\n* Spotlight artifacts\n* Time Machine backups\n\n### 3.4 Timeline Analysis\n\n* Super timeline creation\n* Correlation of multi-source logs\n\n---\n\n# PART II \u2013 FORENSIC METHODOLOGY &amp; ACQUISITION \n\n---\n\n## **Chapter 4 \u2013 Incident Response &amp; Evidence Handling**\n\n### 4.1 First Responder Protocol\n\n### 4.2 Live vs Dead Analysis\n\n### 4.3 Volatile Data Collection\n\n### 4.4 Forensic Imaging Techniques\n\n* Bit-by-bit imaging\n* Logical imaging\n* Network acquisition\n\n### 4.5 Hashing Algorithms\n\n* MD5 weaknesses\n* SHA family\n* Collision risks\n\n### 4.6 Documentation &amp; Reporting Standards\n\n---\n\n## **Chapter 5 \u2013 Forensic Tools &amp; Lab Setup**\n\n### 5.1 Building a Forensic Lab\n\n* Hardware requirements\n* Write blockers\n* Faraday bags\n\n### 5.2 Commercial Tools\n\n* EnCase deep workflow\n* FTK workflow\n\n### 5.3 Open Source Tools\n\n* Autopsy\n* Sleuth Kit\n* Volatility\n* Plaso\n\n### 5.4 Automation &amp; Scripting\n\n* Python for forensics\n* PowerShell artifact extraction\n\n---\n\n# PART III \u2013 DISK &amp; FILE SYSTEM FORENSICS\n\n---\n\n## **Chapter 6 \u2013 NTFS &amp; Windows Artifact Forensics**\n\n* MFT forensic parsing\n* Prefetch analysis\n* Shimcache\n* Amcache\n* LNK artifacts\n* Jump lists\n* USB device history\n* Recycle Bin forensics\n* Browser forensics (Chrome, Firefox, Edge)\n\n---\n\n## **Chapter 7 \u2013 Linux &amp; macOS Forensics**\n\n* Bash history recovery\n* Cron persistence detection\n* Log tampering detection\n* macOS artifact deep dive\n* APFS snapshot recovery\n\n---\n\n## **Chapter 8 \u2013 Data Recovery &amp; Carving**\n\n* Deleted file recovery\n* Signature-based carving\n* Entropy analysis\n* Hidden data detection\n* Slack space analysis\n\n---\n\n# PART IV \u2013 MEMORY &amp; MALWARE FORENSICS\n\n---\n\n## **Chapter 9 \u2013 Memory Forensics**\n\n* Memory acquisition techniques\n* Process enumeration\n* DLL injection detection\n* Rootkit detection\n* Network artifact extraction\n* Volatility deep modules\n\n---\n\n## **Chapter 10 \u2013 Malware Forensics**\n\n* Static analysis workflow\n* PE file structure\n* Packers &amp; obfuscation\n* Dynamic sandbox analysis\n* Reverse engineering basics\n* YARA detection rules\n* IOC development\n\n---\n\n# PART V \u2013 NETWORK &amp; CLOUD FORENSICS \n\n---\n\n## **Chapter 11 \u2013 Network Forensics**\n\n* TCP/IP packet dissection\n* PCAP analysis methodology\n* DNS tunneling detection\n* IDS log correlation\n* NetFlow analysis\n* Timeline reconstruction\n\n---\n\n## **Chapter 12 \u2013 Cloud &amp; Virtualization Forensics**\n\n* AWS log analysis\n* Azure monitoring logs\n* Google Cloud audit logs\n* Virtual machine artifacts\n* Container forensics\n* Kubernetes investigation workflow\n\n---\n\n# PART VI \u2013 MOBILE, IoT &amp; EMERGING TECH \n\n---\n\n## **Chapter 13 \u2013 Mobile Forensics**\n\n* Android file system\n* iOS acquisition\n* App artifact extraction\n* Encrypted device challenges\n* Messaging app investigations\n\n---\n\n## **Chapter 14 \u2013 IoT &amp; Embedded Forensics**\n\n* Firmware extraction\n* Chip-off techniques\n* Smart home device analysis\n* Drone investigations\n\n---\n\n# PART VII \u2013 ADVANCED TOPICS \n\n---\n\n## **Chapter 15 \u2013 Anti-Forensics &amp; Evasion**\n\n* Data wiping methods\n* Encryption bypass concepts\n* Steganography detection\n* Log tampering detection\n* Timestomping detection\n\n---\n\n## **Chapter 16 \u2013 Cryptocurrency &amp; Dark Web Forensics**\n\n* Bitcoin transaction tracing\n* Wallet artifact analysis\n* Blockchain analytics tools\n* Dark web marketplace investigations\n* OSINT correlation\n\n---\n\n# PART VIII \u2013 LEGAL, REPORTING &amp; CAREER (80\u2013120 pages)\n\n---\n\n## **Chapter 17 \u2013 Writing Professional Forensic Reports**\n\n* Executive summary\n* Technical findings\n* Evidence referencing\n* Court admissibility\n* Expert witness preparation\n\n---\n\n## **Chapter 18 \u2013 Real-World Case Studies**\n\n* Ransomware case\n* Insider data theft\n* Financial fraud investigation\n* APT intrusion analysis\n* Timeline reconstruction case\n\n---\n\n# APPENDICES \n* Forensic command reference\n* Artifact cheat sheets\n* Sample forensic report\n* Lab exercises\n* Practice scenarios\n* Glossary\n\n---\n\n# PART I \u2013 FOUNDATIONS OF CYBER FORENSICS\n\n---\n\n## Chapter 1 \u2013 Introduction to Cyber Forensics\n\n---\n\n### 1.1 Evolution of Digital Forensics\n\n#### The Dawn of Digital Crime (1940s-1970s)\n\nThe history of digital forensics begins not with computers as we know them today, but with mainframe systems that occupied entire rooms. In 1946, when ENIAC (Electronic Numerical Integrator and Computer) was unveiled, no one could have imagined that these massive calculating machines would one day become tools for criminal activity.\n\n**Key Milestone:** The first documented computer crime occurred in 1973 when a bank teller at a New York bank used a computer to embezzle over $1.5 million. The teller exploited the bank's systems to modify account balances, demonstrating that computers could be both targets and tools for criminal activity.\n\n**Fact Note:** During this era, \"digital forensics\" didn't exist as a concept. When computer-related crimes occurred, investigators treated them as traditional crimes with a computer component, often lacking specialized knowledge to properly examine digital evidence.\n\n#### The Personal Computer Revolution (1980s)\n\nThe introduction of the IBM PC in 1981 and Apple's Macintosh in 1984 brought computing power into homes and small businesses. With this democratization of technology came new forms of crime.\n\n**1984 \u2013 The Birth of Formal Digital Forensics:** The FBI launched the Magnetic Media Program, marking the first formal government initiative dedicated to examining computer evidence. This program would later evolve into the Computer Analysis and Response Team (CART).\n\n**1987 \u2013 First Forensic Tools:** The IRS Criminal Investigation Division began developing forensic tools to examine computer evidence. These early tools were primitive by today's standards, often involving simple disk utilities and hex editors.\n\n&gt; **Side Note:** Early investigators would often boot suspect computers and examine files using the operating system's native tools. This practice, we now know, modifies critical evidence \u2013 a lesson learned through painful courtroom experiences.\n\n#### The Internet Era (1990s)\n\nThe commercialization of the internet in the mid-1990s transformed digital forensics forever. Suddenly, evidence wasn't confined to a single computer \u2013 it could span continents.\n\n**1995 \u2013 The Birth of Commercial Tools:** ASR Data developed Expert Witness for Macintosh, which would later become EnCase. This marked the transition from custom scripts to commercial forensic platforms.\n\n**1998 \u2013 Network Forensics Emerges:** The first distributed denial-of-service attacks forced investigators to understand network traffic analysis. The concept of \"packet-level\" investigation became essential.\n\n**Forensic Challenge of the Era:** Investigators struggled with increasing storage capacities. When hard drives grew from 10MB to 1GB, the time required for examination grew exponentially, creating backlogs that could last months.\n\n#### Modern Cyber Threat Landscape (2000-Present)\n\nThe 21st century brought unprecedented challenges:\n\n**2000-2005:**\n- Email becomes primary evidence source in corporate litigation\n- First mobile phone forensics tools emerge\n- Windows XP dominance creates standardization in artifact locations\n\n**2006-2010:**\n- Rise of encryption (BitLocker, FileVault)\n- Social media platforms become evidence goldmines\n- Cloud computing complicates jurisdiction\n\n**2011-2015:**\n- Smartphone penetration exceeds 50% globally\n- BYOD (Bring Your Own Device) policies create forensic nightmares\n- First major APT (Advanced Persistent Threat) investigations\n\n**2016-2020:**\n- Ransomware epidemic demands rapid response capabilities\n- IoT devices become evidence sources (smart homes, wearables)\n- Cloud forensics matures as a discipline\n\n**2021-Present:**\n- AI-generated content challenges evidence authenticity\n- Encrypted by default (mobile devices, messaging apps)\n- Quantum computing threatens current encryption standards\n\n#### The Impact of Ransomware &amp; APT Groups\n\n**Ransomware Evolution:**\n\n```mermaid\ngraph LR\n    A[1989: AIDS TrojanFirst ransomware] --&gt; B[2005: ArchiveusPassword-protected files]\n    B --&gt; C[2013: CryptoLockerStrong encryption]\n    C --&gt; D[2017: WannaCryWorm capabilities]\n    D --&gt; E[2020: Ransomware-as-a-ServiceDouble extortion]\n```\n\nModern ransomware investigations require examiners to:\n- Identify initial access vector (phishing, RDP brute force, vulnerability)\n- Trace lateral movement through networks\n- Recover encrypted files where possible\n- Analyze ransom notes for negotiation artifacts\n- Trace cryptocurrency payments\n\n**APT Group Characteristics:**\n\n| APT Group | Region | Primary Targets | Notable Techniques |\n|-----------|--------|-----------------|---------------------|\n| APT29 (Cozy Bear) | Russia | Government, think tanks | Watering holes, supply chain |\n| APT38 (Lazarus) | North Korea | Financial institutions | Swift system compromise |\n| APT3 (Gothic Panda) | China | Defense, aerospace | Zero-day exploitation |\n| FIN7 | Criminal | Retail, hospitality | Memory-only malware |\n\n---\n\n### 1.2 Types of Digital Forensics\n\n#### Computer Forensics\n\nComputer forensics focuses on examination of persistent storage media (hard drives, SSDs) and the operating systems that manage them. This is the foundation upon which all other forensic disciplines are built.\n\n**Scope of Examination:**\n- User-created files (documents, images, emails)\n- System artifacts (logs, registry, prefetch)\n- Deleted data recovery\n- Timeline reconstruction\n- Application analysis\n\n**Typical Investigation Workflow:**\n```\nEvidence Identification \u2192 Preservation \u2192 Acquisition \u2192 Examination \u2192 Analysis \u2192 Reporting\n```\n\n#### Network Forensics\n\nNetwork forensics involves monitoring, capturing, and analyzing network traffic to identify security incidents, gather evidence, and reconstruct events.\n\n**Key Data Sources:**\n- Full packet captures (PCAP files)\n- NetFlow/sFlow records\n- Firewall logs\n- IDS/IPS alerts\n- Proxy server logs\n- DHCP server logs\n\n**Real-World Application:** When investigating a data breach, network forensics can reveal:\n- When the initial compromise occurred (beaconing traffic)\n- What data was exfiltrated (file transfers)\n- Command and control communication patterns\n- Lateral movement between systems\n\n&gt; **Important Note:** Unlike computer forensics, network forensics often deals with volatile evidence that may only exist for milliseconds. This requires continuous monitoring and capture capabilities.\n\n#### Mobile Forensics\n\nMobile devices present unique challenges due to their integrated nature \u2013 they combine computing, communication, and sensing capabilities in a constantly connected package.\n\n**Device Categories:**\n- Smartphones (iOS, Android)\n- Feature phones\n- Tablets\n- Wearables (smartwatches, fitness trackers)\n\n**Evidence Types Found on Mobile Devices:**\n- Call logs and contacts\n- SMS/MMS messages\n- App data (WhatsApp, Signal, Telegram)\n- Location history (GPS coordinates, WiFi networks)\n- Browser artifacts\n- Cloud-synced data\n\n**Acquisition Methods:**\n1. **Logical extraction** \u2013 File system access via APIs\n2. **File system extraction** \u2013 Full file system dump\n3. **Physical extraction** \u2013 Bit-for-bit copy of flash memory\n4. **Chip-off** \u2013 Direct memory chip reading (advanced)\n\n#### Cloud Forensics\n\nCloud forensics extends traditional digital forensics to encompass cloud computing environments, where data may be distributed across multiple jurisdictions and service models.\n\n**Service Models and Forensic Implications:**\n\n| Model | Customer Control | Provider Control | Forensic Challenges |\n|-------|------------------|-------------------|---------------------|\n| IaaS (AWS EC2) | OS, apps, data | Hypervisor, hardware | VM snapshot access |\n| PaaS (Azure SQL) | Data only | Platform, runtime | Limited log access |\n| SaaS (Office 365) | Content only | Everything | API-only evidence |\n\n**Cloud Evidence Sources:**\n- Virtual machine disk images\n- Cloud storage buckets\n- Database snapshots\n- API access logs\n- Identity provider logs\n- CDN logs\n\n**Case Example:** In a 2020 investigation of a compromised AWS environment, forensic examiners had to:\n1. Preserve EC2 instances as snapshots\n2. Analyze CloudTrail logs for API calls\n3. Examine VPC Flow Logs for network connections\n4. Review S3 access logs for data exfiltration\n\n#### Memory Forensics\n\nMemory forensics (also called live forensics) examines the volatile memory (RAM) of a running computer system. This discipline has become critical with the rise of memory-resident malware that never touches the hard drive.\n\n**What Memory Contains:**\n- Running processes and threads\n- Loaded DLLs and kernel modules\n- Network connections (including hidden ones)\n- Open files and registry keys\n- Passwords and encryption keys\n- Malware code and artifacts\n\n**Memory Acquisition Tools:**\n- Windows: FTK Imager, DumpIt, WinPmem\n- Linux: LiME, fmem\n- macOS: OSXPMem\n- Hardware: Tribble (PCI card acquisition)\n\n&gt; **Forensic Fact:** In 2015, the CARBANAK malware used memory-only techniques to avoid detection. Traditional disk forensics showed nothing, but memory analysis revealed the complete malware infrastructure.\n\n#### Database Forensics\n\nDatabase forensics focuses on examining database management systems (DBMS) and their stored data, logs, and structures for evidence of unauthorized activity.\n\n**Database Artifacts:**\n- Transaction logs\n- Audit logs\n- Stored procedures and triggers\n- Index files\n- Temporary tables\n- Query execution plans\n\n**Common Database Investigations:**\n- Data theft (SELECT * FROM customers)\n- Fraudulent transactions (unauthorized updates)\n- SQL injection attacks\n- Privilege abuse\n- Data tampering\n\n**SQL Server Forensic Example:**\n```sql\n-- Examining transaction log for deleted records\nSELECT [Current LSN], Operation, [Transaction Name], [Begin Time], [End Time]\nFROM fn_dblog(NULL, NULL)\nWHERE Operation = 'LOP_DELETE_ROWS'\nORDER BY [Current LSN] DESC;\n```\n\n---\n\n### 1.3 Cybercrime Categories\n\n#### Financial Fraud\n\nFinancial fraud encompasses a wide range of criminal activities targeting monetary assets, banking systems, and financial instruments.\n\n**Types of Financial Fraud:**\n\n1. **Payment Card Fraud**\n   - Skimming devices at ATMs/POS terminals\n   - Card-not-present fraud in e-commerce\n   - Account takeover through credential theft\n\n   *Forensic Indicators:* Unexpected transactions, geographic anomalies, pattern analysis in payment data\n\n2. **Banking Trojans**\n   - Zeus, SpyEye, TrickBot malware families\n   - Web injects modifying browser sessions\n   - Man-in-the-browser attacks\n\n   *Investigation Approach:* Memory analysis for injected code, network traffic for bot communication, disk forensics for configuration files\n\n3. **Business Email Compromise (BEC)**\n   - CEO fraud (impersonating executives)\n   - Invoice manipulation\n   - Vendor email compromise\n\n   *Case Study:* In 2019, a BEC scheme cost a media company $15 million when attackers impersonated a vendor and provided fraudulent banking details for invoice payments.\n\n**Forensic Methodology for Financial Fraud:**\n```\n1. Transaction tracing\n2. Digital evidence collection (emails, logs)\n3. Malware examination\n4. Cryptocurrency tracking (if applicable)\n5. Timeline reconstruction\n```\n\n#### Insider Threats\n\nInsider threats originate from within the organization \u2013 employees, contractors, or business partners who have authorized access to systems and data.\n\n**Insider Threat Categories:**\n\n| Type | Motivation | Indicators | Forensic Focus |\n|------|------------|------------|----------------|\n| Malicious | Financial gain, revenge | Unusual access patterns, data downloads | File access logs, USB history |\n| Negligent | Carelessness, convenience | Policy violations, misconfigurations | Security tool alerts |\n| Compromised | External coercion | Unusual login times, geolocation mismatches | Account activity analysis |\n\n**Real-World Example:** A 2020 insider threat investigation revealed a departing employee had:\n- Accessed 15,000 files in final week (normal: 200/week)\n- Connected 4 USB devices (normal: 0)\n- Emailed 200MB of data to personal account\n- Printed confidential documents after hours\n\n**Detection Techniques:**\n- User and Entity Behavior Analytics (UEBA)\n- Data Loss Prevention (DLP) alerts\n- Privileged Access Management (PAM) logs\n- Endpoint Detection and Response (EDR) data\n\n#### Cyber Terrorism\n\nCyber terrorism involves the use of digital attacks to intimidate or coerce governments or societies in pursuit of political, ideological, or religious objectives.\n\n**Critical Infrastructure Targets:**\n- Power grids and utilities\n- Transportation systems\n- Healthcare facilities\n- Financial systems\n- Government networks\n\n**Notable Incidents:**\n- **2015 Ukraine Power Grid:** Attackers caused blackouts affecting 230,000 people through SCADA system compromise\n- **2020 Israeli Water System:** Attempted chlorine level manipulation thwarted by rapid response\n- **2021 Colonial Pipeline:** Ransomware attack disrupted fuel supply across US East Coast\n\n**Forensic Challenges in Cyber Terrorism:**\n- Rapid response requirements (safety implications)\n- Multiple agency involvement (FBI, DHS, private sector)\n- Classified information handling\n- International cooperation barriers\n\n#### Child Exploitation Investigations\n\nThis sensitive area of digital forensics requires specialized training, both technical and psychological, due to the nature of the content and legal requirements.\n\n**Investigation Components:**\n1. **Peer-to-Peer Networks:** Monitoring file sharing for known contraband hashes\n2. **Hidden Services:** Dark web marketplace investigations\n3. **Social Media:** Platform cooperation for offender identification\n4. **Device Examinations:** Thorough forensic analysis of suspect devices\n\n**Technical Challenges:**\n- Encryption and anonymization tools\n- Steganography for hidden content\n- Anti-forensic techniques (file wiping, encryption)\n- Cross-jurisdiction evidence sharing\n\n&gt; **Important Ethical Note:** Forensic examiners in this field require psychological support and rotation policies to prevent burnout and trauma.\n\n#### Intellectual Property Theft\n\nIP theft involves the unauthorized acquisition of trade secrets, proprietary information, or copyrighted materials.\n\n**Common IP Targets:**\n- Source code and software\n- Product designs and specifications\n- Customer lists and pricing strategies\n- Research and development data\n- Manufacturing processes\n\n**Investigation Approaches:**\n\n*Corporate Espionage Investigation:*\n```\n- Network logs for data exfiltration\n- Email archives for unauthorized sharing\n- USB device connection logs\n- Cloud storage access records\n- Printer logs for document theft\n```\n\n**Case Study:** Waymo v. Uber (2017) involved a former engineer downloading 14,000 files containing trade secrets before joining a competitor. Forensic examination revealed:\n- External drive connections\n- Deleted file recovery\n- Cloud upload timestamps\n- Communication with competitors\n\n---\n\n### 1.4 Legal &amp; Regulatory Frameworks\n\n#### Digital Evidence Laws\n\nDigital evidence is governed by rules of evidence that vary by jurisdiction but share common principles derived from common law traditions.\n\n**Admissibility Requirements:**\n1. **Relevance** \u2013 Evidence must make a fact more or less probable\n2. **Authenticity** \u2013 Evidence must be what it purports to be\n3. **Best Evidence Rule** \u2013 Original documents preferred over copies\n4. **Hearsay Rule** \u2013 Out-of-court statements offered for truth may be excluded\n5. **Chain of Custody** \u2013 Documentation of evidence handling\n\n**US Federal Rules of Evidence (FRE):**\n\n| Rule | Content | Forensic Application |\n|------|---------|----------------------|\n| 901(a) | Authentication requirement | Proving forensic images match originals |\n| 902(14) | Self-authenticating digital evidence | Certified hash values |\n| 1001(6) | Definition of \"duplicate\" | Forensic images as duplicates |\n| 1002 | Original document requirement | Printouts may not suffice |\n\n**International Variations:**\n- **UK:** Police and Criminal Evidence Act 1984 (PACE)\n- **EU:** General Data Protection Regulation (GDPR) affects evidence collection\n- **Canada:** Canada Evidence Act\n- **Australia:** Evidence Act 1995\n\n#### Search and Seizure Procedures\n\nThe Fourth Amendment to the US Constitution (and similar provisions in other countries) protects against unreasonable searches and seizures.\n\n**Warrant Requirements for Digital Evidence:**\n1. **Particularity** \u2013 Warrant must specifically describe what can be searched\n2. **Probable Cause** \u2013 Reasonable basis for believing evidence exists\n3. **Scope Limitations** \u2013 Search limited to areas where evidence might be found\n\n**Search Protocol Example:**\n```\nWARRANT EXECUTION CHECKLIST:\n\n\u2610 Knock and announce (unless exceptions apply)\n\u2610 Secure scene and occupants\n\u2610 Identify all digital devices\n\u2610 Photograph scene before touching devices\n\u2610 Assess if devices are powered on/off\n\u2610 Document all connections\n\u2610 Consult warrant for search scope\n\u2610 Begin evidence collection\n```\n\n**Consent Searches:**\n- Voluntary consent must be obtained\n- Third-party consent limited (shared computers)\n- Consent can be withdrawn\n- Scope defined by consent given\n\n**Border Searches:**\n- Reduced Fourth Amendment protection at borders\n- Forensic examinations may require reasonable suspicion\n- Some jurisdictions require warrant for device search\n\n#### Jurisdiction Challenges\n\nDigital evidence frequently crosses jurisdictional boundaries, creating complex legal questions.\n\n**Types of Jurisdiction:**\n- **Territorial** \u2013 Where crime occurred\n- **Personal** \u2013 Over the suspect\n- **Subject Matter** \u2013 Type of case (federal vs state)\n- **Prescriptive** \u2013 Power to make laws\n- **Adjudicative** \u2013 Power to hear cases\n\n**Cloud Jurisdiction Issues:**\n```\nData stored in Ireland\nCompany headquartered in US\nUsers located worldwide\nCrime affects victims in multiple countries\n\n\u2192 Which country's laws apply?\n\u2192 Who can compel data production?\n\u2192 What privacy laws protect users?\n\u2192 How is evidence authenticated?\n```\n\n**MLAT Process (Mutual Legal Assistance Treaty):**\n1. Requesting country prepares formal request\n2. Request transmitted through diplomatic channels\n3. Requesting country's central authority reviews\n4. Evidence gathered according to local laws\n5. Evidence transmitted back to requesting country\n\n**Timeframe:** MLAT requests typically take 6-24 months \u2013 far too slow for most investigations.\n\n#### Privacy Regulations (GDPR Concepts)\n\nThe GDPR (General Data Protection Regulation) has fundamentally changed how digital evidence can be collected, processed, and transferred.\n\n**Key GDPR Principles Affecting Forensics:**\n\n1. **Lawfulness, Fairness, Transparency** \u2013 Evidence collection must have legal basis\n2. **Purpose Limitation** \u2013 Evidence can only be used for stated purpose\n3. **Data Minimization** \u2013 Collect only necessary evidence\n4. **Accuracy** \u2013 Maintain accurate evidence\n5. **Storage Limitation** \u2013 Don't keep evidence longer than needed\n6. **Security** \u2013 Protect evidence from breach\n\n**Art. 32 \u2013 Security of Processing:**\n- Encryption requirements for evidence\n- Access controls\n- Breach notification\n- Regular testing\n\n**Cross-Border Data Transfers:**\n- Adequacy decisions (countries with equivalent protection)\n- Standard Contractual Clauses (SCCs)\n- Binding Corporate Rules (BCRs)\n- Derogations for legal proceedings\n\n&gt; **Practical Impact:** When investigating a multinational company, forensic examiners must now consider whether they can legally access employee emails stored in different countries, and what privacy rights those employees have.\n\n---\n\n### 1.5 Chain of Custody Deep Dive\n\n#### Documentation Standards\n\nChain of custody refers to the chronological documentation of evidence handling from collection through presentation in court.\n\n**Essential Documentation Elements:**\n\n1. **Evidence Identifier** \u2013 Unique number/case reference\n2. **Description** \u2013 Detailed physical description\n3. **Source** \u2013 Where and when collected\n4. **Collector** \u2013 Who collected it\n5. **Date/Time** \u2013 When collected\n6. **Purpose** \u2013 Why collected\n7. **Storage** \u2013 Where stored\n8. **Transfers** \u2013 Every handoff documented\n9. **Access** \u2013 Who viewed/accessed evidence\n10. **Condition** \u2013 Evidence condition at each stage\n\n**Chain of Custody Form Example:**\n```\n\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n\u2551               CHAIN OF CUSTODY RECORD                \u2551\n\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n\u2551 Case Number: CF-2023-0042                            \u2551\n\u2551 Evidence ID: EX-001                                   \u2551\n\u2551 Description: Dell Latitude 7420 Laptop, SN: 1A2B3C   \u2551\n\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n\u2551 COLLECTED BY: Sgt. Johnson, Cyber Crimes Unit        \u2551\n\u2551 Date/Time: 2023-06-15 14:30                          \u2551\n\u2551 Location: 123 Main St, Office 4B                      \u2551\n\u2551 Condition: Powered off, connected to power           \u2551\n\u2551 Sealed in anti-static bag #AS-8923                    \u2551\n\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n\u2551 TRANSFERRED TO: Evidence Room (Cpl. Martinez)        \u2551\n\u2551 Date/Time: 2023-06-15 16:45                          \u2551\n\u2551 Purpose: Temporary storage pending forensic lab      \u2551\n\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n\u2551 TRANSFERRED TO: Forensic Lab (Dr. Williams)          \u2551\n\u2551 Date/Time: 2023-06-16 09:15                          \u2551\n\u2551 Purpose: Forensic examination                         \u2551\n\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563\n\u2551 RETURNED TO: Evidence Room (Cpl. Martinez)           \u2551\n\u2551 Date/Time: 2023-06-30 11:20                          \u2551\n\u2551 Purpose: Post-examination storage                     \u2551\n\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\n```\n\n#### Evidence Tracking Systems\n\nModern forensic labs use evidence tracking systems to maintain chain of custody electronically.\n\n**System Components:**\n- **Barcode/RFID tagging** \u2013 Physical evidence tracking\n- **Biometric access** \u2013 Who accessed evidence\n- **Audit logs** \u2013 All system actions recorded\n- **Tamper-evident packaging** \u2013 Physical security\n- **Environmental monitoring** \u2013 Temperature/humidity for sensitive evidence\n\n**RFID Tracking Implementation:**\n```\nEvidence arrives \u2192 Tag applied \u2192 Scanner records\n    \u2193\nStorage location updated in database\n    \u2193\nMovement triggers automated alerts\n    \u2193\nInventory audits performed via handheld scanners\n```\n\n**Audit Trail Requirements:**\n- Who, what, when, where, why\n- Cannot be modified or deleted\n- Redundant backup\n- Regular verification\n\n#### Courtroom Challenges\n\nChain of custody is frequently challenged in court to create reasonable doubt.\n\n**Common Defense Arguments:**\n\n1. **Gap in Documentation:**\n   - \"Your Honor, there's a 4-hour gap in the chain of custody. We don't know who had access to the evidence during this time.\"\n\n2. **Improper Storage:**\n   - \"The evidence was stored in an unsecured location accessible to unauthorized personnel.\"\n\n3. **Environmental Concerns:**\n   - \"No temperature/humidity logs exist. Electronic evidence could have been degraded.\"\n\n4. **Multiple Access:**\n   - \"Fifteen people had access to the evidence. Any of them could have tampered with it.\"\n\n5. **Copy vs. Original:**\n   - \"We're being asked to accept a forensic image, not the original evidence.\"\n\n**Prosecution Response Strategy:**\n```\n- Present complete documentation\n- Call each custodian as witness\n- Explain standard procedures\n- Demonstrate security measures\n- Address gaps with reasonable explanations\n- Show hash value verification\n```\n\n#### Real Case Failure Examples\n\n**Case 1: The Unlocked Evidence Room (2015)**\n*Location:* Midwest US State Police Lab\n\n**Situation:** Evidence from a major child exploitation investigation was stored in a room where the lock had been broken for three months. Twenty-three people had access during this period.\n\n**Result:** Defense successfully argued that evidence could have been planted. Charges against the primary suspect were dropped. The lab's entire evidence backlog had to be re-examined at a cost of $2.3 million.\n\n**Lesson Learned:** Physical security of evidence storage is non-negotiable. Broken locks must be repaired immediately, and alternative secure storage arranged in the interim.\n\n**Case 2: The Modified Forensic Image (2018)**\n*Location:* European Forensic Lab\n\n**Situation:** An examiner created a forensic image but, due to storage constraints, stored it on a network drive alongside active case files. The image was accidentally mounted and modified during routine system maintenance.\n\n**Result:** Defense produced logs showing the modification. The evidence was excluded. The case collapsed despite overwhelming other evidence.\n\n**Lesson Learned:** Forensic images must be stored on write-once media or secured systems with strict access controls.\n\n**Case 3: The Missing Documentation (2019)**\n*Location:* Private Forensic Firm\n\n**Situation:** During a corporate espionage trial, defense requested chain of custody documentation. The forensic firm had lost their paper logs and the electronic system had been upgraded, overwriting historical data.\n\n**Result:** Judge ruled that without proper documentation, the evidence could not be authenticated. The $50 million lawsuit was dismissed.\n\n**Lesson Learned:** Redundant documentation systems must exist. Paper and electronic logs should be maintained separately.\n\n**Case 4: The Contaminated Evidence (2020)**\n*Location:* International Investigation\n\n**Situation:** A laptop seized in Country A was examined by local police before being sent to Country B for forensic analysis. The initial exam wasn't documented, and no hash values were calculated.\n\n**Result:** Country B's court ruled that they couldn't know if the evidence was authentic, as they couldn't prove what had been done during the initial exam.\n\n**Lesson Learned:** First responders must be trained that ANY examination changes evidence. No examination should occur without proper documentation.\n\n---\n\n## Chapter 2 \u2013 Computer Architecture &amp; Storage Internals\n\n---\n\n### 2.1 CPU Architecture &amp; Registers\n\n#### CPU Basics for Forensic Examiners\n\nUnderstanding CPU architecture is essential for:\n- Memory analysis (process structures, thread contexts)\n- Malware analysis (instruction sets, calling conventions)\n- Live system examination (register values during acquisition)\n- Exploit analysis (buffer overflows, ROP chains)\n\n**CPU Components Relevant to Forensics:**\n\n1. **Control Unit** \u2013 Fetches and decodes instructions\n2. **ALU** \u2013 Performs arithmetic/logical operations\n3. **Registers** \u2013 Fastest memory, holds current instructions/data\n4. **Cache** \u2013 L1/L2/L3, high-speed memory\n5. **Bus Interface** \u2013 Connects to memory and I/O\n\n#### Register Sets\n\nRegisters are the CPU's working memory \u2013 the first place data goes when being processed.\n\n**x86 Architecture (32-bit):**\n\n| Register | Purpose | Forensic Significance |\n|----------|---------|----------------------|\n| EAX | Accumulator | Function return values |\n| EBX | Base | Memory addressing |\n| ECX | Counter | Loop iterations |\n| EDX | Data | I/O operations |\n| ESI | Source Index | String operations |\n| EDI | Destination Index | Memory copying |\n| EBP | Base Pointer | Stack frame base |\n| ESP | Stack Pointer | Top of stack |\n| EIP | Instruction Pointer | Current instruction |\n\n**x86-64 Architecture (64-bit):**\n- Registers extended to 64-bit (RAX, RBX, etc.)\n- Additional registers: R8-R15\n- Larger address space\n\n**Forensic Application Example:**\nWhen performing memory forensics, examining the stack through ESP/RSP reveals:\n- Function call history\n- Local variables\n- Return addresses\n- Exception handlers\n\n#### CPU Modes\n\nModern CPUs operate in different modes that affect forensic access:\n\n1. **Real Mode** \u2013 16-bit, direct hardware access (boot process)\n2. **Protected Mode** \u2013 32-bit, memory protection (Windows)\n3. **Long Mode** \u2013 64-bit, extended features (modern OS)\n4. **System Management Mode** \u2013 Highest privilege, hidden from OS\n\n&gt; **Critical Forensic Fact:** System Management Mode (SMM) operates below the operating system. Malware like \"LoJax\" has been found hiding in SMM, completely invisible to traditional forensics.\n\n---\n\n### 2.2 Memory Hierarchy\n\nUnderstanding memory hierarchy helps forensic examiners:\n- Know where evidence exists at different levels\n- Understand persistence characteristics\n- Identify anti-forensic techniques targeting specific memory\n- Plan acquisition strategies\n\n#### Memory Levels\n\n```\nSpeed \u2191           Cost \u2191\n  |    REGISTERS (CPU)\n  |        \u2193\n  |    L1 CACHE (CPU)\n  |        \u2193\n  |    L2 CACHE (CPU)\n  |        \u2193\n  |    L3 CACHE (CPU)\n  |        \u2193\n  |    RAM (Main Memory)\n  |        \u2193\n  |    SSD/HDD (Storage)\n  \u2193        \u2193\nSize \u2191     Cost \u2193\n```\n\n**Level 1: CPU Registers**\n- Size: Bytes to kilobytes\n- Speed: &lt; 1 ns access\n- Persistence: Volatile (lost on power off)\n- Forensic Access: Only via live debugging\n\n**Level 2: CPU Cache (L1/L2/L3)**\n- Size: Kilobytes to megabytes\n- Speed: 1-10 ns access\n- Persistence: Volatile\n- Forensic Access: Generally inaccessible\n\n**Level 3: RAM (Main Memory)**\n- Size: Gigabytes to terabytes\n- Speed: 50-100 ns access\n- Persistence: Volatile (seconds after power loss)\n- Forensic Access: Memory acquisition tools\n\n**Level 4: Persistent Storage**\n- Size: Gigabytes to petabytes\n- Speed: Milliseconds to seconds\n- Persistence: Non-volatile\n- Forensic Access: Imaging tools\n\n#### RAM Persistence Characteristics\n\n**Cold Boot Attacks:** RAM retains data for seconds to minutes after power loss, depending on temperature.\n\n| Temperature | Data Retention |\n|-------------|----------------|\n| Room temp (20\u00b0C) | 2-3 seconds |\n| Cooled (-50\u00b0C) | Several minutes |\n| Liquid Nitrogen (-196\u00b0C) | Hours |\n\n**Forensic Application:** In 2008, researchers demonstrated cold boot attacks could recover encryption keys from RAM by physically cooling memory modules and transferring them to another system for analysis.\n\n---\n\n### 2.3 Storage Media Types\n\n#### HDD Magnetic Structure\n\nHard disk drives store data magnetically on rotating platters. Understanding their structure helps in:\n- Physical recovery of damaged drives\n- Understanding data remanence\n- Identifying anti-forensic techniques\n\n**HDD Components:**\n```\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502    Platters (magnetic)   \u2502\n\u2502    Spindle (rotates)     \u2502\n\u2502    Read/Write Heads      \u2502\n\u2502    Actuator (moves heads)\u2502\n\u2502    Controller Board      \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n**Data Organization:**\n- **Track** \u2013 Concentric circle of data\n- **Sector** \u2013 Smallest addressable unit (typically 512 bytes or 4K)\n- **Cluster** \u2013 Group of sectors (file system allocation unit)\n- **Cylinder** \u2013 Same track across all platters\n\n**Magnetic Remanence:**\nWhen data is \"overwritten\" on HDDs:\n- Single overwrite may leave residual magnetism\n- Government standards require multiple passes for sanitization\n- Advanced recovery techniques can read previous data\n\n**Gutmann Method:** 35-pass overwrite sequence designed to defeat magnetic force microscopy recovery.\n\n#### SSD NAND Flash Structure\n\nSolid State Drives use NAND flash memory, fundamentally different from HDDs in operation and forensic implications.\n\n**NAND Flash Types:**\n| Type | Bits/Cell | Endurance | Speed | Forensic Challenge |\n|------|-----------|-----------|-------|---------------------|\n| SLC | 1 | High (100k writes) | Fast | Least complex |\n| MLC | 2 | Medium (10k writes) | Moderate | Page mapping complex |\n| TLC | 3 | Low (3k writes) | Slow | Wear leveling aggressive |\n| QLC | 4 | Very Low (1k writes) | Slowest | Maximum complexity |\n\n**SSD Components:**\n- **Controller** \u2013 Manages all operations\n- **DRAM Cache** \u2013 Temporary storage\n- **NAND Chips** \u2013 Actual storage\n- **Firmware** \u2013 Controller instructions\n\n#### Wear Leveling &amp; Forensic Impact\n\nWear leveling is the SSD's method of distributing writes evenly across all memory cells to extend drive life. This has profound forensic implications.\n\n**How Wear Leveling Works:**\n```\nData Write Request \u2192 Controller maps to physical location\n                           \u2193\nLogical address maps to different physical address\n                           \u2193\nOld physical location marked for garbage collection\n                           \u2193\nOriginal data may remain (until overwritten)\n```\n\n**Forensic Challenges:**\n\n1. **Data Relocation:**\n   - File system thinks data is in one place\n   - Controller moves it to another\n   - Traditional file system forensics may miss data\n\n2. **TRIM Command:**\n   - OS tells SSD which blocks are unused\n   - SSD immediately erases or marks for garbage collection\n   - Deleted files may be unrecoverable within seconds\n\n   ```\n   Traditional HDD: Delete file \u2192 Data remains until overwritten\n   Modern SSD with TRIM: Delete file \u2192 Data erased immediately\n   ```\n\n3. **Garbage Collection:**\n   - SSD reorganizes data in background\n   - Can destroy evidence even without TRIM\n   - Timing unpredictable\n\n4. **Over-Provisioning:**\n   - Extra storage space not visible to OS\n   - May contain historical data\n   - Difficult to access forensically\n\n**Case Example:** In 2015, a suspect's SSD was seized minutes after deleting incriminating files. Traditional recovery tools found nothing \u2013 the TRIM command had already erased the data.\n\n**Forensic Best Practices for SSDs:**\n```\n1. Immediate imaging after seizure\n2. Use hardware write blockers\n3. Consider chip-off for extreme cases\n4. Document drive model and firmware\n5. Research specific controller behavior\n6. Be prepared for incomplete recovery\n```\n\n---\n\n### 2.4 Disk Partitioning Systems\n\n#### MBR Internals\n\nMaster Boot Record is the traditional partitioning scheme, still widely used for compatibility.\n\n**MBR Structure:**\n```\nAddress: 0x0000 - Boot code (446 bytes)\nAddress: 0x01BE - Partition 1 entry (16 bytes)\nAddress: 0x01CE - Partition 2 entry (16 bytes)\nAddress: 0x01DE - Partition 3 entry (16 bytes)\nAddress: 0x01EE - Partition 4 entry (16 bytes)\nAddress: 0x01FE - Boot signature (0x55, 0xAA)\n```\n\n**Partition Entry Format:**\n| Offset | Length | Description |\n|--------|--------|-------------|\n| 0 | 1 | Boot indicator (0x80 = bootable) |\n| 1 | 3 | CHS start address |\n| 4 | 1 | Partition type |\n| 5 | 3 | CHS end address |\n| 8 | 4 | LBA start sector |\n| 12 | 4 | Partition size in sectors |\n\n**Partition Types (Common):**\n- 0x07 \u2013 NTFS (Windows)\n- 0x0B \u2013 FAT32 (CHS)\n- 0x0C \u2013 FAT32 (LBA)\n- 0x83 \u2013 Linux ext2/3/4\n- 0x82 \u2013 Linux swap\n\n**Forensic Significance:**\n- MBR can hide partitions (unused entries)\n- Boot code may contain malware (bootkits)\n- Partition table modifications hide data\n\n#### GPT Internals\n\nGUID Partition Table is the modern standard, part of UEFI firmware.\n\n**GPT Structure:**\n```\nPrimary GPT Header (LBA 1)\n    \u2193\nPartition Entry Array (LBA 2-33)\n    \u2193\nActual Partitions\n    \u2193\nBackup Partition Entry Array\n    \u2193\nBackup GPT Header (Last LBA)\n```\n\n**GPT Header:**\n| Offset | Length | Field |\n|--------|--------|-------|\n| 0 | 8 | Signature (\"EFI PART\") |\n| 8 | 4 | Revision |\n| 12 | 4 | Header size |\n| 16 | 4 | CRC32 of header |\n| 20 | 4 | Reserved |\n| 24 | 8 | Current LBA |\n| 32 | 8 | Backup LBA |\n| 40 | 8 | First usable LBA |\n| 48 | 8 | Last usable LBA |\n| 56 | 16 | Disk GUID |\n| 72 | 8 | Partition entry LBA |\n| 80 | 4 | Number of entries |\n| 84 | 4 | Entry size |\n| 88 | 4 | CRC32 of array |\n\n**Advantages for Forensics:**\n- Redundant headers (primary and backup)\n- CRC32 checksums detect tampering\n- Unique GUIDs identify partitions\n- No 2TB limit\n\n#### Hidden Partitions\n\nBoth MBR and GPT can hide partitions through various techniques:\n\n**MBR Hiding Methods:**\n\n1. **Type Modification:**\n   - Change partition type to unused value (e.g., 0x00)\n   - Partition exists but OS ignores it\n\n2. **Entry Deletion:**\n   - Remove partition entry\n   - Data remains until overwritten\n\n3. **CHS/LBA Mismatch:**\n   - Specify invalid geometry\n   - OS can't access correctly\n\n**GPT Hiding Methods:**\n\n1. **Attribute Flags:**\n   - Set \"hidden\" attribute\n   - OS may honor this flag\n\n2. **Header Corruption:**\n   - Damage primary header\n   - OS uses backup, hidden partition not in backup\n\n3. **GUID Manipulation:**\n   - Change partition type GUID to unused value\n\n**Detection Tools:**\n- **TestDisk** \u2013 Scans for lost partitions\n- **gpart** \u2013 Guesses partition tables\n- **Autopsy** \u2013 Partition recovery module\n- Manual sector examination with hex editor\n\n---\n\n### 2.5 File Systems Deep Analysis\n\n#### FAT32 Structure\n\nFile Allocation Table (FAT) is the simplest file system, but understanding it is fundamental to grasping more complex systems.\n\n**FAT32 Layout:**\n```\nReserved Sectors (including boot sector)\n    \u2193\nFAT1 (Primary File Allocation Table)\n    \u2193\nFAT2 (Mirror of FAT1)\n    \u2193\nRoot Directory (optional in FAT32)\n    \u2193\nData Region (clusters)\n```\n\n**Boot Sector Analysis:**\n| Offset | Length | Field | Example |\n|--------|--------|-------|---------|\n| 0x0B | 2 | Bytes per sector | 512 |\n| 0x0D | 1 | Sectors per cluster | 8 |\n| 0x0E | 2 | Reserved sectors | 32 |\n| 0x10 | 1 | Number of FATs | 2 |\n| 0x20 | 4 | Sectors per FAT | 7800 |\n\n**Directory Entry Structure (32 bytes):**\n| Offset | Length | Description |\n|--------|--------|-------------|\n| 0x00 | 8 | Filename |\n| 0x08 | 3 | Extension |\n| 0x0B | 1 | Attributes |\n| 0x0C | 1 | Reserved |\n| 0x0D | 1 | Creation time (tenths) |\n| 0x0E | 2 | Creation time |\n| 0x10 | 2 | Creation date |\n| 0x12 | 2 | Last access date |\n| 0x14 | 2 | High cluster (FAT32) |\n| 0x16 | 2 | Last modification time |\n| 0x18 | 2 | Last modification date |\n| 0x1A | 2 | Low cluster |\n| 0x1C | 4 | File size |\n\n**FAT32 Forensic Artifacts:**\n- **Deleted files:** First byte of filename set to 0xE5\n- **Long filenames:** Multiple directory entries with attributes 0x0F\n- **Volume label:** Directory entry with attribute 0x08\n\n#### NTFS Deep Internals\n\nNTFS (New Technology File System) is Windows' primary file system, rich with forensic artifacts.\n\n**NTFS Volume Layout:**\n```\nBoot Sector (first 16 sectors)\n    \u2193\nMaster File Table ($MFT)\n    \u2193\nSystem Files (metadata)\n    \u2193\nData Region\n    \u2193\nBackup Boot Sector (last sector)\n```\n\n#### MFT Structure\n\nThe Master File Table is the heart of NTFS \u2013 every file and folder has at least one entry.\n\n**MFT Entry Structure:**\n```\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Header (42 bytes)   \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Attribute 1         \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Attribute 2         \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 ...                 \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Attribute N         \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 End marker (0xFFFFFFFF)\u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n**MFT Header:**\n| Offset | Field | Significance |\n|--------|-------|--------------|\n| 0x00 | \"FILE\" signature | Valid entry (0x454C4946) |\n| 0x04 | Update sequence offset | For fixing |\n| 0x08 | Log file sequence number | Transaction tracking |\n| 0x10 | Sequence number | Increments on reuse |\n| 0x12 | Link count | Hard links count |\n| 0x14 | First attribute offset | |\n| 0x16 | Flags | 0x01=in use, 0x02=directory |\n| 0x18 | Entry size in bytes | |\n| 0x1C | Allocated size | |\n| 0x20 | File reference to base | For extended entries |\n| 0x28 | Next attribute ID | |\n| 0x2C | Record number | |\n\n**Critical NTFS Attributes:**\n\n| Attribute Type | ID | Forensic Value |\n|----------------|-----|----------------|\n| $STANDARD_INFORMATION | 0x10 | MAC times, permissions |\n| $ATTRIBUTE_LIST | 0x20 | For fragmented MFT |\n| $FILE_NAME | 0x30 | Filename, MAC times |\n| $OBJECT_ID | 0x40 | Unique file ID |\n| $SECURITY_DESCRIPTOR | 0x50 | Permissions, ownership |\n| $VOLUME_NAME | 0x60 | Volume label |\n| $VOLUME_INFORMATION | 0x70 | Volume version |\n| $DATA | 0x80 | File content |\n| $INDEX_ROOT | 0x90 | Directory indexing |\n| $INDEX_ALLOCATION | 0xA0 | Large directory index |\n| $BITMAP | 0xB0 | Cluster allocation |\n| $REPARSE_POINT | 0xC0 | Symbolic links |\n\n**Forensic Gold in MFT:**\n- **$STANDARD_INFORMATION vs $FILE_NAME times:**\n  - Malware often modifies $SI but misses $FN\n  - Comparison reveals timestomping\n\n- **Slack space:**\n  - MFT entries are fixed size (usually 1024 bytes)\n  - Unused space may contain previous file data\n\n- **Resident vs Non-Resident:**\n  - Small files stored entirely in MFT\n  - Extremely difficult to delete\n\n#### $LogFile Analysis\n\nThe NTFS Log File tracks metadata changes for recovery purposes \u2013 a forensic goldmine.\n\n**$LogFile Structure:**\n```\nRestart Area\n    \u2193\nLogging Area (circular buffer)\n    \u2193\n    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n    \u2502 Log Records  \u2502\n    \u2502              \u2502\n    \u2502 Redo/Undo    \u2502\n    \u2502 Operations   \u2502\n    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n**Log Record Types:**\n- **Initialize File Record** \u2013 Creating MFT entry\n- **Write Attribute** \u2013 Modifying file metadata\n- **Delete Attribute** \u2013 Removing data\n- **Update Resident Value** \u2013 Changing small files\n- **End of Log Record** \u2013 Transaction complete\n\n**Forensic Applications:**\n```\nExample: Suspect deletes incriminating file\n        \u2193\n$LogFile shows:\n- File record initialization\n- Attribute writes\n- Deletion operations\n- Timestamps of all actions\n```\n\n**Recovering Deleted Files from $LogFile:**\nEven when files are deleted and MFT entries reused, $LogFile may retain:\n- Original filenames\n- Timestamps before tampering\n- Cluster allocations\n- File attributes\n\n#### $UsnJrnl (Update Sequence Number Journal)\n\nThe USN Journal records all changes to files on an NTFS volume \u2013 like a surveillance camera for file activity.\n\n**USN Record Structure:**\n| Field | Size | Description |\n|-------|------|-------------|\n| Record length | 4 | Size of this record |\n| Major version | 2 | USN version |\n| Minor version | 2 | Minor version |\n| File reference | 8 | MFT reference |\n| Parent reference | 8 | Parent directory |\n| USN | 8 | Update sequence number |\n| Timestamp | 8 | File time (Windows format) |\n| Reason | 4 | Change reason flags |\n| Source info | 4 | Source of change |\n| Security ID | 4 | Security identifier |\n| File attributes | 4 | File attributes |\n| Filename length | 2 | Length of filename |\n| Filename offset | 2 | Offset to filename |\n| Filename | Variable | Unicode filename |\n\n**Reason Flags (Partial):**\n- 0x00000001 \u2013 DATA_OVERWRITE\n- 0x00000002 \u2013 DATA_EXTEND\n- 0x00000004 \u2013 DATA_TRUNCATION\n- 0x00000100 \u2013 FILE_CREATE\n- 0x00000200 \u2013 FILE_DELETE\n- 0x00010000 \u2013 CLOSE\n- 0x80000000 \u2013 RENAME_NEW_NAME\n\n**Forensic Power of $UsnJrnl:**\n```\nTimeline of EVERY file operation:\n12:01:23 \u2013 secret.doc CREATED\n12:02:45 \u2013 secret.doc DATA_OVERWRITE\n12:03:12 \u2013 secret.doc RENAME (to \"innocent.txt\")\n12:04:30 \u2013 innocent.txt CLOSE\n12:05:17 \u2013 innocent.txt DELETE\n```\n\n**Even after deletion and MFT reuse, the USN Journal shows:**\n- Original filename\n- Exact time of creation\n- Rename operations\n- Deletion timestamp\n\n#### EXT4 Journal System\n\nLinux's EXT4 file system includes journaling capabilities similar to NTFS, with distinct forensic artifacts.\n\n**EXT4 Layout:**\n```\nBoot Block (optional)\n    \u2193\nBlock Group 0\n    \u2193\nBlock Group 1\n    \u2193\n... (more groups)\n```\n\n**Each Block Group Contains:**\n- Superblock copy\n- Group descriptors\n- Data block bitmap\n- Inode bitmap\n- Inode table\n- Data blocks\n\n**Journal (JBD2):**\nThe journal is actually a separate file (.journal) containing transaction records.\n\n**Journal Record Types:**\n- **Descriptor block** \u2013 Describes following data blocks\n- **Commit block** \u2013 Transaction committed\n- **Revoke block** \u2013 Blocks to ignore on replay\n- **Data block** \u2013 Actual metadata/data\n\n**Forensic Recovery from Journal:**\n```\nDeleted file originally in inode 12345\n        \u2193\nJournal may contain:\n- Inode 12345 data before deletion\n- Directory entry modifications\n- Block allocation changes\n```\n\n#### APFS Snapshots\n\nApple File System (APFS) introduces snapshot capabilities with forensic implications.\n\n**How APFS Snapshots Work:**\n```\nInitial State: File A, File B\n        \u2193\nTake Snapshot 1\n        \u2193\nModify File A\n        \u2193\nTake Snapshot 2\n        \u2193\nDelete File B\n        \u2193\nTake Snapshot 3\n```\n\n**Space Sharing:**\nSnapshots use copy-on-write \u2013 modified blocks are written to new locations while original blocks remain referenced by snapshots.\n\n**Forensic Access:**\nEven when a user deletes files, snapshots may retain:\n- Original file versions\n- Deleted files\n- Historical directory structures\n- Previous metadata\n\n**Accessing Snapshots:**\n- **/Volumes** \u2013 Mounted snapshots appear here\n- **.HFS+ Private Directory Data** \u2013 Hidden directory\n- **tmutil** \u2013 Time Machine utility\n- **fs_snapshot** \u2013 APFS snapshot commands\n\n---\n\n### 2.6 RAID Forensics\n\n#### RAID Concepts for Examiners\n\nRAID (Redundant Array of Independent Disks) combines multiple drives into one logical unit, creating forensic challenges.\n\n**Common RAID Levels:**\n\n| Level | Description | Min Drives | Forensic Challenge |\n|-------|-------------|------------|---------------------|\n| RAID 0 | Striping | 2 | Data striped across drives |\n| RAID 1 | Mirroring | 2 | Duplicate data |\n| RAID 5 | Striping + Parity | 3 | Parity distributed |\n| RAID 6 | Striping + Double Parity | 4 | More fault tolerant |\n| RAID 10 | Mirror of Stripes | 4 | Combined approach |\n\n#### RAID 0 Reconstruction\n\nRAID 0 spreads data across drives in stripes \u2013 losing one drive loses everything, but forensically we must reconstruct the logical volume.\n\n**RAID 0 Parameters Needed:**\n- Stripe size (chunk size)\n- Drive order\n- Number of drives\n- Start offset\n\n**Example Configuration:**\n```\nDrive 1: Block 0, Block 3, Block 6, Block 9...\nDrive 2: Block 1, Block 4, Block 7, Block 10...\nDrive 3: Block 2, Block 5, Block 8, Block 11...\n\nStripe size: 64KB\n```\n\n**Reconstruction Process:**\n```\n1. Acquire all drives individually (images)\n2. Determine stripe size (often 64KB, 128KB, 256KB)\n3. Identify drive order (may require analysis)\n4. Calculate logical block mapping\n5. Reassemble using RAID reconstruction tool\n6. Verify file system consistency\n```\n\n#### RAID 5 Reconstruction\n\nRAID 5 adds parity, making reconstruction more complex but providing redundancy.\n\n**Parity Calculation:**\n```\nData Drive 1: A\nData Drive 2: B\nParity Drive: XOR(A,B)\n\nXOR truth table:\n0 XOR 0 = 0\n0 XOR 1 = 1\n1 XOR 0 = 1\n1 XOR 1 = 0\n```\n\n**Parity Rotation:**\nMost RAID 5 implementations rotate parity across drives:\n```\nStripe 0: Parity on Drive 1\nStripe 1: Parity on Drive 2\nStripe 2: Parity on Drive 3\nStripe 3: Parity on Drive 1 (repeat)\n```\n\n**Reconstruction with Missing Drive:**\nIf one drive fails, data can be reconstructed using:\n```\nData = Parity XOR remaining data\n\nExample: Drive 2 failed\nNeed block from Drive 2\nAvailable: Drive 1, Drive 3, Parity\nRecover = Drive1 XOR Drive3 XOR Parity\n```\n\n#### RAID 6 Reconstruction\n\nRAID 6 uses two parity blocks per stripe, allowing two drive failures.\n\n**Parity Types:**\n- **P Parity:** XOR of data (like RAID 5)\n- **Q Parity:** Reed-Solomon or Galois field calculation\n\n**Reconstruction Complexity:**\nRequires understanding of:\n- Galois field arithmetic\n- Reed-Solomon codes\n- Specific RAID implementation\n\n#### Data Carving from RAID\n\nWhen RAID reconstruction is impossible, data carving may recover files.\n\n**Challenges in RAID Carving:**\n\n1. **Striping:**\n   - File fragments distributed across drives\n   - Carving must account for stripe boundaries\n\n2. **Parity Interleaving:**\n   - Parity blocks interspersed with data\n   - Must identify and skip parity\n\n3. **Multiple Drives:**\n   - Need synchronized reading across images\n   - Timing of writes affects fragment locations\n\n**RAID Carving Tools:**\n- **R-Studio** \u2013 RAID reconstruction\n- **UFS Explorer** \u2013 RAID recovery\n- **DMDE** \u2013 RAID assembly\n- **Foremost/ Scalpel** \u2013 Modified for RAID\n\n**Manual Carving Example for JPEG:**\n```\n1. Locate JPEG header (FF D8 FF) in first drive\n2. Determine stripe size from header location\n3. Calculate which drive contains next fragment\n4. Follow fragmentation pattern\n5. Reassemble across drives\n```\n\n---\n\n## Chapter 3 \u2013 Operating System Artifacts\n\n---\n\n### 3.1 Windows Internals\n\n#### Windows Boot Process\n\nUnderstanding boot process helps identify bootkits and timeline system initialization.\n\n**Boot Sequence:**\n```\nPower On \u2192 UEFI/BIOS \u2192 Boot Manager \u2192 OS Loader \u2192 Kernel \u2192 Session Manager \u2192 Logon\n```\n\n**Detailed Steps:**\n\n1. **UEFI/BIOS Phase:**\n   - POST (Power-On Self Test)\n   - Hardware initialization\n   - Boot device selection\n   - UEFI loads bootloader from EFI partition\n\n2. **Windows Boot Manager (bootmgfw.efi):**\n   - Reads BCD (Boot Configuration Data)\n   - Displays boot menu (if configured)\n   - Launches selected OS loader\n\n3. **Windows OS Loader (winload.exe):**\n   - Loads kernel (ntoskrnl.exe)\n   - Loads HAL (hal.dll)\n   - Loads boot drivers\n   - Transitions to kernel mode\n\n4. **Kernel Initialization:**\n   - Creates system processes\n   - Loads remaining drivers\n   - Starts Session Manager (smss.exe)\n\n5. **Session Manager (smss.exe):**\n   - Creates user session\n   - Starts subsystem processes\n   - Launches Winlogon\n\n6. **Winlogon:**\n   - Starts Logon UI\n   - Handles authentication\n   - Launches user shell\n\n**Forensic Artifacts from Boot:**\n- **Event Log 6005/6006:** System start/shutdown\n- **Event Log 6009:** OS version at boot\n- **Event Log 6013:** System uptime\n- **Prefetch files:** Boot prefetch (.pf)\n- **Registry:** Last known good configuration\n\n#### Registry Hive Structure\n\nThe Windows Registry is a hierarchical database of system and application configuration \u2013 a primary source of forensic evidence.\n\n**Registry Hives (Files):**\n| Hive | File Location | Content |\n|------|---------------|---------|\n| HKEY_LOCAL_MACHINE\\SAM | %SystemRoot%\\System32\\config\\SAM | User passwords (hashed) |\n| HKEY_LOCAL_MACHINE\\SECURITY | %SystemRoot%\\System32\\config\\SECURITY | Security policies |\n| HKEY_LOCAL_MACHINE\\SOFTWARE | %SystemRoot%\\System32\\config\\SOFTWARE | System-wide settings |\n| HKEY_LOCAL_MACHINE\\SYSTEM | %SystemRoot%\\System32\\config\\SYSTEM | Hardware configuration |\n| HKEY_CURRENT_USER | %UserProfile%\\NTUSER.DAT | User-specific settings |\n| HKEY_USERS\\.DEFAULT | %SystemRoot%\\System32\\config\\DEFAULT | Default profile |\n\n**Registry Structure:**\n```\nRegistry Hive\n    \u2193\nKey (like folder)\n    \u2193\nSubkeys\n    \u2193\nValues (name/data pairs)\n    \u2193\nData Types:\n- REG_SZ (string)\n- REG_DWORD (32-bit number)\n- REG_BINARY (binary data)\n- REG_MULTI_SZ (multiple strings)\n- REG_EXPAND_SZ (expandable string)\n```\n\n**Forensically Significant Registry Locations:**\n\n1. **System Information:**\n   ```\n   SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ComputerName\n   SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation\n   SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\n   ```\n\n2. **User Activity:**\n   ```\n   Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RecentDocs\n   Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU\n   Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\TypedPaths\n   Software\\Microsoft\\Internet Explorer\\TypedURLs\n   ```\n\n3. **USB Device History:**\n   ```\n   SYSTEM\\CurrentControlSet\\Enum\\USBSTOR\n   SYSTEM\\CurrentControlSet\\Enum\\USB\n   SOFTWARE\\Microsoft\\Windows Portable Devices\\Devices\n   ```\n\n4. **Program Execution:**\n   ```\n   SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\n   SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\n   SYSTEM\\CurrentControlSet\\Services (drivers/services)\n   ```\n\n5. **Network Information:**\n   ```\n   SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkList\n   SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\n   SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\n   ```\n\n**Registry Transaction Logs:**\n- **.LOG files** \u2013 Transaction logs for registry hives\n- **.BLF files** \u2013 Background logs (Windows 10+)\n- **.REGTRANS-MS** \u2013 Transaction manager logs\n\n&gt; **Forensic Gold:** Registry transaction logs may contain data that was deleted from the main hive but remains in logs.\n\n#### System32 Artifacts\n\nThe System32 directory contains critical Windows system files that leave forensic traces.\n\n**Key Artifacts:**\n\n1. **Event Logs (.evtx):**\n   Location: `%SystemRoot%\\System32\\winevt\\Logs\\`\n\n   Important logs:\n   - Application.evtx\n   - Security.evtx\n   - System.evtx\n   - Setup.evtx\n   - PowerShell.evtx\n\n2. **Prefetch (.pf):**\n   Location: `%SystemRoot%\\Prefetch\\`\n\n   Records recently executed programs:\n   - Creates .pf file per executable\n   - Includes run count\n   - Includes last run time\n   - Lists files accessed\n\n3. **Task Scheduler:**\n   Location: `%SystemRoot%\\System32\\Tasks\\`\n\n   Scheduled tasks:\n   - XML format tasks\n   - Execution times\n   - Triggers\n   - Actions\n\n4. **Windows Error Reporting (WER):**\n   Location: `%ProgramData%\\Microsoft\\Windows\\WER\\`\n\n   Crash dumps and reports:\n   - Application crashes\n   - Memory dumps\n   - Error signatures\n\n5. **Amcache.hve:**\n   Location: `%SystemRoot%\\AppCompat\\Programs\\Amcache.hve`\n\n   Program execution artifacts:\n   - SHA1 hashes of executables\n   - File paths\n   - Installation times\n   - Deletion records\n\n6. **Shimcache (AppCompatCache):**\n   Location: Registry `SYSTEM\\CurrentControlSet\\Control\\Session Manager\\AppCompatCache`\n\n   Tracks program execution:\n   - File path\n   - Last modified time\n   - Execution flag\n\n7. **RecentFileCache.bcf:**\n   Location: `%SystemRoot%\\AppCompat\\Programs\\RecentFileCache.bcf`\n\n   Recently used files:\n   - Quick Launch entries\n   - Recent documents\n\n#### Event Logs Deep Dive\n\nWindows Event Logs are structured records of system, security, and application events.\n\n**Event Log Structure:**\n```\nEvent Record:\n- Record ID (incremental)\n- Timestamp\n- Event ID\n- Level (Info, Warning, Error)\n- Source\n- Computer name\n- User SID\n- Event data (XML format)\n```\n\n**Critical Event IDs:**\n\n*Security Log:*\n| Event ID | Description | Forensic Value |\n|----------|-------------|----------------|\n| 4624 | Successful logon | User, time, logon type |\n| 4625 | Failed logon | Brute force attempts |\n| 4634 | Logoff | Session end time |\n| 4648 | Logon with explicit credentials | RunAs usage |\n| 4672 | Special privileges assigned | Admin logon |\n| 4688 | Process creation | Program execution |\n| 4689 | Process termination | End of execution |\n| 4698 | Scheduled task created | Persistence mechanism |\n| 4702 | Scheduled task updated | Modification |\n| 4720 | User account created | New user |\n| 4724 | Password reset attempt | Account compromise |\n| 4732 | User added to group | Privilege escalation |\n| 5140 | Network share accessed | Data access |\n| 5156 | Windows Filtering Platform connection | Network connection |\n\n*System Log:*\n| Event ID | Description |\n|----------|-------------|\n| 6005 | Event log service started (system boot) |\n| 6006 | Event log service stopped (shutdown) |\n| 6008 | Unexpected shutdown |\n| 6009 | OS version at boot |\n| 6013 | System uptime |\n| 7001 | Service started |\n| 7036 | Service state change |\n\n*Application Log:*\n- Application-specific events\n- Error reports\n- Installation events\n- Crash information\n\n**Logon Types:**\n| Type | Description | Forensic Significance |\n|------|-------------|----------------------|\n| 2 | Interactive (local console) | Physical access |\n| 3 | Network (network share) | Remote file access |\n| 4 | Batch (scheduled task) | Automated execution |\n| 5 | Service (service startup) | System services |\n| 7 | Unlock (screen unlock) | After idle/lock |\n| 8 | NetworkCleartext (IIS) | Web authentication |\n| 9 | NewCredentials (RunAs) | Alternate credentials |\n| 10 | RemoteInteractive (RDP) | Remote desktop |\n| 11 | CachedInteractive | Domain cached credentials |\n\n**Parsing Event Logs:**\n```powershell\n# PowerShell example\nGet-WinEvent -LogName Security -MaxEvents 100 | \nWhere-Object { $_.Id -eq 4624 } |\nSelect-Object TimeCreated, Message\n\n# Using wevtutil\nwevtutil qe Security /f:text /q:\"*[System[(EventID=4624)]]\"\n\n# Export to CSV\nGet-WinEvent -LogName Security | \nExport-Csv security_events.csv\n```\n\n---\n\n### 3.2 Linux Internals\n\n#### Init Systems (systemd)\n\nLinux boot and service management has evolved, with systemd becoming the standard on most distributions.\n\n**Boot Process:**\n```\nBIOS/UEFI \u2192 Bootloader (GRUB) \u2192 Kernel \u2192 Init (systemd) \u2192 Target \u2192 Services\n```\n\n**systemd Architecture:**\n```\nsystemd (PID 1)\n    \u2193\nTargets (runlevels)\n    \u2193\nServices (.service files)\n    \u2193\nSockets, Timers, Mounts, etc.\n```\n\n**Key systemd Components:**\n\n| Component | Purpose | Forensic Location |\n|-----------|---------|-------------------|\n| systemd | Main init process | PID 1, /proc/1/ |\n| journald | Logging daemon | /var/log/journal/ |\n| udevd | Device management | /dev/, rules in /etc/udev/ |\n| logind | Session management | /var/log/wtmp, /var/run/utmp |\n| timedated | Time synchronization | /etc/systemd/timesyncd.conf |\n\n**Forensic Artifacts from systemd:**\n\n1. **Service Files:**\n   Location: `/etc/systemd/system/`, `/lib/systemd/system/`\n\n   ```ini\n   [Unit]\n   Description=Malicious Service\n   After=network.target\n   \n   [Service]\n   ExecStart=/usr/local/bin/malware\n   Restart=always\n   \n   [Install]\n   WantedBy=multi-user.target\n   ```\n\n2. **Journal Logs:**\n   ```bash\n   # View logs from specific service\n   journalctl -u malicious.service\n   \n   # View logs since boot\n   journalctl -b\n   \n   # Export to text\n   journalctl -o export &gt; system_logs.txt\n   ```\n\n3. **Timer Units:**\n   Scheduled tasks in systemd:\n   ```ini\n   [Unit]\n   Description=Run malware daily\n   \n   [Timer]\n   OnCalendar=daily\n   Persistent=true\n   \n   [Install]\n   WantedBy=timers.target\n   ```\n\n#### /proc Filesystem\n\nThe /proc filesystem is a virtual filesystem providing runtime system information \u2013 critical for live forensics.\n\n**Key /proc Entries:**\n\n| Path | Content | Forensic Value |\n|------|---------|----------------|\n| /proc/cpuinfo | CPU information | System identification |\n| /proc/meminfo | Memory usage | RAM capacity, usage |\n| /proc/version | Kernel version | OS identification |\n| /proc/cmdline | Boot parameters | How system booted |\n| /proc/mounts | Mounted filesystems | Storage layout |\n| /proc/self/ | Current process | Context for tools |\n| /proc/[PID]/ | Process-specific | Per-process details |\n\n**Process Directory (/proc/[PID]/):**\n\n| File | Contains |\n|------|----------|\n| cmdline | Command line arguments |\n| environ | Environment variables |\n| exe | Symlink to executable |\n| fd/ | Open file descriptors |\n| maps | Memory mappings |\n| mem | Process memory (requires ptrace) |\n| root | Symlink to root directory |\n| status | Process status |\n\n**Forensic Commands:**\n```bash\n# List all processes with details\nls -la /proc/*/exe 2&gt;/dev/null\n\n# Get command line of all processes\nfor pid in /proc/[0-9]*; do \n    echo -n \"$(basename $pid): \"\n    cat $pid/cmdline | tr '\\0' ' '\n    echo\ndone\n\n# Check for hidden processes\nps aux | grep -v \"\\[\"  # Kernel threads are in []\n```\n\n**Detecting Rootkits via /proc:**\n- Check for hidden PIDs (processes not in ps output but in /proc)\n- Verify /proc/[PID]/exe points to valid file\n- Check for unusual memory mappings\n- Examine /proc/modules for hidden kernel modules\n\n#### Authentication Logs\n\nLinux maintains detailed authentication logs essential for intrusion investigation.\n\n**Primary Log Files:**\n\n1. **/var/log/auth.log** (Debian/Ubuntu):\n   ```bash\n   # SSH logins\n   tail -f /var/log/auth.log | grep sshd\n   \n   # Failed logins\n   grep \"Failed password\" /var/log/auth.log\n   \n   # sudo usage\n   grep sudo /var/log/auth.log\n   ```\n\n2. **/var/log/secure** (RHEL/CentOS):\n   Same content as auth.log but different location.\n\n3. **/var/log/wtmp:**\n   Binary log of all logins/logouts:\n   ```bash\n   # View login history\n   last\n   \n   # Specific user\n   last username\n   \n   # Reboot history\n   last reboot\n   ```\n\n4. **/var/log/btmp:**\n   Failed login attempts:\n   ```bash\n   # View failed logins\n   lastb\n   ```\n\n5. **/var/run/utmp:**\n   Currently logged in users:\n   ```bash\n   who\n   w\n   ```\n\n**SSH Forensic Artifacts:**\n\n- **Known hosts:** `~/.ssh/known_hosts`\n  Shows systems the user connected TO\n\n- **Authorized keys:** `~/.ssh/authorized_keys`\n  Shows who can connect TO this system\n\n- **SSH logs:** auth.log entries for each connection\n  - Source IP\n  - Authentication method\n  - Session duration\n\n**Sudo Forensics:**\n```bash\n# sudoers file - who can sudo\ncat /etc/sudoers\ncat /etc/sudoers.d/*\n\n# sudo logs\ngrep sudo /var/log/auth.log\n# Format: user : TTY=pts/0 ; PWD=/home/user ; USER=root ; COMMAND=/bin/bash\n```\n\n---\n\n### 3.3 macOS Internals\n\n#### Unified Logs\n\nmacOS uses a unified logging system that captures detailed system activity.\n\n**Log Architecture:**\n```\nlog collect (command) \u2192 .logarchive directory\n    \u2193\nContains:\n- .tracev3 files (binary logs)\n- metadata.plist\n- timesync database\n```\n\n**Accessing Logs:**\n\n```bash\n# Collect system logs\nlog collect --last 1d --output system_logs.logarchive\n\n# Stream live logs\nlog stream --predicate 'eventMessage contains \"error\"'\n\n# Show logs from specific process\nlog show --predicate 'process == \"kernel\"'\n\n# Export to text\nlog show --archive system_logs.logarchive &gt; logs.txt\n```\n\n**Forensically Significant Log Entries:**\n\n1. **Application Launch:**\n   ```\n   process: appsync[PID]\n   eventMessage: launching application /Applications/Malware.app\n   ```\n\n2. **USB Device Connection:**\n   ```\n   process: kernel\n   eventMessage: IOUSBHostDevice - device 0x1234 connected\n   ```\n\n3. **Network Connections:**\n   ```\n   process: firewall\n   eventMessage: Connection from 192.168.1.100:54321\n   ```\n\n4. **File Access:**\n   ```\n   process: sandboxd\n   eventMessage: deny file-write /Users/user/Documents/secret.doc\n   ```\n\n#### Spotlight Artifacts\n\nSpotlight is macOS's search index \u2013 a rich source of file metadata.\n\n**Spotlight Database Location:**\n```\n/.Spotlight-V100/Store-V1/ (volume root)\n/System/Volumes/Data/.Spotlight-V100/ (modern macOS)\n```\n\n**Database Structure:**\n- SQLite database\n- Indexes of all files\n- Metadata extracted\n- Search history\n\n**Forensic Extraction:**\n\n```bash\n# Search for files (but updates timestamps!)\nmdfind -onlyin / suspect_term\n\n# Export metadata for specific file\nmdls /path/to/file\n\n# Show search history\nplutil -convert xml1 ~/Library/Preferences/com.apple.spotlight.plist\n\n# Recover deleted file references\nsqlite3 .Spotlight-V100/Store-V1/store.db\nSELECT * FROM files WHERE path LIKE '%secret%';\n```\n\n**Critical Spotlight Tables:**\n\n| Table | Content |\n|-------|---------|\n| files | File paths, inodes, flags |\n| metadata | Extended attributes, timestamps |\n| content | File content snippets |\n| search_history | User searches |\n\n#### Time Machine Backups\n\nTime Machine creates incremental backups that can be forensic goldmines.\n\n**Backup Structure:**\n```\nBackups.backupdb/\n\u2514\u2500\u2500 Computer Name/\n    \u251c\u2500\u2500 2023-06-15-123456/\n    \u2502   \u251c\u2500\u2500 Macintosh HD -&gt; Data/\n    \u2502   \u2514\u2500\u2500 ...\n    \u251c\u2500\u2500 2023-06-14-093022/\n    \u2514\u2500\u2500 Latest -&gt; 2023-06-15-123456/\n```\n\n**Forensic Value:**\n- Historical versions of files\n- Deleted file recovery\n- Timeline of file changes\n- System state at specific times\n\n**Accessing Backups:**\n\n```bash\n# Mount Time Machine sparse bundle\nhdiutil attach /Volumes/TimeMachine/Backups.backupdb/sparsebundle\n\n# Navigate to specific backup\ncd /Volumes/TimeMachine/Backups.backupdb/Computer/2023-06-15-123456/Macintosh\\ HD\n\n# Find deleted files\nfind . -name \"secret.doc\" 2&gt;/dev/null\n```\n\n**Hard Link Structure:**\nTime Machine uses hard links for unchanged files:\n- Multiple backups reference same physical data\n- Deleting one backup doesn't free space\n- Historical data persists until all references gone\n\n---\n\n### 3.4 Timeline Analysis\n\n#### Super Timeline Creation\n\nTimeline analysis correlates artifacts from multiple sources to reconstruct events.\n\n**Sources for Timeline:**\n- File system metadata (MAC times)\n- Log files (event logs, auth logs)\n- Registry artifacts\n- Application data\n- Network logs\n- Memory artifacts\n\n**log2timeline/plaso Approach:**\n\n```bash\n# Create timeline from disk image\nlog2timeline.py --storage-file case.plaso image.dd\n\n# Process multiple sources\nlog2timeline.py --storage-file case.plaso \\\n    --partitions all \\\n    --vss parsing \\\n    image.dd\n\n# Generate timeline\npsort.py -o l2tcsv case.plaso &gt; timeline.csv\n```\n\n**Timeline Format:**\n| Timestamp | Source | Description | Full Path |\n|-----------|--------|-------------|-----------|\n| 2023-06-15 10:23:45 | FILE | Modified | /Users/user/secret.doc |\n| 2023-06-15 10:24:12 | REG | Key created | HKU\\SID\\Software\\Microsoft |\n| 2023-06-15 10:25:30 | LOG | Logon | Security.evtx:4624 |\n\n#### Correlation of Multi-Source Logs\n\nEffective timeline analysis correlates events across sources to establish the full picture.\n\n**Example Investigation: Data Theft**\n\n*Event 1: Preparation*\n- 09:15:23 \u2013 Process: cmd.exe launched (Prefetch)\n- 09:15:45 \u2013 USB device connected (Registry USBSTOR)\n- 09:16:12 \u2013 File: confidential.xlsx opened (Jump Lists)\n\n*Event 2: Data Access*\n- 09:20:34 \u2013 File: confidential.xlsx accessed (USN Journal)\n- 09:21:56 \u2013 Copy operation detected (Shellbags)\n- 09:22:30 \u2013 File: confidential.xlsx accessed again (MFT)\n\n*Event 3: Exfiltration*\n- 09:25:12 \u2013 Network connection to external IP (Firewall log)\n- 09:25:45 \u2013 Large data transfer (NetFlow)\n- 09:26:30 \u2013 USB device removed (Setupapi.log)\n\n**Correlation Techniques:**\n\n1. **Normalization:** Convert all timestamps to common format (UTC)\n2. **Super Timeline:** Combine all events chronologically\n3. **Gap Analysis:** Identify missing time periods\n4. **Pattern Recognition:** Detect suspicious sequences\n5. **Anomaly Detection:** Flag deviations from baseline\n\n**Timeline Visualization:**\n```\n09:00 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n09:15 \u2500\u2500\u2500\u2500\u2500[CMD][USB][FILE]\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n09:20 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500[ACCESS]\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n09:25 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500[NET][XFER][USB REM]\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n09:30 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nKey: [CMD]=cmd.exe, [USB]=USB connect, [FILE]=file open,\n     [ACCESS]=file access, [NET]=connection, [XFER]=transfer\n```\n\n---\n\n# \ud83d\udd39 PART II \u2013 FORENSIC METHODOLOGY &amp; ACQUISITION\n\n---\n\n## Chapter 4 \u2013 Incident Response &amp; Evidence Handling\n\n---\n\n### 4.1 First Responder Protocol\n\nFirst responders are often non-forensic personnel who arrive first at a scene containing digital evidence. Their actions can make or break a case.\n\n**Initial Priorities:**\n\n1. **Safety First:**\n   - Ensure scene safety (physical threats)\n   - Check for hazardous materials\n   - Secure area from unauthorized access\n\n2. **Preserve Life:**\n   - Medical emergencies take priority\n   - Digital evidence secondary to life safety\n\n3. **Secure Scene:**\n   - Establish perimeter\n   - Control access\n   - Document initial observations\n\n**Digital Evidence Considerations:**\n\n```\nARRIVAL ASSESSMENT:\n- What type of incident? (homicide, fraud, intrusion)\n- What devices are present? (computers, phones, servers)\n- Are devices powered on or off?\n- Is network connectivity present?\n- Are there multiple users/workstations?\n- Is this a live incident requiring response?\n```\n\n**Documentation Before Touching:**\n\n```markdown\nPhotograph entire scene:\n- Overall room layout\n- Each device position\n- Screen contents (if powered on)\n- Cable connections\n- Surrounding area\n- Anyone present\n\nWritten notes:\n- Date and time of arrival\n- Weather conditions (for outdoor scenes)\n- Who is present\n- Initial observations\n- Any odors, sounds, unusual conditions\n```\n\n**Critical Mistakes by First Responders:**\n\n1. **Turning off powered-on computers:**\n   - Loses volatile data (memory, network connections)\n   - May trigger encryption\n   - Can corrupt open files\n\n2. **Using suspect's computer to examine files:**\n   - Modifies access times\n   - May trigger anti-forensics\n   - Contaminates evidence\n\n3. **Discussing case near devices:**\n   - Voice assistants may record\n   - Cameras may capture\n   - Microphones may be active\n\n4. **Improper handling of mobile devices:**\n   - Network connections may wipe data\n   - Fingerprints on screens\n   - Battery disconnection critical\n\n---\n\n### 4.2 Live vs Dead Analysis\n\nUnderstanding when to perform live analysis versus dead analysis is crucial.\n\n**Dead Analysis (Traditional):**\n- System powered off\n- Storage media removed and imaged\n- Analysis performed on image\n- No volatile data\n\n**Live Analysis:**\n- System running\n- Volatile data collected first\n- May include memory acquisition\n- Changes system state\n\n**Decision Matrix:**\n\n| Scenario | Approach | Rationale |\n|----------|----------|-----------|\n| Encrypted system running | Live | Can't access data after shutdown |\n| Server can't be offline | Live | Business continuity |\n| Suspect at keyboard | Live | May contain active sessions |\n| Powered-off computer | Dead | Preserve state, no volatile loss |\n| Malware investigation | Both | Memory for malware, disk for persistence |\n| Network intrusion | Live | Active connections, processes |\n\n**Live Response Order of Volatility:**\n\n```\nMOST VOLATILE (collect first)\n    \u2193\n1. CPU registers, cache\n2. Routing tables, ARP cache\n3. Process table, kernel modules\n4. Memory (RAM)\n5. Temporary file systems (/tmp)\n6. Disk (persistent storage)\n7. Remote logs, backups\n    \u2193\nLEAST VOLATILE (collect last)\n```\n\n**Live Response Tools:**\n\nWindows:\n```powershell\n# Built-in commands\nsysteminfo &gt; systeminfo.txt\nipconfig /all &gt; ipconfig.txt\nnetstat -ano &gt; netstat.txt\ntasklist /v &gt; tasklist.txt\nnet session &gt; sessions.txt\n\n# Specialized tools (copy to USB)\nautorunsc.exe -a -c &gt; autoruns.csv\npsloggedon.exe &gt; loggedon.txt\nhandle.exe -a &gt; handles.txt\n```\n\nLinux:\n```bash\n# Collect system information\nuname -a &gt; uname.txt\nps auxf &gt; processes.txt\nlsof &gt; open_files.txt\nnetstat -tupan &gt; connections.txt\narp -a &gt; arp_cache.txt\nlast &gt; logins.txt\ndmesg &gt; kernel_messages.txt\n```\n\n---\n\n### 4.3 Volatile Data Collection\n\nVolatile data must be collected systematically, starting with the most volatile.\n\n**Live Response Toolkit Preparation:**\n\n```\nForensic USB Drive Contents:\n- Write-protected USB (hardware switch)\n- Clean tools (verified hashes)\n- Batch scripts for collection\n- Output directory structure\n- Documentation templates\n- Write blocker software\n- Memory acquisition tools\n```\n\n**Windows Volatile Collection Script:**\n\n```powershell\n# forensic_collection.ps1\n$output = \"C:\\forensics_$(Get-Date -Format 'yyyyMMdd_HHmmss')\"\nNew-Item -ItemType Directory -Path $output -Force\n\n# System time (critical for timeline)\nGet-Date | Out-File \"$output\\system_time.txt\"\nw32tm /stripchart /computer:time.windows.com /samples:1 &gt;&gt; \"$output\\time_sync.txt\"\n\n# Network configuration\nipconfig /all &gt; \"$output\\ipconfig.txt\"\nroute print &gt; \"$output\\route.txt\"\narp -a &gt; \"$output\\arp.txt\"\nnetstat -ano &gt; \"$output\\netstat.txt\"\nnbtstat -c &gt; \"$output\\nbtstat.txt\"\n\n# Process information\ntasklist /v &gt; \"$output\\tasklist.txt\"\ntasklist /svc &gt; \"$output\\tasklist_services.txt\"\nwmic process list full &gt; \"$output\\wmic_process.txt\"\n\n# User sessions\nquery user &gt; \"$output\\query_user.txt\"\nnet session &gt; \"$output\\net_session.txt\"\n\n# Network shares\nnet share &gt; \"$output\\net_share.txt\"\n\n# Open files\nopenfiles /query /v &gt; \"$output\\openfiles.txt\"\n\n# Services\nnet start &gt; \"$output\\net_start.txt\"\nsc query &gt; \"$output\\sc_query.txt\"\n\n# Drivers\ndriverquery /v &gt; \"$output\\driverquery.txt\"\n\n# Registry volatile data\nreg export HKLM\\SAM \"$output\\sam.reg\" /y\nreg export HKLM\\SECURITY \"$output\\security.reg\" /y\nreg export HKLM\\SYSTEM \"$output\\system.reg\" /y\nreg export HKLM\\SOFTWARE \"$output\\software.reg\" /y\n\n# Event logs (last 1000)\nGet-WinEvent -LogName System -MaxEvents 1000 | Export-Csv \"$output\\system_log.csv\"\nGet-WinEvent -LogName Security -MaxEvents 1000 | Export-Csv \"$output\\security_log.csv\"\nGet-WinEvent -LogName Application -MaxEvents 1000 | Export-Csv \"$output\\application_log.csv\"\n\n# Memory acquisition (requires separate tool)\n# .\\memdump.exe \"$output\\memory.raw\"\n```\n\n**Linux Volatile Collection Script:**\n\n```bash\n#!/bin/bash\n# linux_forensics.sh\n\nOUTPUT=\"/forensics/$(date +%Y%m%d_%H%M%S)\"\nmkdir -p $OUTPUT\n\n# System time\ndate &gt; $OUTPUT/date.txt\ncat /proc/driver/rtc &gt; $OUTPUT/rtc.txt\n\n# System information\nuname -a &gt; $OUTPUT/uname.txt\ncat /etc/*release* &gt; $OUTPUT/release.txt\nhostname &gt; $OUTPUT/hostname.txt\nuptime &gt; $OUTPUT/uptime.txt\n\n# Network\nifconfig -a &gt; $OUTPUT/ifconfig.txt\nip addr show &gt; $OUTPUT/ipaddr.txt\nip route show &gt; $OUTPUT/route.txt\narp -a &gt; $OUTPUT/arp.txt\nnetstat -tupan &gt; $OUTPUT/netstat.txt\nnetstat -rn &gt; $OUTPUT/routing.txt\nss -tulpn &gt; $OUTPUT/ss.txt\niptables-save &gt; $OUTPUT/iptables.txt\n\n# Processes\nps auxf &gt; $OUTPUT/ps.txt\npstree &gt; $OUTPUT/pstree.txt\nlsof &gt; $OUTPUT/lsof.txt\nlsmod &gt; $OUTPUT/lsmod.txt\n\n# Users\nw &gt; $OUTPUT/w.txt\nwho &gt; $OUTPUT/who.txt\nlast &gt; $OUTPUT/last.txt\nlastlog &gt; $OUTPUT/lastlog.txt\n\n# Filesystems\nmount &gt; $OUTPUT/mount.txt\ndf -h &gt; $OUTPUT/df.txt\nfdisk -l &gt; $OUTPUT/fdisk.txt\n\n# Memory (requires LiME)\n# insmod lime.ko \"path=$OUTPUT/memory.lime format=lime\"\n\n# Hash all collected files\ncd $OUTPUT &amp;&amp; sha256sum * &gt; hashes.txt\n```\n\n---\n\n### 4.4 Forensic Imaging Techniques\n\n#### Bit-by-Bit Imaging\n\nBit-for-bit imaging creates a perfect duplicate of source media, including slack space and unallocated areas.\n\n**Imaging Types:**\n\n| Type | Copies | Includes | Use Case |\n|------|--------|----------|----------|\n| Physical/Bit-for-bit | All sectors | Everything | Complete preservation |\n| Logical | Active files only | File system only | Quick collection |\n| Sparse | Specific areas | Selected data | Targeted collection |\n\n**Hardware Write Blockers:**\n- Connect between source drive and imaging computer\n- Prevent any writes to source\n- Required for evidence admissibility\n- Types: FireWire, USB, SATA, IDE\n\n**dd (Data Duplicator):**\n\n```bash\n# Basic image\ndd if=/dev/sda of=/evidence/case001.dd bs=4M conv=noerror,sync status=progress\n\n# With compression\ndd if=/dev/sda bs=4M | gzip -c &gt; /evidence/case001.dd.gz\n\n# Network imaging (receiver)\nnc -l -p 9999 | dd of=/evidence/case001.dd bs=4M\n\n# Network imaging (sender)\ndd if=/dev/sda bs=4M | nc 192.168.1.100 9999\n\n# Split into parts\ndd if=/dev/sda bs=4M | split -b 2G - /evidence/case001.dd.\n\n# Verify with hash\ndd if=/dev/sda bs=4M | tee &gt;(sha256sum &gt; /evidence/case001.sha256) &gt; /evidence/case001.dd\n```\n\n**Guymager (GUI Tool):**\n- User-friendly interface\n- Multiple output formats (DD, E01, AFF)\n- Automatic hashing\n- Verification after imaging\n- Detailed logging\n\n**FTK Imager (Windows):**\n- Create disk images\n- Mount images for viewing\n- Capture memory\n- Create directory listings\n- Export files\n\n**E01 (EnCase) Format:**\n```\nHeader (Case info, examiner, notes)\n    \u2193\nCompressed data chunks\n    \u2193\nCRC32 per chunk\n    \u2193\nMD5 hash of entire image\n    \u2193\nTrailer with metadata\n```\n\n**AFF (Advanced Forensic Format):**\n- Open format\n- Compression support\n- Metadata stored with image\n- Encryption support\n- Segmentation support\n\n#### Logical Imaging\n\nLogical imaging only copies active files and directories, not free space.\n\n**When to Use:**\n- Large drives with time constraints\n- Cloud storage collection\n- Mobile device logical extraction\n- Targeted collection by file type\n\n**Tools:**\n```bash\n# rsync logical copy\nrsync -av /source/ /destination/\n\n# tar with preservation\ntar cvpf logical_backup.tar --atime-preserve /source/\n\n# FTK Imager logical\n# Add source folder \u2192 Export files\n```\n\n#### Network Acquisition\n\nImaging across networks introduces challenges but may be necessary.\n\n**Network Imaging Considerations:**\n- Bandwidth limitations\n- Network reliability\n- Encryption requirements\n- Authentication\n- Chain of custody\n\n**Tools for Network Acquisition:**\n\n```bash\n# netcat (unencrypted)\n# Receiver\nnc -l -p 9999 | dd of=evidence.dd\n# Sender\ndd if=/dev/sda | nc receiver_ip 9999\n\n# cryptcat (encrypted)\n# Same as netcat but with encryption\n\n# socat (advanced networking)\nsocat OPENSSL-LISTEN:4443,cert=server.pem,verify=0,fork \\\n    OPEN:evidence.dd,create,append\n\n# dd over SSH\ndd if=/dev/sda | ssh user@server \"dd of=evidence.dd\"\n```\n\n**Remote Forensic Acquisition Tools:**\n- **F-Response:** SANE protocol for remote access\n- **EnCase Enterprise:** Remote acquisition\n- **FTK Enterprise:** Network-enabled\n- **GRR (Google Rapid Response):** Live response\n\n---\n\n### 4.5 Hashing Algorithms\n\n#### MD5 Weaknesses\n\nMD5 (Message Digest 5) produces 128-bit hash values but is no longer considered cryptographically secure.\n\n**MD5 Collision Example:**\n\nTwo different files with same MD5 hash:\n```\nFile 1: \nd131dd02c5e6eec4693d9a0698aff95c\n2fcab58712467eab4004583eb8fb7f89\n55ad340609f4b30283e488832571415a\n085125e8f7cdc99fd91dbdf280373c5b\nd8823e3156348f5bae6dacd436c919c6\ndd53e2b487da03fd02396306d248cda0\ne99f33420f577ee8ce54b67080a80d1e\nc69821bcb6a8839396f9652b6ff72a70\n\nFile 2:\nd131dd02c5e6eec4693d9a0698aff95c\n2fcab50712467eab4004583eb8fb7f89\n55ad340609f4b30283e488832571415a\n085125e8f7cdc99fd91dbdf280373c5b\nd8823e3156348f5bae6dacd436c919c6\ndd53e2b487da03fd02396306d248cda0\ne99f33420f577ee8ce54b67080a80d1e\nc69821bcb6a8839396f9652b6ff72a70\n```\n\n**Forensic Implications:**\n- MD5 alone insufficient for evidence authentication\n- Should not be used for cryptographic verification\n- Still useful for non-critical identification\n- Use additional algorithms for verification\n\n#### SHA Family\n\nSHA (Secure Hash Algorithm) family provides stronger hashing.\n\n**SHA Variants:**\n\n| Algorithm | Output Size | Security Status | Use in Forensics |\n|-----------|-------------|-----------------|-------------------|\n| SHA-1 | 160 bits | Broken (collisions found) | Deprecated |\n| SHA-256 | 256 bits | Secure | Standard |\n| SHA-512 | 512 bits | Secure | High-security |\n| SHA-3 | Variable | Latest standard | Emerging |\n\n**Practical Usage:**\n\n```bash\n# Calculate SHA-256\nsha256sum evidence.dd &gt; evidence.sha256\n\n# Verify\nsha256sum -c evidence.sha256\n\n# Multiple algorithms\nshasum -a 1 -a 256 -a 512 evidence.dd\n\n# Windows PowerShell\nGet-FileHash -Algorithm SHA256 evidence.dd\n```\n\n#### Collision Risks\n\nUnderstanding collision probabilities is important for evidence admissibility.\n\n**Birthday Paradox:**\n- Probability of finding two files with same hash\n- For 256-bit hash: 2^128 operations theoretically\n- Practically impossible with current technology\n\n**Forensic Standard:**\n- Use multiple hash algorithms\n- Document hash values in reports\n- Verify immediately after imaging\n- Re-verify before court\n\n**Chain of Custody Hashing:**\n```\nStep 1: Calculate hash at acquisition\nStep 2: Document hash in chain of custody\nStep 3: Recalculate before analysis (verify match)\nStep 4: Recalculate before court (verify match)\nStep 5: Present all hash verifications\n```\n\n---\n\n### 4.6 Documentation &amp; Reporting Standards\n\nDocumentation is as important as the evidence itself.\n\n**Case Documentation Requirements:**\n\n1. **Incident Report:**\n   - Date/time of incident\n   - Reporting party\n   - Nature of incident\n   - Initial observations\n\n2. **Chain of Custody:**\n   - Every person handling evidence\n   - Dates and times\n   - Purpose of handling\n   - Condition of evidence\n\n3. **Examination Log:**\n   - Date/time of examination\n   - Tools used (with versions)\n   - Actions performed\n   - Findings\n   - Any issues encountered\n\n4. **Image Documentation:**\n   - Source drive information (model, serial, size)\n   - Imaging method\n   - Hash values (pre and post)\n   - Verification results\n   - Storage location\n\n**Report Structure:**\n\n```\nCASE REPORT\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n1. CASE INFORMATION\n   - Case number\n   - Investigator\n   - Date of report\n   - Classification\n\n2. EXECUTIVE SUMMARY\n   - Brief overview of findings\n   - Key evidence discovered\n   - Conclusions\n\n3. EVIDENCE LIST\n   - Itemized evidence with hash values\n   - Chain of custody summary\n\n4. EXAMINATION DETAILS\n   - Methodology\n   - Tools used (with versions)\n   - Step-by-step analysis\n   - Screenshots and documentation\n\n5. FINDINGS\n   - Detailed findings\n   - Timeline of events\n   - Relevant artifacts\n   - Correlation with other evidence\n\n6. CONCLUSIONS\n   - Summary of findings\n   - Expert opinions\n   - Recommendations\n\n7. APPENDICES\n   - Raw data exports\n   - Tool output\n   - Hash verification\n   - Chain of custody forms\n   - Glossary\n```\n\n**Tool Documentation Standards:**\n\n```markdown\nTool Documentation Template:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nTool Name: FTK Imager\nVersion: 4.7.1\nDeveloper: AccessData\nHash: SHA256: 1a2b3c...\nUsage: Created forensic image of evidence item EX-001\nParameters: Source: \\\\.\\PhysicalDrive1, Destination: EX-001.E01\nOutput: EX-001.E01, EX-001.txt (log)\nVerification: SHA256 match: 9f8e7d...\nNotes: No errors during imaging\n```\n\n**Court-Ready Documentation:**\n- Use third-person narrative\n- Avoid technical jargon in summaries\n- Include definitions of technical terms\n- Reference specific evidence items\n- Include visual aids (timelines, diagrams)\n- Document negative findings (what wasn't found)\n\n---\n\n## Chapter 5 \u2013 Forensic Tools &amp; Lab Setup\n\n---\n\n### 5.1 Building a Forensic Lab\n\n#### Hardware Requirements\n\n**Workstation Specifications:**\n\n| Component | Minimum | Recommended | High-End |\n|-----------|---------|-------------|----------|\n| CPU | i7 (8 cores) | Xeon/Threadripper (16+ cores) | Dual Xeon (32+ cores) |\n| RAM | 32GB | 64GB | 128GB+ |\n| Storage | 4TB | 8TB RAID | 20TB+ RAID |\n| OS Drive | 500GB SSD | 1TB NVMe | 2TB NVMe |\n\n**Forensic Bays:**\n\n```\nWrite Blockers (Hardware):\n- Tableau TD3 (SATA/SAS)\n- WiebeTech Forensic UltraDock\n- CRU WiebeTech DriveBay\n\nWrite Blockers (Software):\n- FTK Imager (with write-block enabled)\n- Linux with mount options\n```\n\n**Evidence Storage:**\n- Secure, access-controlled room\n- Environmental controls (temp/humidity)\n- Fire suppression\n- Backup power\n- Redundant storage\n- Off-site backup\n\n**Additional Equipment:**\n- Faraday bags (mobile devices)\n- Anti-static mats/wrist straps\n- Screwdriver sets (all types)\n- Soldering equipment\n- Chip programmer\n- Logic analyzer\n- Spectrum analyzer (RF forensics)\n\n#### Write Blockers\n\nWrite blockers are essential for evidence integrity.\n\n**Hardware Write Blockers:**\n\n```\nTableau TD3 (SATA/SAS):\n- Write-block verified by NIST\n- Activity LEDs\n- Power control\n- Multiple drive support\n- Forensic mode\n\nWiebeTech Forensic UltraDock:\n- Hot-swappable\n- Multiple interfaces\n- UAS support\n- Hardware write-protect\n```\n\n**Software Write Blockers:**\n\nWindows Registry:\n```\n[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\StorageDevicePolicies]\n\"WriteProtect\"=dword:00000001\n```\n\nLinux mount:\n```bash\n# Read-only mount\nmount -o ro /dev/sdb1 /mnt/evidence\n\n# Block device read-only\nblockdev --setro /dev/sdb\n```\n\n**Write Blocker Testing:**\n```\nBefore each use:\n1. Connect drive (non-evidence)\n2. Attempt write (should fail)\n3. Verify no modifications\n4. Document test\n```\n\n#### Faraday Bags\n\nFaraday bags block electromagnetic signals, preventing remote wiping and network connections.\n\n**When to Use:**\n- Mobile phone seizure\n- Tablets\n- Smart watches\n- GPS devices\n- Key fobs\n- Any cellular/WiFi device\n\n**Proper Usage:**\n```\n1. Power off device (if safe)\n2. Place in inner bag\n3. Remove air (seal)\n4. Place in outer bag\n5. Test with phone call\n6. Document containment\n```\n\n**Types:**\n- Single-use mylar bags\n- Multi-use military-grade\n- Portable tents (large devices)\n- Mesh pouches (signal attenuation)\n\n---\n\n### 5.2 Commercial Tools\n\n#### EnCase Deep Workflow\n\nEnCase is the industry standard for forensic investigations.\n\n**EnCase Features:**\n- Evidence processing\n- File signature analysis\n- Email analysis\n- Registry viewer\n- Scripting (EnScript)\n- Reporting\n\n**Workflow:**\n\n```\n1. CASE CREATION\n   - New case\n   - Case information\n   - Examiner details\n\n2. EVIDENCE ADDITION\n   - Add evidence file (.E01)\n   - Verify hash\n   - Add to case\n\n3. PROCESSING\n   - Recover deleted files\n   - File signature analysis\n   - Hash analysis (NSRL)\n   - Indexing\n   - Encryption detection\n\n4. EXAMINATION\n   - File system browser\n   - Keyword search\n   - Bookmark evidence\n   - Timeline analysis\n   - Registry viewer\n   - Email parser\n\n5. REPORTING\n   - Bookmark report\n   - Case report\n   - Export evidence\n```\n\n**Key EnCase Concepts:**\n\n| Concept | Description | Forensic Use |\n|---------|-------------|--------------|\n| Evidence Files | Container format (.E01) | Store images |\n| Case File | Case metadata (.case) | Case management |\n| EnScripts | Automation scripts | Custom processing |\n| Conditions | Filter criteria | Evidence filtering |\n| Queries | Search definitions | Complex searches |\n\n**EnScript Examples:**\n```\n- File carver (recover by signature)\n- Registry parser (extract artifacts)\n- Timeline creator (super timeline)\n- Hash analyzer (compare to NSRL)\n```\n\n#### FTK Workflow\n\nForensic Toolkit (FTK) by AccessData offers powerful processing and indexing.\n\n**FTK Features:**\n- Distributed processing\n- Advanced indexing\n- Email analysis\n- Data carving\n- KFF (Known File Filter)\n- PRTK (Password Recovery)\n\n**Workflow:**\n\n```\n1. CASE CREATION\n   - Case wizard\n   - Examiner information\n   - Case options\n\n2. EVIDENCE ADDITION\n   - Add evidence items\n   - Processing options\n   - Indexing selection\n\n3. PROCESSING\n   - MD5/SHA hash calculation\n   - File signature analysis\n   - Compound file analysis\n   - Email extraction\n   - Thumbnail generation\n   - Text extraction\n   - Data carving\n\n4. EXAMINATION\n   - File list view\n   - Filtering\n   - Search (indexed)\n   - Email view\n   - Graphics view\n   - Bookmarks\n\n5. REPORTING\n   - Bookmark report\n   - File list report\n   - Custom templates\n   - Export\n```\n\n**FTK Distributed Processing:**\n- Master node coordinates\n- Worker nodes process evidence\n- Scales for large cases\n- Reduces processing time\n\n---\n\n### 5.3 Open Source Tools\n\n#### Autopsy\n\nAutopsy is the graphical interface to The Sleuth Kit, offering comprehensive forensic capabilities.\n\n**Features:**\n- Timeline analysis\n- Keyword search\n- File system browsing\n- EXIF metadata extraction\n- Email analysis\n- Registry analysis\n- LNK file analysis\n- Web artifact analysis\n\n**Installation:**\n```bash\n# Linux\napt-get install autopsy\n\n# Windows\n# Download installer from autopsy.com\n\n# macOS\nbrew install autopsy\n```\n\n**Basic Workflow:**\n\n```python\n# Autopsy Python module example\nfrom org.sleuthkit.autopsy.ingest import IngestManager\nfrom org.sleuthkit.autopsy.casemodule import Case\n\n# Create case\ncase = Case.create(\"CaseName\", \"ExaminerName\", \"CaseDirectory\")\n\n# Add data source\ncase.addImage(\"evidence.dd\", \"SATA Drive\", 0)\n\n# Run ingest modules\ningest = IngestManager.getInstance()\ningest.execute(case.getDataSource(0))\n\n# Access results\nfrom org.sleuthkit.autopsy.coreutils import FileUtil\nfile_results = FileUtil.findFiles(dataSource, \"keyword\", 0)\n```\n\n**Autopsy Modules:**\n\n| Module | Function |\n|--------|----------|\n| File Ingestion | File processing |\n| Hash Lookup | NSRL comparison |\n| Keyword Search | Indexed searching |\n| Email Parser | PST/OST extraction |\n| Extension Mismatch | File signature analysis |\n| EXIF Parser | Metadata extraction |\n| Recent Activity | Registry analysis |\n\n#### The Sleuth Kit (TSK)\n\nTSK is the command-line backbone of many forensic tools.\n\n**Key TSK Commands:**\n\n| Command | Function | Example |\n|---------|----------|---------|\n| mmstat | Partition info | `mmstat image.dd` |\n| mmls | List partitions | `mmls image.dd` |\n| fsstat | File system info | `fsstat -o 2048 image.dd` |\n| fls | List files/dirs | `fls -o 2048 image.dd` |\n| icat | Output file by inode | `icat -o 2048 image.dd 1234` |\n| ils | List inode info | `ils -o 2048 image.dd` |\n| jls | List journal entries | `jls -o 2048 image.dd` |\n| tsk_recover | Recover files | `tsk_recover -o 2048 image.dd output/` |\n| sorter | Automated analysis | `sorter -f ntfs image.dd` |\n\n**TSK Workflow Example:**\n\n```bash\n# Examine partition layout\nmmls evidence.dd\n\n# Output:\n# 00: ------ 0000000000 0000000000 0001953525 0x00 (Unused)\n# 01: Linux 0001953525 0001953795 0000000271 0x82 (Linux swap)\n# 02: Linux 0001953795 0390624999 0388671205 0x83 (Linux files)\n\n# Access partition 2 (offset 0001953795 sectors * 512 = 10003445760 bytes)\nfsstat -o 10003445760 evidence.dd\n\n# List root directory\nfls -o 10003445760 evidence.dd\n\n# Recover deleted files\ntsk_recover -o 10003445760 evidence.dd recovered/\n```\n\n#### Volatility\n\nVolatility is the premier memory forensics framework.\n\n**Installation:**\n```bash\n# pip installation\npip install volatility3\n\n# From source\ngit clone https://github.com/volatilityfoundation/volatility3.git\ncd volatility3\npython setup.py install\n```\n\n**Basic Commands:**\n\n```bash\n# List plugins\npython vol.py -f memory.dmp --info\n\n# Get image info\npython vol.py -f memory.dmp windows.info\n\n# List processes\npython vol.py -f memory.dmp windows.pslist\npython vol.py -f memory.dmp windows.psscan\npython vol.py -f memory.dmp windows.pstree\n\n# List network connections\npython vol.py -f memory.dmp windows.netstat\n\n# List DLLs\npython vol.py -f memory.dmp windows.dlllist --pid 1234\n\n# Dump process\npython vol.py -f memory.dmp windows.memdump --pid 1234 --dump\n\n# Extract command line\npython vol.py -f memory.dmp windows.cmdline\n\n# Registry hives\npython vol.py -f memory.dmp windows.hivelist\npython vol.py -f memory.dmp windows.printkey --key \"ControlSet001\\Control\"\n\n# Malfind (find injected code)\npython vol.py -f memory.dmp windows.malfind\n```\n\n**Plugin Categories:**\n\n| Category | Plugins | Function |\n|----------|---------|----------|\n| Process | pslist, psscan, pstree | Process enumeration |\n| Network | netscan, netstat | Network artifacts |\n| Registry | hivelist, printkey | Registry analysis |\n| Files | filescan, dumpfiles | File recovery |\n| Malware | malfind, apihooks | Malware detection |\n| Kernel | modules, drivers | Kernel artifacts |\n\n**Volatility 3 vs 2:**\n- Python 3 support\n- Faster processing\n- Better symbol handling\n- Layer architecture\n- Plugin system redesigned\n\n#### Plaso (log2timeline)\n\nPlaso creates super timelines from multiple sources.\n\n**Installation:**\n```bash\n# pip\npip install plaso\n\n# Ubuntu\napt-get install plaso-tools\n\n# From source\ngit clone https://github.com/log2timeline/plaso.git\ncd plaso\npython setup.py install\n```\n\n**Workflow:**\n\n```bash\n# Create timeline from image\nlog2timeline.py --storage-file case.plaso evidence.dd\n\n# Add additional sources\nlog2timeline.py --storage-file case.plaso --append event_logs.evtx\n\n# Process multiple partitions\nlog2timeline.py --storage-file case.plaso --partitions all evidence.dd\n\n# Generate output\npsort.py -o l2tcsv -w timeline.csv case.plaso\n\n# Filter timeline\npsort.py -o l2tcsv -w filtered.csv \"date &gt; '2023-01-01' AND source == 'WINREG'\"\n\n# Timeline analysis\npinfo.py case.plaso  # Information about timeline\n```\n\n**Plaso Parsers:**\n\n| Parser | Source | Artifacts |\n|--------|--------|-----------|\n| winreg | Registry | User activity, system config |\n| winevt | Event logs | Security, system events |\n| filestat | File system | MAC times |\n| sqlite | SQLite DBs | Browser history, app data |\n| plist | Property lists | macOS preferences |\n| utmp | Login records | User sessions |\n| prefecth | Windows Prefetch | Program execution |\n\n---\n\n### 5.4 Automation &amp; Scripting\n\n#### Python for Forensics\n\nPython is the language of choice for forensic automation.\n\n**Essential Python Libraries:**\n\n| Library | Purpose | Example |\n|---------|---------|---------|\n| pytsk3 | File system access | Read disk images |\n| pyewf | E01 image support | Access EnCase images |\n| dfVFS | Virtual file system | Multi-format support |\n| registry | Registry parsing | Windows registry |\n| pefile | PE file analysis | Malware analysis |\n| yara | Pattern matching | Malware detection |\n| volatility3 | Memory analysis | Plugin development |\n\n**File System Access Example:**\n\n```python\nimport pytsk3\nimport pyewf\n\n# Open E01 image\newf_handle = pyewf.handle()\newf_handle.open('evidence.E01')\n\n# Create TSK image\nimg_info = pytsk3.img_info(ewf_handle)\n\n# Open partition\nvolume = pytsk3.volume(img_info)\nfor part in volume:\n    print(f\"Partition {part.addr}: {part.desc}\")\n\n# Access file system\nfilesystem = pytsk3.fs_info(img_info)\ndirectory = filesystem.open_dir(path=\"/\")\nfor f in directory:\n    print(f.info.name.name)\n```\n\n**Registry Parsing:**\n\n```python\nfrom Registry import Registry\n\n# Open registry hive\nreg = Registry.Registry('NTUSER.DAT')\n\n# Get user activity\nkey = reg.open('Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Explorer\\\\RecentDocs')\nfor value in key.values():\n    print(f\"{value.name()}: {value.value()}\")\n\n# Typed URLs\nkey = reg.open('Software\\\\Microsoft\\\\Internet Explorer\\\\TypedURLs')\nfor value in key.values():\n    print(f\"{value.name()}: {value.value()}\")\n```\n\n**File Carving:**\n\n```python\nimport re\n\ndef carve_jpegs(image_path, output_dir):\n    \"\"\"Simple JPEG carver\"\"\"\n    JPEG_HEADER = b'\\xff\\xd8\\xff'\n    JPEG_FOOTER = b'\\xff\\xd9'\n    \n    with open(image_path, 'rb') as f:\n        data = f.read()\n    \n    # Find all JPEG headers\n    offsets = [m.start() for m in re.finditer(JPEG_HEADER, data)]\n    \n    for i, start in enumerate(offsets):\n        # Find next footer after header\n        footer_pos = data.find(JPEG_FOOTER, start + 2)\n        if footer_pos &gt; start:\n            # Extract JPEG\n            jpeg_data = data[start:footer_pos + 2]\n            with open(f\"{output_dir}/carved_{i}.jpg\", 'wb') as out:\n                out.write(jpeg_data)\n                print(f\"Carved JPEG {i}: {len(jpeg_data)} bytes\")\n```\n\n#### PowerShell Artifact Extraction\n\nPowerShell is invaluable for Windows live response.\n\n**System Information:**\n\n```powershell\n# Comprehensive system info\n$sysinfo = [PSCustomObject]@{\n    ComputerName = $env:COMPUTERNAME\n    OS = (Get-WmiObject Win32_OperatingSystem).Caption\n    Version = (Get-WmiObject Win32_OperatingSystem).Version\n    LastBoot = (Get-WmiObject Win32_OperatingSystem).LastBootUpTime\n    Uptime = (Get-Date) - (Get-WmiObject Win32_OperatingSystem).ConvertToDateTime(\n        (Get-WmiObject Win32_OperatingSystem).LastBootUpTime\n    )\n    TimeZone = (Get-TimeZone).DisplayName\n    Domain = (Get-WmiObject Win32_ComputerSystem).Domain\n}\n$sysinfo | Export-Csv system_info.csv -NoTypeInformation\n```\n\n**Process Analysis:**\n\n```powershell\n# Detailed process list with network connections\n$processes = Get-Process | ForEach-Object {\n    $proc = $_\n    $connections = netstat -ano | Where-Object {$_ -match $proc.Id}\n    \n    [PSCustomObject]@{\n        PID = $proc.Id\n        Name = $proc.ProcessName\n        Path = $proc.Path\n        CPU = $proc.CPU\n        Memory = $proc.WorkingSet / 1MB\n        Connections = $connections -join \"; \"\n        Started = $proc.StartTime\n        Company = (Get-Item $proc.Path -ErrorAction SilentlyContinue |\n            Select-Object -ExpandProperty VersionInfo).CompanyName\n    }\n}\n$processes | Export-Csv processes.csv -NoTypeInformation\n```\n\n**Registry Artifacts:**\n\n```powershell\n# Extract USB history\n$usbKeys = Get-ChildItem \"HKLM:\\SYSTEM\\CurrentControlSet\\Enum\\USBSTOR\" -Recurse -ErrorAction SilentlyContinue\n$usbDevices = foreach($key in $usbKeys) {\n    $values = Get-ItemProperty $key.PSPath\n    [PSCustomObject]@{\n        FriendlyName = $values.FriendlyName\n        Serial = $key.PSChildName\n        Class = $values.Class\n        FirstInstall = $key.LastWriteTime\n    }\n}\n$usbDevices | Export-Csv usb_history.csv -NoTypeInformation\n\n# Recent documents\n$recentDocs = Get-ChildItem \"HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RecentDocs\" |\n    Get-ItemProperty |\n    Select-Object -ExpandProperty PSObject.Properties |\n    Where-Object {$_.Name -match \"^[0-9]+$\"}\n$recentDocs | Export-Csv recent_docs.csv -NoTypeInformation\n```\n\n**Event Log Extraction:**\n\n```powershell\n# Extract security events with details\n$events = Get-WinEvent -LogName Security -MaxEvents 10000 | ForEach-Object {\n    [PSCustomObject]@{\n        TimeCreated = $_.TimeCreated\n        ID = $_.Id\n        Level = $_.LevelDisplayName\n        User = $_.Properties[0].Value  # Often user in first property\n        Computer = $_.MachineName\n        Message = $_.Message\n    }\n}\n$events | Export-Csv security_events.csv -NoTypeInformation\n\n# Failed logons\n$failedLogons = Get-WinEvent -FilterHashtable @{\n    LogName='Security'\n    ID=4625\n} -MaxEvents 1000 | ForEach-Object {\n    $xml = [xml]$_.ToXml()\n    [PSCustomObject]@{\n        Time = $_.TimeCreated\n        User = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'TargetUserName'} | Select-Object -ExpandProperty '#text'\n        IP = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'IpAddress'} | Select-Object -ExpandProperty '#text'\n        Process = $xml.Event.EventData.Data | Where-Object {$_.Name -eq 'ProcessName'} | Select-Object -ExpandProperty '#text'\n    }\n}\n$failedLogons | Export-Csv failed_logons.csv -NoTypeInformation\n```\n\n**File System Timeline:**\n\n```powershell\n# Create timeline of recent file activity\n$timeline = Get-ChildItem C:\\ -Recurse -ErrorAction SilentlyContinue |\n    Where-Object {$_.LastWriteTime -gt (Get-Date).AddDays(-7)} |\n    ForEach-Object {\n        [PSCustomObject]@{\n            Path = $_.FullName\n            LastWrite = $_.LastWriteTime\n            LastAccess = $_.LastAccessTime\n            Creation = $_.CreationTime\n            Size = $_.Length\n            Attributes = $_.Attributes\n        }\n    }\n$timeline | Export-Csv file_timeline.csv -NoTypeInformation\n```\n\n**Memory Acquisition:**\n\n```powershell\n# Using built-in tools for memory capture\n$memoryFile = \"C:\\forensics\\memory_$(Get-Date -Format 'yyyyMMdd_HHmmss').raw\"\n\n# Use winpmem if available\nif (Test-Path \".\\winpmem_mini_x64_rc2.exe\") {\n    .\\winpmem_mini_x64_rc2.exe $memoryFile\n}\n\n# Alternative using FTK Imager CLI\nif (Test-Path \"C:\\Program Files\\AccessData\\FTK Imager\\ftkimager.exe\") {\n    &amp; \"C:\\Program Files\\AccessData\\FTK Imager\\ftkimager.exe\" memory $memoryFile\n}\n\n# Hash the memory capture\n$hash = Get-FileHash $memoryFile -Algorithm SHA256\n$hash | Out-File \"$memoryFile.sha256\"\n```\n\n---\n\n# PART III \u2013 DISK &amp; FILE SYSTEM FORENSICS\n\n---\n\n## Chapter 6 \u2013 NTFS &amp; Windows Artifact Forensics\n\n---\n\n### 6.1 MFT Forensic Parsing\n\nThe Master File Table (MFT) is the most critical artifact in NTFS forensics. Every file and folder on an NTFS volume has at least one entry in the MFT, making it a comprehensive record of all file system activity.\n\n#### MFT Entry Structure Deep Dive\n\nEach MFT entry is typically 1024 bytes (although this can vary) and begins with a standard header. Understanding this structure allows examiners to recover critical information even when files are deleted or partially overwritten.\n\n**MFT Header (First 42 bytes):**\n\n| Offset | Field | Size | Description | Forensic Value |\n|--------|-------|------|-------------|----------------|\n| 0x00 | Signature | 4 bytes | \"FILE\" (0x454C4946) for valid entries | Quick validation |\n| 0x04 | Update Offset | 2 bytes | Offset to fixup array | Data integrity |\n| 0x06 | Update Count | 2 bytes | Number of fixup entries | Fixup validation |\n| 0x08 | $LogFile LSN | 8 bytes | Last LSN modifying this entry | Transaction tracking |\n| 0x10 | Sequence Number | 2 bytes | Incremented when entry reused | Detects deletion/recreation |\n| 0x12 | Hard Link Count | 2 bytes | Number of directory entries | Multiple names/paths |\n| 0x14 | Attribute Offset | 2 bytes | Offset to first attribute | Navigation |\n| 0x16 | Flags | 2 bytes | 0x01=InUse, 0x02=Directory | File/folder status |\n| 0x18 | Entry Size | 4 bytes | Size of this MFT entry | Slack space calculation |\n| 0x1C | Allocated Size | 4 bytes | Size allocated on disk | Deleted entry detection |\n| 0x20 | File Reference | 8 bytes | Base file record | Extended entries |\n| 0x28 | Next Attribute ID | 2 bytes | ID for next attribute | Attribute counting |\n| 0x2A | Record Number | 4 bytes | Index of this entry | Location tracking |\n\n**Forensic Gold in the Header:**\n\nThe **Sequence Number** is particularly valuable. Each time an MFT entry is reused (when a file is deleted and a new file created), this number increments. By examining sequence numbers, investigators can:\n- Determine if a file record has been reused\n- Estimate how many files have occupied this MFT slot\n- Detect anti-forensic tools that attempt to wipe MFT entries\n\nThe **Flags** field tells us immediately whether this entry is in use and whether it represents a file or directory. Deleted files will have this flag set to 0x00 (not in use) or 0x02 (directory not in use).\n\n#### Attribute Types and Their Forensic Significance\n\nFollowing the header are attributes. Each attribute has a standard header followed by attribute-specific data.\n\n**Standard Attribute Header (16 bytes):**\n\n| Offset | Field | Size | Description |\n|--------|-------|------|-------------|\n| 0x00 | Type ID | 4 bytes | Attribute type (e.g., 0x10 = $STANDARD_INFORMATION) |\n| 0x04 | Length | 4 bytes | Total attribute length |\n| 0x08 | Non-resident flag | 1 byte | 0=Resident, 1=Non-resident |\n| 0x09 | Name length | 1 byte | Length of attribute name |\n| 0x0A | Name offset | 2 bytes | Offset to attribute name |\n| 0x0C | Flags | 2 bytes | Compression, encryption, sparse |\n| 0x0E | Attribute ID | 2 bytes | Unique ID for this attribute |\n\n**For resident attributes** (data stored within MFT), after the header comes:\n| Offset | Size | Field |\n|--------|------|-------|\n| 0x10 | 4 bytes | Attribute content size |\n| 0x14 | 2 bytes | Offset to content |\n| 0x16 | 1 byte | Indexed flag |\n| 0x17 | 1 byte | Padding |\n| Then content at offset specified\n\n**For non-resident attributes** (data stored in clusters), after the header comes:\n| Offset | Size | Field |\n|--------|------|-------|\n| 0x10 | 8 bytes | Starting VCN |\n| 0x18 | 8 bytes | Last VCN |\n| 0x20 | 2 bytes | Data runs offset |\n| 0x22 | 2 bytes | Compression unit size |\n| 0x24 | 4 bytes | Padding |\n| 0x28 | 8 bytes | Allocated size |\n| 0x30 | 8 bytes | Actual size |\n| 0x38 | 8 bytes | Initialized size |\n| Then data runs at offset specified\n\n#### Critical MFT Attributes\n\n**$STANDARD_INFORMATION (0x10)**\n\nThis attribute contains basic file metadata and is frequently targeted by anti-forensic tools.\n\n```\nStructure:\n- Creation time (64-bit Windows timestamp)\n- Modification time\n- MFT modification time\n- Access time\n- File permissions (DOS attributes)\n- Maximum versions\n- Version number\n- Class ID\n- Owner ID\n- Security ID\n- Quota charged\n- USN Journal ID\n```\n\n**Forensic Significance:** Malware often modifies timestamps in this attribute to hide its activities. However, many anti-forensic tools miss the timestamps stored elsewhere.\n\n**$FILE_NAME (0x30)**\n\nThis attribute contains the file name and parent directory reference. A file can have multiple $FILE_NAME attributes (hard links, long vs short names).\n\n```\nStructure:\n- Parent directory file reference\n- Creation time\n- Modification time\n- MFT modification time\n- Access time\n- Allocated size\n- Actual size\n- Flags\n- Extended attributes size\n- Name length\n- Name namespace (POSIX, Win32, DOS, etc.)\n- File name (Unicode)\n```\n\n**Forensic Gold:** Comparing timestamps between $STANDARD_INFORMATION and $FILE_NAME often reveals timestamp manipulation. If they differ significantly, the file may have been tampered with.\n\n**$DATA (0x80)**\n\nThis is the actual file content. For small files (typically &lt; 700 bytes), the data is stored resident within the MFT entry itself.\n\n**Resident Data:** The file content is right there in the MFT. Even if the file is \"deleted,\" if the MFT entry hasn't been reused, the content remains accessible.\n\n**Non-Resident Data:** The attribute contains data runs that point to clusters on disk where the file content is stored.\n\n**Data Run Structure:**\n```\nEach data run: [Header][Length][Offset]\nHeader: 1 byte, high nibble = offset length, low nibble = length length\nLength: Variable length, little-endian, actual length in clusters\nOffset: Variable length, little-endian, relative offset to previous run\n```\n\n**Example Data Run Parsing:**\n```\nData run: 31 02 3A 01 34 12\n31 = 0x31 \u2192 length length = 1, offset length = 3\n02 = length = 2 clusters\n3A 01 34 = offset = 0x34013A (relative offset)\n```\n\nThis points to 2 clusters starting at offset 0x34013A from the previous run.\n\n**$INDEX_ROOT and $INDEX_ALLOCATION (0x90, 0xA0)**\n\nThese attributes store directory information. Directories are actually special files containing indexes of their contents.\n\n**$INDEX_ROOT:** For small directories, contains the index entries directly.\n**$INDEX_ALLOCATION:** For large directories, contains index buffers stored outside the MFT.\n\n**Index Entry Structure:**\n- File reference (MFT entry of the file)\n- Index entry length\n- Stream length\n- Flags (0x01=Has subnode, 0x02=Last entry)\n- File name length\n- File name\n- Padding\n\n#### Deleted File Recovery from MFT\n\nWhen a file is deleted in NTFS:\n\n1. The MFT entry's Flags field changes from 0x01 (in use) to 0x00 (not in use)\n2. The $BITMAP attribute marks the file's clusters as available\n3. The file's directory entry is removed (but may remain in index buffers)\n4. The MFT entry's Sequence Number increments\n5. All attributes remain intact until overwritten\n\n**Recovery Process:**\n\n```python\nimport pytsk3\nimport sys\n\ndef recover_deleted_mft_entries(image_path, partition_offset):\n    \"\"\"Extract and analyze MFT entries to find deleted files\"\"\"\n    \n    # Open image\n    img = pytsk3.Img_Info(image_path)\n    \n    # Open partition\n    fs = pytsk3.FS_Info(img, offset=partition_offset)\n    \n    # Get MFT info\n    mft = fs.open_meta(file=0)  # MFT itself is file 0\n    \n    # Read MFT in chunks\n    mft_size = mft.info.meta.size\n    mft_entry_size = 1024  # Typical size\n    num_entries = mft_size // mft_entry_size\n    \n    recovered_files = []\n    \n    for i in range(num_entries):\n        # Read this MFT entry\n        entry_data = mft.read_random(i * mft_entry_size, mft_entry_size)\n        \n        # Check signature\n        if entry_data[0:4] != b'FILE':\n            continue\n            \n        # Check flags (0x00 = deleted, 0x01 = in use)\n        flags = int.from_bytes(entry_data[0x16:0x18], 'little')\n        \n        if flags &amp; 0x01 == 0:  # Not in use (deleted)\n            # Parse attributes to find filename\n            attr_offset = int.from_bytes(entry_data[0x14:0x16], 'little')\n            \n            while attr_offset &lt; mft_entry_size:\n                attr_type = int.from_bytes(\n                    entry_data[attr_offset:attr_offset+4], 'little'\n                )\n                attr_len = int.from_bytes(\n                    entry_data[attr_offset+4:attr_offset+8], 'little'\n                )\n                \n                if attr_type == 0x30:  # $FILE_NAME\n                    # Extract filename\n                    name_len = entry_data[attr_offset+0x58]\n                    name_offset = attr_offset + 0x5A\n                    filename = entry_data[name_offset:name_offset+name_len*2].decode(\n                        'utf-16le', errors='ignore'\n                    ).strip('\\x00')\n                    \n                    # Extract timestamps\n                    create_time = int.from_bytes(\n                        entry_data[attr_offset+0x18:attr_offset+0x20], 'little'\n                    )\n                    \n                    recovered_files.append({\n                        'record_number': i,\n                        'filename': filename,\n                        'create_time': create_time,\n                        'flags': flags\n                    })\n                    \n                if attr_len == 0:\n                    break\n                    \n                attr_offset += attr_len\n    \n    return recovered_files\n\n# Usage\ndeleted = recover_deleted_mft_entries('evidence.dd', 2048 * 512)\nfor f in deleted:\n    print(f\"Record {f['record_number']}: {f['filename']}\")\n```\n\n**Manual MFT Parsing with TSK:**\n\n```bash\n# List all files including deleted\nfls -o 2048 -r evidence.dd\n\n# Show MFT entry details\nistat -o 2048 evidence.dd 12345\n\n# Extract specific MFT entry\nicat -o 2048 evidence.dd 12345 &gt; mft_entry_12345.bin\n\n# List deleted files only\nfls -o 2048 -d evidence.dd\n```\n\n---\n\n### 6.2 Prefetch Analysis\n\nPrefetch files are created by Windows to speed up application loading. Each time an application runs, Windows records information about the files it accesses and stores this in a .pf file in the %SystemRoot%\\Prefetch directory.\n\n#### Prefetch File Structure\n\n**Windows 10/11 Prefetch (.pf) Format:**\n\n| Offset | Size | Field | Description |\n|--------|------|-------|-------------|\n| 0x00 | 4 | Version | Format version |\n| 0x04 | 4 | Signature | \"SCCA\" |\n| 0x08 | 4 | File size | Total prefetch size |\n| 0x18 | 8 | Last run time | When program last executed |\n| 0x20 | 8 | Run count | Number of executions |\n| 0x48 | 4 | File metrics offset | Offset to file list |\n| 0x4C | 4 | File metrics count | Number of files accessed |\n| 0x68 | 4 | Trace chains offset | Volume information |\n| 0x70 | 4 | Volume info offset | Volume data |\n| 0x74 | 4 | Volume info size | Size of volume data |\n| Variable | | File list | Array of accessed files |\n| Variable | | Volume information | Volume paths and serials |\n\n**File Metrics Entry:**\n- Filename offset\n- Filename size\n- Number of runs\n- Run offsets\n\n#### Forensic Value of Prefetch\n\nPrefetch provides:\n- **Execution history:** Every time a program runs (up to 128 executions per program)\n- **First execution time:** When the program first ran\n- **Last execution time:** Most recent execution\n- **Run count:** How many times executed\n- **File access:** All files accessed during execution\n- **Volume information:** Source volume and path\n\n**What Prefetch Reveals:**\n\n```\nExample: NOTEPAD.EXE-12345678.pf\n- Application: Notepad\n- Hash: 12345678 (based on path)\n- Run count: 15\n- Last run: 2023-06-15 14:23:45\n- Accessed files:\n  - \\WINDOWS\\SYSTEM32\\NOTEPAD.EXE\n  - \\USERS\\JOHN\\DOCUMENTS\\SECRET.TXT\n  - \\WINDOWS\\SYSTEM32\\NTDLL.DLL\n```\n\n**Investigative Uses:**\n\n1. **Determine what applications were run:**\n   - Malware execution\n   - Unauthorized tools\n   - User activity\n\n2. **Establish timeline:**\n   - When malware first appeared\n   - Pattern of usage\n\n3. **Find accessed files:**\n   - What documents were opened with that application\n   - Data theft evidence\n\n4. **Identify USB launches:**\n   - Programs executed from external drives\n   - Path shows drive letter\n\n#### Prefetch Analysis Tools\n\n**PECmd (Prefetch Explorer Command Line):**\n\n```bash\n# Parse single prefetch file\nPECmd.exe -f C:\\Windows\\Prefetch\\NOTEPAD.EXE-12345678.pf\n\n# Parse all prefetch files\nPECmd.exe -d C:\\Windows\\Prefetch -o results.csv\n\n# Output with timeline\nPECmd.exe -d C:\\Windows\\Prefetch --csv timeline.csv\n```\n\n**Sample Output:**\n```\nProcessing NOTEPAD.EXE-12345678.pf\n\nCreated on: 2023-01-15 10:23:45\nModified on: 2023-06-15 14:25:12\nLast executed: 2023-06-15 14:23:45\nExecutions: 15\n\nVolume Information:\n  Serial Number: 1234-5678\n  Path: \\VOLUME{01abc234}\n  Creation: 2023-01-15 10:23:45\n\nAccessed Files:\n  1. \\WINDOWS\\SYSTEM32\\NOTEPAD.EXE\n  2. \\USERS\\JOHN\\DOCUMENTS\\SECRET.TXT\n  3. \\WINDOWS\\SYSTEM32\\NTDLL.DLL\n  4. \\USERS\\JOHN\\DESKTOP\\NOTES.TXT\n```\n\n**PowerShell Analysis:**\n\n```powershell\n# Extract prefetch information\n$prefetchDir = \"C:\\Windows\\Prefetch\"\n$results = @()\n\nGet-ChildItem $prefetchDir -Filter *.pf | ForEach-Object {\n    $file = $_\n    $bytes = [System.IO.File]::ReadAllBytes($file.FullName)\n    \n    # Check signature\n    $sig = [System.Text.Encoding]::ASCII.GetString($bytes[4..7])\n    if ($sig -ne \"SCCA\") { return }\n    \n    # Get run count and last run time\n    $runCount = [System.BitConverter]::ToUInt32($bytes, 0x20)\n    $lastRun = [System.BitConverter]::ToUInt64($bytes, 0x18)\n    \n    # Convert Windows file time\n    if ($lastRun -gt 0) {\n        $lastRunTime = [DateTime]::FromFileTime($lastRun)\n    }\n    \n    $results += [PSCustomObject]@{\n        FileName = $_.Name\n        Executable = ($_.Name -split '\\.')[0]\n        RunCount = $runCount\n        LastRun = $lastRunTime\n        Created = $_.CreationTime\n        Modified = $_.LastWriteTime\n    }\n}\n\n$results | Sort-Object LastRun -Descending | Export-Csv prefetch.csv\n```\n\n#### Prefetch Limitations and Anti-Forensics\n\n**Limitations:**\n- Only enabled by default on desktop OS (not servers)\n- Limited to 128 executions (older entries overwritten)\n- Only tracks GUI applications (some services excluded)\n- Can be disabled via group policy\n- Not available on SSDs with TRIM enabled in some Windows versions\n\n**Anti-Forensics:**\n- Attackers may delete prefetch files\n- Modify timestamps within prefetch\n- Disable prefetch entirely via registry\n- Run tools from locations that don't generate prefetch\n\n**Detection of Prefetch Tampering:**\n- Gap in prefetch timeline (missing files)\n- Inconsistent timestamps\n- Deleted prefetch files may be recoverable\n- Event logs may show service disable\n\n---\n\n### 6.3 Shimcache (AppCompatCache)\n\nShimcache, also known as AppCompatCache, is a registry artifact that tracks program execution. Unlike Prefetch, it works on all Windows versions and cannot be easily disabled.\n\n#### Registry Location\n\n**Windows Registry Paths:**\n\n```\nWindows 7/Server 2008:\nSYSTEM\\CurrentControlSet\\Control\\Session Manager\\AppCompatCache\n\nWindows 8/10/11/Server 2012/2016/2019:\nSYSTEM\\CurrentControlSet\\Control\\Session Manager\\AppCompatCache\n```\n\nThe data is stored in a binary value named \"AppCompatCache\" (Windows 7) or in a binary format that varies by OS version.\n\n#### Data Structure by Windows Version\n\n**Windows XP/2003:**\n- 12 entries maximum\n- Simple list of filenames\n- No timestamps\n\n**Windows Vista/7/2008:**\n- 512 entries (32-bit) or 1024 entries (64-bit)\n- Filename and last modified time\n- Not in order of execution\n\n**Windows 8/10/2012/2016:**\n- Up to 1024 entries\n- Filename, last modified time, and last update time\n- Additional flags\n- Cached across reboots\n\n**Windows 10 (1703+) and Windows 11:**\n- Different structure (AppCompatCache renamed)\n- Filename, standard information timestamps\n- Multiple entries per file possible\n\n#### Forensic Value\n\nShimcache provides:\n- **Program execution:** Every executed file leaves an entry\n- **Last modified time:** When the file was last modified\n- **Last update time:** When the cache entry was updated\n- **Execution timeline:** Approximate execution time (based on cache updates)\n\n**What Shimcache Reveals:**\n\n```\nEntry 1:\nPath: C:\\Users\\John\\Downloads\\malware.exe\nLast Modified: 2023-06-15 10:23:45\nLast Update: 2023-06-15 10:24:12\nFlag: 0x02 (Executed)\n\nEntry 2:\nPath: C:\\Windows\\System32\\cmd.exe\nLast Modified: 2023-04-10 05:30:22\nLast Update: 2023-06-15 10:30:45\nFlag: 0x02 (Executed)\n```\n\n**Investigative Uses:**\n- Identify malware execution\n- Timeline of activities\n- Verify other artifacts (Prefetch, Event Logs)\n- Detect file execution even if deleted\n\n#### Shimcache Analysis Tools\n\n**AppCompatCacheParser (Eric Zimmerman):**\n\n```bash\n# Parse Shimcache from registry hive\nAppCompatCacheParser.exe --csv output --csvf shimcache.csv -f SYSTEM\n\n# Parse from live system\nAppCompatCacheParser.exe --csv output --csvf shimcache.csv\n```\n\n**Sample Output:**\n```\nControlSet001\\Control\\Session Manager\\AppCompatCache\n\nEntry,Path,Last Modified Time UTC,Last Update Time UTC,Flag\n1,C:\\Windows\\System32\\userinit.exe,2023-01-15 10:23:45,2023-06-15 08:15:22,0x02\n2,C:\\Windows\\System32\\winlogon.exe,2023-01-15 10:23:47,2023-06-15 08:15:23,0x02\n3,C:\\Users\\John\\AppData\\Local\\Temp\\malware.exe,2023-06-15 14:23:45,2023-06-15 14:24:12,0x02\n```\n\n**PowerShell Extraction:**\n\n```powershell\n# Extract Shimcache from offline SYSTEM hive\nfunction Get-Shimcache {\n    param($SystemHive)\n    \n    reg load HKLM\\TempSys $SystemHive\n    \n    $paths = @()\n    $key = \"HKLM:\\TempSys\\ControlSet001\\Control\\Session Manager\\AppCompatCache\"\n    \n    if (Test-Path $key) {\n        $value = (Get-ItemProperty -Path $key).AppCompatCache\n        \n        # Parse based on OS version (simplified)\n        # Windows 7 structure\n        $offset = 0\n        while ($offset -lt $value.Length - 16) {\n            $pathBytes = $value[$offset..($offset+512)]\n            $path = [System.Text.Encoding]::Unicode.GetString($pathBytes).Trim(\"`0\")\n            \n            if ($path.Length -gt 0) {\n                $timestamp = [System.BitConverter]::ToInt64($value, $offset+512)\n                if ($timestamp -gt 0) {\n                    $time = [DateTime]::FromFileTime($timestamp)\n                }\n                \n                $paths += [PSCustomObject]@{\n                    Path = $path\n                    LastModified = $time\n                }\n            }\n            $offset += 528\n        }\n    }\n    \n    reg unload HKLM\\TempSys\n    return $paths\n}\n\nGet-Shimcache \"C:\\evidence\\SYSTEM\" | Export-Csv shimcache.csv\n```\n\n#### Shimcache vs Prefetch\n\n| Feature | Shimcache | Prefetch |\n|---------|-----------|----------|\n| Windows versions | All | Desktop only |\n| Persistence | Registry (permanent) | Files (may be deleted) |\n| Capacity | 512-1024 entries | 128 entries per program |\n| Timestamps | Last modified | Last execution time |\n| Run count | No | Yes |\n| Files accessed | No | Yes |\n| Anti-forensics | Hard to clear | Easy to delete |\n| Forensic value | High for execution | High for details |\n\n---\n\n### 6.4 Amcache\n\nAmcache (Application Compatibility Cache) is a more recent artifact that tracks program execution and installation with greater detail.\n\n#### Amcache Hive Location\n\n```\n%SystemRoot%\\AppCompat\\Programs\\Amcache.hve\n```\n\nThe Amcache.hve file is a registry hive that can be loaded and parsed like any other registry hive.\n\n#### Key Amcache Tables\n\n**InventoryApplicationFile Table:**\n- Program executables\n- File paths\n- File sizes\n- Modification times\n- Hash values (SHA1)\n- Product names\n- Publisher information\n- Version numbers\n\n**InventoryApplication Table:**\n- Installed applications\n- Installation times\n- Publisher information\n- Uninstall keys\n- Version data\n\n**InventoryDeviceContainer:**\n- Connected devices\n- USB devices\n- Device classes\n- Friendly names\n\n**InventoryDevicePnp:**\n- Plug and Play devices\n- Hardware IDs\n- Driver information\n\n#### Forensic Value\n\nAmcache provides:\n- **Full program details:** Not just execution, but complete metadata\n- **Installed applications:** Complete list of installed software\n- **USB device history:** Detailed device information\n- **File hashes:** SHA1 of executables (for threat intelligence)\n- **Deletion records:** When programs were uninstalled\n- **First execution:** When a program first ran\n- **Last execution:** Most recent execution (some versions)\n\n**What Amcache Reveals:**\n\n```\nInventoryApplicationFile:\nPath: C:\\Program Files\\Malware\\malware.exe\nSHA1: 1A2B3C4D5E6F7890...\nSize: 245760 bytes\nModified: 2023-06-15 10:23:45\nProduct Name: Malicious Software\nPublisher: Unknown\nVersion: 1.0.0.0\nProgramId: {GUID}\n\nInventoryApplication:\nName: Malicious Software\nPublisher: Unknown\nVersion: 1.0.0.0\nInstallDate: 2023-06-15 10:23:45\nUninstallKey: {GUID}\n```\n\n#### Amcache Analysis Tools\n\n**AmcacheParser (Eric Zimmerman):**\n\n```bash\n# Parse Amcache hive\nAmcacheParser.exe -f Amcache.hve --csv output\n\n# Output includes multiple CSV files:\n# - Amcache_InventoryApplication.csv\n# - Amcache_InventoryApplicationFile.csv\n# - Amcache_InventoryDeviceContainer.csv\n# - Amcache_InventoryDriverBinary.csv\n```\n\n**Sample Output (InventoryApplicationFile.csv):**\n```\n\"ProgramId\",\"FileId\",\"Path\",\"Sha1\",\"Size\",\"FileDescription\",\"Modified\"\n\"{GUID1}\",\"{GUID2}\",\"C:\\Windows\\System32\\cmd.exe\",\"1A2B3C...\",\"296960\",\"Windows Command Processor\",\"2023-01-15 10:23:45\"\n\"{GUID3}\",\"{GUID4}\",\"C:\\Users\\John\\Downloads\\malware.exe\",\"9F8E7D...\",\"245760\",\"\",\"2023-06-15 14:23:45\"\n```\n\n**PowerShell Amcache Analysis:**\n\n```powershell\n# Load Amcache as registry hive\nreg load HKLM\\Amcache C:\\evidence\\Amcache.hve\n\n# Query installed applications\nGet-ChildItem \"HKLM:\\Amcache\\InventoryApplication\" -Recurse | ForEach-Object {\n    $props = Get-ItemProperty $_.PSPath\n    [PSCustomObject]@{\n        Name = $props.Name\n        Publisher = $props.Publisher\n        Version = $props.Version\n        InstallDate = if ($props.InstallDate) {\n            [DateTime]::ParseExact($props.InstallDate, \"yyyyMMdd\", $null)\n        }\n        UninstallKey = $props.UninstallKey\n    }\n} | Export-Csv amcache_apps.csv\n\n# Query executable files\nGet-ChildItem \"HKLM:\\Amcache\\InventoryApplicationFile\" -Recurse | ForEach-Object {\n    $props = Get-ItemProperty $_.PSPath\n    [PSCustomObject]@{\n        Path = $props.Path\n        Sha1 = $props.Sha1\n        Size = $props.Size\n        Modified = if ($props.LongModified) {\n            [DateTime]::FromFileTime($props.LongModified)\n        }\n        ProgramId = $props.ProgramId\n    }\n} | Export-Csv amcache_files.csv\n\nreg unload HKLM\\Amcache\n```\n\n#### Amcache Timeline Creation\n\n```python\nimport pandas as pd\nfrom datetime import datetime\n\ndef create_amcache_timeline(amcache_files):\n    \"\"\"Create timeline from Amcache data\"\"\"\n    \n    # Read Amcache CSV\n    df = pd.read_csv(amcache_files)\n    \n    timeline = []\n    \n    for _, row in df.iterrows():\n        # First seen (installation or first execution)\n        if pd.notna(row.get('InstallDate')):\n            timeline.append({\n                'timestamp': row['InstallDate'],\n                'event': 'Program Installed',\n                'details': f\"{row['Name']} v{row['Version']} by {row['Publisher']}\",\n                'source': 'Amcache'\n            })\n        \n        # File modified (may indicate execution or update)\n        if pd.notna(row.get('Modified')):\n            timeline.append({\n                'timestamp': row['Modified'],\n                'event': 'File Modified',\n                'details': row['Path'],\n                'source': 'Amcache'\n            })\n    \n    # Sort by timestamp\n    timeline.sort(key=lambda x: x['timestamp'])\n    \n    return timeline\n\ntimeline = create_amcache_timeline('amcache_files.csv')\nfor event in timeline:\n    print(f\"{event['timestamp']}: {event['event']} - {event['details']}\")\n```\n\n---\n\n### 6.5 LNK Artifacts\n\nWindows LNK (link) files are shortcuts created when users access files, providing rich forensic evidence.\n\n#### When LNK Files Are Created\n\n- **User opens a document:** LNK created in Recent folder\n- **USB device connection:** LNK files in Recent show drive letter\n- **File access via network:** LNK shows network path\n- **Program execution:** Start menu shortcuts\n- **Office documents:** Office creates LNK files in special folders\n\n#### LNK File Locations\n\n**User Recent Files:**\n```\n%UserProfile%\\Recent\\\n%UserProfile%\\AppData\\Roaming\\Microsoft\\Windows\\Recent\\\n%UserProfile%\\AppData\\Roaming\\Microsoft\\Office\\Recent\\\n```\n\n**AutomaticDestinations (Windows 7+):**\n```\n%UserProfile%\\AppData\\Roaming\\Microsoft\\Windows\\Recent\\AutomaticDestinations\\\n```\n\n**CustomDestinations:**\n```\n%UserProfile%\\AppData\\Roaming\\Microsoft\\Windows\\Recent\\CustomDestinations\\\n```\n\n#### LNK File Structure\n\n**LNK Header (0x4C bytes):**\n\n| Offset | Size | Field | Description |\n|--------|------|-------|-------------|\n| 0x00 | 4 | Header size | Always 0x4C |\n| 0x04 | 16 | Class identifier | CLSID_ShellLink |\n| 0x14 | 4 | Flags | Link flags (0x01=Has ID list, etc.) |\n| 0x18 | 4 | File attributes | Read-only, hidden, system |\n| 0x1C | 8 | Creation time | When target file created |\n| 0x24 | 8 | Access time | When target last accessed |\n| 0x2C | 8 | Write time | When target last modified |\n| 0x34 | 4 | File size | Target file size |\n| 0x38 | 4 | Icon index | Icon location |\n| 0x3C | 4 | Show command | Window state |\n| 0x40 | 2 | Hotkey | Keyboard shortcut |\n| 0x42 | 2 | Reserved | |\n| 0x44 | 4 | Reserved | |\n| 0x48 | 4 | Reserved | |\n\n**Following the header are optional structures based on flags:**\n\n1. **LinkTargetIDList** (if flag 0x01 set):\n   - Item ID list (Shell namespace paths)\n   - Reconstructs full path to target\n\n2. **LinkInfo** (if flag 0x02 set):\n   - Volume information\n   - Local path\n   - Network path\n   - Drive type\n   - Volume serial number\n\n3. **String Data** (if flags set):\n   - Name string\n   - Relative path\n   - Working directory\n   - Command line arguments\n   - Icon location\n\n#### Forensic Value of LNK Files\n\nLNK files provide:\n- **File access evidence:** What files were opened\n- **Timeline:** When files were accessed (three timestamps)\n- **Location information:** Where files were stored (including USB/network)\n- **Volume details:** Volume serial numbers (matches registry)\n- **File metadata:** Original file size and attributes\n- **MAC times:** Creation, modification, access of target\n\n**What LNK Reveals:**\n\n```\nLNK File: secret.docx.lnk\n\nTarget Information:\n- Full path: D:\\Documents\\secret.docx\n- Volume: D:\\ (removable)\n- Volume serial: 1234-5678\n- File size: 245760 bytes\n- Created: 2023-06-15 09:15:23\n- Modified: 2023-06-15 09:30:45\n- Accessed: 2023-06-15 09:30:45\n\nLNK File Metadata:\n- Created: 2023-06-15 09:31:12 (when shortcut created)\n- Modified: 2023-06-15 09:31:12\n- Accessed: 2023-06-15 09:31:12\n```\n\n**Investigative Uses:**\n- Prove file access (especially incriminating documents)\n- Identify external drives used (volume serial)\n- Reconstruct file system structure at time of access\n- Timeline user activity\n- Find files that have been deleted\n\n#### LNK Analysis Tools\n\n**LECmd (LNK Explorer Command Line):**\n\n```bash\n# Parse single LNK file\nLECmd.exe -f \"C:\\Users\\John\\Recent\\secret.docx.lnk\"\n\n# Parse all LNK files in directory\nLECmd.exe -d \"C:\\Users\\John\\Recent\" --csv output.csv\n\n# Parse AutomaticDestinations\nLECmd.exe -d \"C:\\Users\\John\\AppData\\Roaming\\Microsoft\\Windows\\Recent\\AutomaticDestinations\" --csv output.csv\n```\n\n**Sample Output:**\n```\nProcessing secret.docx.lnk\n\nLink Information:\n  Creation Time: 2023-06-15 09:31:12\n  Modification Time: 2023-06-15 09:31:12\n  Access Time: 2023-06-15 09:31:12\n  File Size: 245760 bytes\n\nTarget Information:\n  Full Path: D:\\Documents\\secret.docx\n  Working Directory: D:\\Documents\n  File Size: 245760 bytes\n  Creation Time: 2023-06-15 09:15:23\n  Modification Time: 2023-06-15 09:30:45\n  Access Time: 2023-06-15 09:30:45\n  File Attributes: Archive\n\nVolume Information:\n  Volume Type: Removable\n  Volume Serial: 1234-5678\n  Volume Label: USB DRIVE\n  Local Path: D:\\\n```\n\n**PowerShell LNK Parser:**\n\n```powershell\nfunction Parse-LNK {\n    param($LnkPath)\n    \n    $bytes = [System.IO.File]::ReadAllBytes($LnkPath)\n    \n    # Check signature (first 4 bytes should be 0x4C)\n    if ($bytes[0] -ne 0x4C) {\n        Write-Warning \"Not a valid LNK file\"\n        return\n    }\n    \n    # Parse header\n    $flags = [System.BitConverter]::ToUInt32($bytes, 0x14)\n    $fileAttrs = [System.BitConverter]::ToUInt32($bytes, 0x18)\n    $createTime = [System.BitConverter]::ToInt64($bytes, 0x1C)\n    $accessTime = [System.BitConverter]::ToInt64($bytes, 0x24)\n    $writeTime = [System.BitConverter]::ToInt64($bytes, 0x2C)\n    $fileSize = [System.BitConverter]::ToInt32($bytes, 0x34)\n    \n    $result = [PSCustomObject]@{\n        LnkPath = $LnkPath\n        LnkCreated = if ($createTime -gt 0) { [DateTime]::FromFileTime($createTime) }\n        LnkModified = if ($accessTime -gt 0) { [DateTime]::FromFileTime($accessTime) }\n        LnkAccessed = if ($writeTime -gt 0) { [DateTime]::FromFileTime($writeTime) }\n        TargetFileSize = $fileSize\n        Flags = \"0x$('{0:X}' -f $flags)\"\n        Attributes = $fileAttrs\n    }\n    \n    # Try to extract target path (simplified)\n    if ($flags -band 0x02) { # Has LinkInfo\n        # Parse LinkInfo structure\n        $linkInfoSize = [System.BitConverter]::ToUInt32($bytes, 0x4C)\n        $linkInfoHeaderSize = [System.BitConverter]::ToUInt32($bytes, 0x50)\n        $localPathOffset = [System.BitConverter]::ToUInt32($bytes, 0x60)\n        \n        if ($localPathOffset -gt 0) {\n            $pathBytes = $bytes[($linkInfoHeaderSize + $localPathOffset)..($bytes.Length - 2)]\n            $nullIndex = [Array]::IndexOf($pathBytes, 0x00)\n            if ($nullIndex -gt 0) {\n                $result.TargetPath = [System.Text.Encoding]::Unicode.GetString($pathBytes[0..($nullIndex-1)])\n            }\n        }\n    }\n    \n    return $result\n}\n\nParse-LNK \"C:\\evidence\\secret.docx.lnk\"\n```\n\n---\n\n### 6.6 Jump Lists\n\nJump Lists are an evolution of LNK files in Windows 7 and later, providing even more forensic detail.\n\n#### Jump List Types\n\n**AutomaticDestinations:**\n- Created automatically when programs are used\n- Stored as .automaticDestinations-ms files\n- Named by AppID (Application Identifier)\n- Contains recent items for that application\n\n**CustomDestinations:**\n- Created when users pin items to taskbar\n- Stored as .customDestinations-ms files\n- Named by user action\n- Shows user preferences\n\n#### Jump List Structure\n\nJump Lists are OLE compound files containing:\n- **DestList stream:** List of entries with timestamps\n- **Embedded LNK files:** Complete LNK data for each entry\n\n**DestList Entry Structure:**\n| Offset | Size | Field |\n|--------|------|-------|\n| 0x00 | 8 | Entry ID |\n| 0x08 | 8 | First access time |\n| 0x10 | 8 | Last access time |\n| 0x18 | 8 | Entry ID (again) |\n| 0x20 | 4 | Pin status (0=unpinned, 1=pinned) |\n| 0x24 | 4 | Entry count for this item |\n\n#### Forensic Value\n\nJump Lists provide:\n- **Application usage:** Which programs were used\n- **Recent files:** Complete history of opened files\n- **Access times:** First and last access for each file\n- **Pin status:** User's priority items\n- **Embedded LNK data:** Full file metadata\n\n**What Jump Lists Reveal:**\n\n```\nAppID: {1ac14e77-02e7-4e5d-b744-2eb1ae5198b7} (Windows Explorer)\n\nEntries:\n1. Path: C:\\Users\\John\\Documents\\secret.docx\n   First accessed: 2023-06-15 09:15:23\n   Last accessed: 2023-06-15 14:30:45\n   Access count: 4\n   Pin status: Unpinned\n\n2. Path: \\\\SERVER\\SHARE\\financial.xlsx\n   First accessed: 2023-06-14 10:23:45\n   Last accessed: 2023-06-15 11:15:22\n   Access count: 12\n   Pin status: Pinned\n```\n\n#### Jump List Analysis Tools\n\n**JLECmd (Jump List Explorer Command Line):**\n\n```bash\n# Parse AutomaticDestinations\nJLECmd.exe -d \"C:\\Users\\John\\AppData\\Roaming\\Microsoft\\Windows\\Recent\\AutomaticDestinations\" --csv output.csv\n\n# Parse specific file\nJLECmd.exe -f \"C:\\Users\\John\\AppData\\Roaming\\Microsoft\\Windows\\Recent\\AutomaticDestinations\\1ac14e77.automaticDestinations-ms\"\n```\n\n**Sample Output:**\n```\nProcessing 1ac14e77.automaticDestinations-ms\n\nAppID: {1ac14e77-02e7-4e5d-b744-2eb1ae5198b7}\nAppName: Windows Explorer\n\nEntry 1:\n  Target: C:\\Users\\John\\Documents\\secret.docx\n  First Access: 2023-06-15 09:15:23\n  Last Access: 2023-06-15 14:30:45\n  Access Count: 4\n  Pin Status: 0\n  LNK Data: (embedded)\n\nEntry 2:\n  Target: \\\\SERVER\\SHARE\\financial.xlsx\n  First Access: 2023-06-14 10:23:45\n  Last Access: 2023-06-15 11:15:22\n  Access Count: 12\n  Pin Status: 1\n  LNK Data: (embedded)\n```\n\n**PowerShell Jump List Extraction:**\n\n```powershell\nfunction Parse-JumpList {\n    param($JumpListPath)\n    \n    # Load OLE compound file\n    $storage = New-Object -ComObject \"Storage.Object\"\n    $storage.Open($JumpListPath)\n    \n    # Access DestList stream\n    $destList = $storage.OpenStream(\"DestList\")\n    $bytes = New-Object byte[] $destList.Size\n    $destList.Read($bytes, 0, $destList.Size)\n    \n    # Parse entries (simplified)\n    $entries = @()\n    $offset = 32 # Skip header\n    \n    while ($offset -lt $bytes.Length - 32) {\n        $entryId = [System.BitConverter]::ToUInt64($bytes, $offset)\n        $firstAccess = [System.BitConverter]::ToInt64($bytes, $offset + 8)\n        $lastAccess = [System.BitConverter]::ToInt64($bytes, $offset + 16)\n        $pinStatus = [System.BitConverter]::ToInt32($bytes, $offset + 32)\n        \n        if ($firstAccess -gt 0) {\n            $entries += [PSCustomObject]@{\n                EntryId = $entryId\n                FirstAccess = [DateTime]::FromFileTime($firstAccess)\n                LastAccess = [DateTime]::FromFileTime($lastAccess)\n                PinStatus = $pinStatus\n            }\n        }\n        \n        $offset += 40 # Entry size\n    }\n    \n    $storage.Close()\n    return $entries\n}\n\nParse-JumpList \"C:\\evidence\\1ac14e77.automaticDestinations-ms\"\n```\n\n---\n\n### 6.7 USB Device History\n\nUSB device forensics reveals external storage connections, crucial for data theft investigations.\n\n#### Registry USB Artifacts\n\n**USBSTOR (USB Storage):**\n```\nSYSTEM\\CurrentControlSet\\Enum\\USBSTOR\n```\n\nThis key contains entries for every USB storage device ever connected.\n\n**USBSTOR Subkey Structure:**\n```\nUSBSTOR\\Disk&amp;Ven_Vendor&amp;Prod_Product&amp;Rev_Version\\SerialNumber\n```\n\n**Properties under each device:**\n- **FriendlyName:** User-friendly device name\n- **Class:** Device class (usually \"USB\")\n- **Mfg:** Manufacturer\n- **Service:** Driver service (usually \"disk\")\n- **DeviceDesc:** Device description\n- **Capabilities:** Device capabilities\n- **CompatibleIDs:** Compatible device IDs\n- **HardwareID:** Hardware identifier\n\n**Example:**\n```\nKey: USBSTOR\\Disk&amp;Ven_SanDisk&amp;Prod_Ultra&amp;Rev_1.00\\123456789ABC\nValues:\n  FriendlyName: SanDisk Ultra USB Device\n  Mfg: SanDisk\n  Service: disk\n  DeviceDesc: USB Mass Storage Device\n```\n\n**USB (General USB Devices):**\n```\nSYSTEM\\CurrentControlSet\\Enum\\USB\n```\n\nContains all USB devices, not just storage:\n- Hubs\n- Input devices\n- Composite devices\n- Unknown devices\n\n**Mounted Devices:**\n```\nSYSTEM\\MountedDevices\n```\n\nShows drive letters assigned to volumes, including USB drives.\n\n**Volume Serial Numbers:**\n```\n\\??\\Volume{12345678-9abc-def0-1234-56789abcdef0}\n```\n\nEach volume has a unique GUID and shows:\n- Drive letter assignment\n- Volume serial number\n- Device type\n\n#### Setupapi.log / setupapi.dev.log\n\nLocated in `%SystemRoot%\\INF\\setupapi.dev.log`, this log records device installation events.\n\n**Key Information:**\n- Device installation start/end\n- Driver installation\n- Device removal\n- Error conditions\n- Timestamps\n\n**Example Entry:**\n```\n&gt;&gt;&gt;  [Device Install (Hardware initiated) - USB\\VID_0781&amp;PID_5583\\123456789ABC]\n&gt;&gt;&gt;  Section start 2023/06/15 14:23:45.123\n     cmd: PnP utility\n     ndv: USB\\VID_0781&amp;PID_5583\\123456789ABC\n     dvi: {D7B9D7B5-5D4A-4A5D-9F5D-5F5D5F5D5F5D}\n     dvs: {D7B9D7B5-5D4A-4A5D-9F5D-5F5D5F5D5F5D}\n     Section end 2023/06/15 14:23:46.234\n```\n\n#### Shellbags\n\nShellbags record folder views in Explorer and can show USB folder access.\n\n**Location:**\n```\nNTUSER.DAT\\Software\\Microsoft\\Windows\\Shell\\BagMRU\nNTUSER.DAT\\Software\\Microsoft\\Windows\\Shell\\Bags\n```\n\n**What Shellbags Reveal:**\n- Folders browsed on USB drives\n- Folder names and paths\n- First and last access times\n- Window positions and views\n\n#### Complete USB Investigation Workflow\n\n```python\nimport os\nimport Registry\n\ndef investigate_usb_history(registry_hives_path):\n    \"\"\"Complete USB history investigation\"\"\"\n    \n    results = []\n    \n    # 1. Load SYSTEM hive\n    system = Registry.Registry( os.path.join(registry_hives_path, 'SYSTEM'))\n    \n    # 2. Enumerate USBSTOR\n    try:\n        usbstor = system.open('ControlSet001\\\\Enum\\\\USBSTOR')\n        for device in usbstor.subkeys():\n            for instance in device.subkeys():\n                device_info = {}\n                \n                # Get device properties\n                for value in instance.values():\n                    device_info[value.name()] = value.value()\n                \n                # Get first/ last connection from timestamps\n                # (stored in subkey timestamps)\n                \n                results.append({\n                    'source': 'USBSTOR',\n                    'device_id': instance.name(),\n                    'friendly_name': device_info.get('FriendlyName', ''),\n                    'manufacturer': device_info.get('Mfg', ''),\n                    'serial': instance.name().split('&amp;')[-1],\n                    'first_seen': instance.timestamp(),\n                    'last_seen': instance.timestamp(),  # Approximate\n                })\n    except Registry.RegistryKeyNotFoundException:\n        pass\n    \n    # 3. Check MountedDevices for drive letters\n    try:\n        mounted = system.open('MountedDevices')\n        for value in mounted.values():\n            value_name = value.name()\n            if 'Volume' in value_name:\n                # Parse binary data for volume info\n                # (complex - varies by Windows version)\n                pass\n    except:\n        pass\n    \n    # 4. Check user hives for shellbags\n    for user_hive in ['NTUSER.DAT', 'UsrClass.dat']:\n        try:\n            user_reg = Registry.Registry(\n                os.path.join(registry_hives_path, user_hive)\n            )\n            \n            # Look for USB paths in BagMRU\n            try:\n                bagmru = user_reg.open('Software\\\\Microsoft\\\\Windows\\\\Shell\\\\BagMRU')\n                # Recursively enumerate for USB paths\n                # (D:\\, E:\\ etc.)\n                pass\n            except:\n                pass\n        except:\n            pass\n    \n    # 5. Parse setupapi logs\n    setup_log = os.path.join(os.environ['SystemRoot'], 'INF', 'setupapi.dev.log')\n    if os.path.exists(setup_log):\n        with open(setup_log, 'r', errors='ignore') as f:\n            for line in f:\n                if 'USB' in line and 'Device Install' in line:\n                    # Parse device installation events\n                    pass\n    \n    return results\n\n# Run investigation\nusb_history = investigate_usb_history('C:/evidence/Registry')\nfor device in usb_history:\n    print(f\"Device: {device['friendly_name']}\")\n    print(f\"  Serial: {device['serial']}\")\n    print(f\"  First seen: {device['first_seen']}\")\n    print(f\"  Last seen: {device['last_seen']}\")\n```\n\n#### USB Device Timeline Creation\n\n```python\ndef create_usb_timeline(usb_history, shellbags, setupapi):\n    \"\"\"Create comprehensive USB timeline\"\"\"\n    \n    timeline = []\n    \n    # Add USBSTOR events\n    for device in usb_history:\n        timeline.append({\n            'timestamp': device['first_seen'],\n            'event': 'USB Device Connected',\n            'details': f\"{device['friendly_name']} ({device['serial']})\",\n            'source': 'USBSTOR'\n        })\n        \n        if device['last_seen'] != device['first_seen']:\n            timeline.append({\n                'timestamp': device['last_seen'],\n                'event': 'USB Device Last Seen',\n                'details': f\"{device['friendly_name']} ({device['serial']})\",\n                'source': 'USBSTOR'\n            })\n    \n    # Add shellbag events (folder access)\n    for folder in shellbags:\n        if 'USB' in folder['path'] or folder['path'].startswith(('D:', 'E:', 'F:')):\n            timeline.append({\n                'timestamp': folder['accessed'],\n                'event': 'USB Folder Accessed',\n                'details': folder['path'],\n                'source': 'Shellbags'\n            })\n    \n    # Add setupapi events\n    for event in setupapi:\n        timeline.append({\n            'timestamp': event['time'],\n            'event': event['description'],\n            'details': event['details'],\n            'source': 'SetupAPI'\n        })\n    \n    # Sort chronologically\n    timeline.sort(key=lambda x: x['timestamp'])\n    \n    return timeline\n```\n\n---\n\n### 6.8 Recycle Bin Forensics\n\nThe Recycle Bin preserves deleted files with metadata essential for investigations.\n\n#### Recycle Bin Structure\n\n**Windows XP and earlier:**\n- INFO2 file in each drive's RECYCLER folder\n- Hidden folder: `C:\\RECYCLER\\SID\\`\n\n**Windows Vista and later:**\n- `$Recycle.Bin` folder on each drive\n- Subfolder for each user SID: `C:\\$Recycle.Bin\\S-1-5-21-...\\`\n\n**File Naming:**\n- Deleted files renamed to `$R[random].[ext]`\n- Metadata stored in `$I[random].[ext]` (same random name)\n\n#### $I File Structure\n\nThe $I file contains metadata about the deleted file:\n\n| Offset | Size | Field | Description |\n|--------|------|-------|-------------|\n| 0x00 | 8 | Header | \"$I\" + version (30 00 30 00 30 00 30 00) |\n| 0x08 | 8 | Original file size | Size before deletion |\n| 0x10 | 8 | Deletion time | When file was deleted |\n| 0x18 | 8 | Original file path length | Length in characters |\n| 0x20 | Variable | Original file path | Unicode path |\n\n**Example $I File:**\n```\nHeader: $I (30 00 30 00 30 00 30 00)\nSize: 245760 bytes\nDeleted: 2023-06-15 14:30:45\nPath: C:\\Users\\John\\Documents\\secret.docx\n```\n\n#### $R File\n\nThe $R file contains the actual file content:\n- May be partially overwritten\n- Original filename not preserved\n- Content remains until overwritten\n\n#### Forensic Value\n\nRecycle Bin provides:\n- **Deleted file recovery:** Content of deleted files\n- **Original paths:** Where files came from\n- **Deletion timestamps:** When files were deleted\n- **File sizes:** Original size (compare to recovered)\n- **User attribution:** Which user deleted (by SID folder)\n\n#### Recycle Bin Analysis Tools\n\n**PowerShell Recycle Bin Parser:**\n\n```powershell\nfunction Get-RecycleBin {\n    param($Drive = \"C:\")\n    \n    $recyclePath = Join-Path $Drive \"\\$Recycle.Bin\"\n    $results = @()\n    \n    # Get all user SID folders\n    Get-ChildItem $recyclePath -Directory | ForEach-Object {\n        $userFolder = $_.FullName\n        $sid = $_.Name\n        \n        # Find all $I files\n        Get-ChildItem \"$userFolder\\$I*\" | ForEach-Object {\n            $iFile = $_.FullName\n            $rFile = $iFile.Replace('\\$I', '\\$R')\n            \n            # Read $I file structure\n            $bytes = [System.IO.File]::ReadAllBytes($iFile)\n            \n            # Check header\n            if ($bytes[0] -ne 0x30 -or $bytes[1] -ne 0x00) {\n                return\n            }\n            \n            # Parse metadata\n            $fileSize = [System.BitConverter]::ToInt64($bytes, 0x08)\n            $deleteTime = [System.BitConverter]::ToInt64($bytes, 0x10)\n            $pathLength = [System.BitConverter]::ToInt32($bytes, 0x18)\n            \n            # Extract original path\n            $pathBytes = $bytes[0x1C..(0x1C + ($pathLength * 2) - 1)]\n            $originalPath = [System.Text.Encoding]::Unicode.GetString($pathBytes)\n            \n            # Get $R file info if exists\n            $rFileInfo = if (Test-Path $rFile) {\n                Get-ChildItem $rFile | Select-Object Length, LastWriteTime\n            }\n            \n            $results += [PSCustomObject]@{\n                SID = $sid\n                OriginalPath = $originalPath\n                OriginalSize = $fileSize\n                DeletedTime = [DateTime]::FromFileTime($deleteTime)\n                RecycleFile = $rFile\n                RecycledSize = if ($rFileInfo) { $rFileInfo.Length } else { 0 }\n                RecycledModified = if ($rFileInfo) { $rFileInfo.LastWriteTime } else { $null }\n                Recovered = (Test-Path $rFile)\n            }\n        }\n    }\n    \n    return $results\n}\n\n# Analyze recycle bin\n$deleted = Get-RecycleBin \"C:\"\n$deleted | Export-Csv recycle_bin.csv -NoTypeInformation\n```\n\n**FTK Imager:**\n- Browse to `C:\\$Recycle.Bin`\n- View $I files as metadata\n- Export $R files for recovery\n\n#### Recovering Specific Files\n\n```python\ndef recover_from_recycle_bin(recycle_path, target_filename_pattern):\n    \"\"\"Recover specific files from Recycle Bin\"\"\"\n    \n    import os\n    import struct\n    \n    recovered = []\n    \n    for root, dirs, files in os.walk(recycle_path):\n        for file in files:\n            if file.startswith('$I'):\n                i_path = os.path.join(root, file)\n                r_path = i_path.replace('$I', '$R')\n                \n                # Read $I file\n                with open(i_path, 'rb') as f:\n                    data = f.read()\n                \n                # Parse header\n                if len(data) &lt; 0x20:\n                    continue\n                \n                # Get path length\n                path_len = struct.unpack(' {download['path']}\"\n                })\n    \n    # Firefox events\n    if firefox_data:\n        for visit in firefox_data['history']:\n            if visit['visit_date']:\n                timeline.append({\n                    'timestamp': visit['visit_date'],\n                    'browser': 'Firefox',\n                    'event': 'Page Visit',\n                    'details': f\"{visit['url']} - {visit['title']}\"\n                })\n        \n        for download in firefox_data['downloads']:\n            if download['start']:\n                timeline.append({\n                    'timestamp': download['start'],\n                    'browser': 'Firefox',\n                    'event': 'Download Started',\n                    'details': f\"{download['source']} -&gt; {download['target']}\"\n                })\n    \n    # Sort chronologically\n    timeline.sort(key=lambda x: x['timestamp'])\n    \n    return timeline\n```\n\n#### Recovering Deleted Browser History\n\nWhen browser history is deleted, the SQLite databases may still contain recoverable data:\n\n```python\ndef recover_deleted_chrome_history(history_db_path):\n    \"\"\"Attempt recovery of deleted Chrome history entries\"\"\"\n    \n    # Open the database file directly for hex analysis\n    with open(history_db_path, 'rb') as f:\n        data = f.read()\n    \n    # Look for URL patterns in unallocated space\n    import re\n    \n    # Find HTTP/HTTPS URLs\n    url_pattern = re.compile(b'https?://[^\\\\s\"\\']+')\n    urls = url_pattern.findall(data)\n    \n    # Find timestamps (Windows file time format)\n    timestamp_pattern = re.compile(b'.{8}')  # 8-byte timestamps\n    \n    recovered = []\n    for url in urls[:100]:  # Limit for demo\n        try:\n            url_str = url.decode('utf-8', errors='ignore')\n            recovered.append({\n                'source': 'carved',\n                'url': url_str,\n                'timestamp': 'unknown (carved)'\n            })\n        except:\n            pass\n    \n    return recovered\n```\n\n---\n\n## Chapter 7 \u2013 Linux &amp; macOS Forensics\n\n---\n\n### 7.1 Linux Forensics Overview\n\nLinux systems present unique forensic challenges and opportunities due to their open-source nature and extensive logging capabilities.\n\n#### Key Linux Artifacts\n\n| Artifact | Location | Forensic Value |\n|----------|----------|----------------|\n| Bash history | ~/.bash_history | Commands executed |\n| Authentication logs | /var/log/auth.log | Logins, sudo usage |\n| System logs | /var/log/syslog | System events |\n| Package manager logs | /var/log/dpkg.log, /var/log/yum.log | Software installation |\n| Cron jobs | /var/spool/cron/, /etc/crontab | Scheduled tasks |\n| User accounts | /etc/passwd, /etc/shadow | User enumeration |\n| Last logins | /var/log/wtmp, /var/log/btmp | Login history |\n| Process accounting | /var/log/account/ | Process execution |\n| Audit logs | /var/log/audit/ | Security events |\n| Systemd journals | /var/log/journal/ | Comprehensive logging |\n\n---\n\n### 7.2 Bash History Recovery\n\nBash history records commands entered by users, providing a timeline of activities.\n\n#### Bash History Files\n\n**Primary locations:**\n- `~/.bash_history` (user-specific)\n- `~/.zsh_history` (Zsh)\n- `~/.history` (some shells)\n- `~/.sh_history` (Korn shell)\n\n**History Configuration:**\n```bash\n# History settings in ~/.bashrc\nexport HISTSIZE=1000          # Number of commands to keep in memory\nexport HISTFILESIZE=2000       # Number of commands in history file\nexport HISTTIMEFORMAT=\"%F %T \" # Add timestamps to history\nexport HISTCONTROL=ignoredups  # Don't save duplicate commands\nexport HISTIGNORE=\"ls:ps:history\" # Commands to ignore\n```\n\n#### Timestamped History\n\nIf `HISTTIMEFORMAT` is set, history includes timestamps:\n\n```bash\n# Example .bash_history with timestamps\n#1678951234\ncd /etc\n#1678951245\nls -la\n#1678951300\nnano /etc/passwd\n```\n\nFormat: `#` followed by the command\n\n#### Recovering Deleted Bash History\n\nEven when users delete their history, recovery is often possible:\n\n```python\ndef recover_bash_history(disk_image_path, username):\n    \"\"\"Recover bash history from unallocated space\"\"\"\n    \n    import re\n    import datetime\n    \n    with open(disk_image_path, 'rb') as f:\n        data = f.read()\n    \n    # Look for bash history entries\n    # Pattern: common Linux commands\n    commands = [\n        b'cd ', b'ls ', b'cat ', b'grep ', b'ssh ',\n        b'scp ', b'wget ', b'curl ', b'nano ', b'vim ',\n        b'rm ', b'mv ', b'cp ', b'mkdir ', b'touch ',\n        b'sudo ', b'apt ', b'yum ', b'dnf ', b'tar '\n    ]\n    \n    found = []\n    for cmd in commands:\n        for match in re.finditer(cmd, data):\n            # Get context around match\n            start = max(0, match.start() - 50)\n            end = min(len(data), match.end() + 100)\n            context = data[start:end]\n            \n            # Try to extract full command line\n            # (ends with newline or null)\n            cmd_line = b''\n            in_cmd = False\n            for byte in context:\n                if byte in (10, 0):  # newline or null\n                    if in_cmd:\n                        break\n                else:\n                    in_cmd = True\n                    cmd_line += bytes([byte])\n            \n            try:\n                cmd_str = cmd_line.decode('ascii', errors='ignore').strip()\n                if cmd_str and len(cmd_str) &gt; 3:\n                    found.append({\n                        'offset': match.start(),\n                        'command': cmd_str,\n                        'context': context[:100].hex()[:20] + '...'\n                    })\n            except:\n                pass\n    \n    return found\n```\n\n#### Bash History Analysis Script\n\n```python\ndef analyze_bash_history(history_path):\n    \"\"\"Analyze bash history for suspicious commands\"\"\"\n    \n    if not os.path.exists(history_path):\n        return []\n    \n    suspicious_patterns = [\n        'rm -rf', 'dd if=', 'chmod 777', 'sudo su',\n        'wget.*\\\\|', 'curl.*\\\\|', 'nc -l', 'ncat',\n        'chattr', '&gt; /dev/sda', 'mkfs', 'shred',\n        'ssh.*@', 'scp.*@', 'rsync.*@', 'ftp.*@',\n        'python -c', 'perl -e', 'php -r',\n        'base64 -d', 'openssl enc', 'gpg',\n        'crontab', 'at now', 'nohup'\n    ]\n    \n    with open(history_path, 'r', errors='ignore') as f:\n        lines = f.readlines()\n    \n    suspicious = []\n    timestamp = None\n    \n    for line in lines:\n        line = line.strip()\n        \n        # Check for timestamp\n        if line.startswith('#'):\n            try:\n                epoch = int(line[1:])\n                timestamp = datetime.fromtimestamp(epoch)\n            except:\n                pass\n            continue\n        \n        # Check for suspicious commands\n        for pattern in suspicious_patterns:\n            if pattern in line:\n                suspicious.append({\n                    'command': line,\n                    'timestamp': timestamp,\n                    'pattern': pattern,\n                    'line_number': lines.index(line)\n                })\n                break\n    \n    return suspicious\n\n# Usage\nsuspicious = analyze_bash_history('/evidence/home/user/.bash_history')\nfor cmd in suspicious:\n    print(f\"[{cmd['timestamp']}] {cmd['command']} (matches: {cmd['pattern']})\")\n```\n\n---\n\n### 7.3 Linux Authentication Forensics\n\nLinux maintains detailed authentication logs essential for intrusion detection.\n\n#### Authentication Logs\n\n**Primary Files:**\n- `/var/log/auth.log` (Debian/Ubuntu)\n- `/var/log/secure` (RHEL/CentOS)\n- `/var/log/messages` (some distros)\n\n**Key Events to Monitor:**\n\n```python\ndef parse_auth_log(log_path):\n    \"\"\"Parse Linux authentication logs\"\"\"\n    \n    import re\n    from datetime import datetime\n    \n    events = []\n    \n    # Regular expressions for different events\n    patterns = {\n        'ssh_login': re.compile(r'sshd.*Accepted password for (\\w+) from (\\d+\\.\\d+\\.\\d+\\.\\d+)'),\n        'ssh_failed': re.compile(r'sshd.*Failed password for (\\w+) from (\\d+\\.\\d+\\.\\d+\\.\\d+)'),\n        'sudo': re.compile(r'sudo: (\\w+) : .*COMMAND=(.*)'),\n        'useradd': re.compile(r'useradd.*new user: name=(\\w+),'),\n        'userdel': re.compile(r'userdel.*delete user (\\w+)'),\n        'groupadd': re.compile(r'groupadd.*new group: name=(\\w+),'),\n        'login': re.compile(r'login:.*LOGIN ON (.*) BY (\\w+)'),\n        'su': re.compile(r'su:.*session opened for user (\\w+) by (\\w+)'),\n        'cron': re.compile(r'CRON.*\\((\\w+)\\) CMD \\((.*)\\)'),\n    }\n    \n    with open(log_path, 'r', errors='ignore') as f:\n        for line in f:\n            # Parse timestamp (format varies)\n            try:\n                # Common format: \"Jun 15 10:23:45\"\n                parts = line.split()\n                if len(parts) &gt; 3:\n                    month = parts[0]\n                    day = parts[1]\n                    time = parts[2]\n                    # Create timestamp (assumes current year)\n                    timestamp = datetime.strptime(\n                        f\"{datetime.now().year} {month} {day} {time}\",\n                        \"%Y %b %d %H:%M:%S\"\n                    )\n                else:\n                    timestamp = None\n            except:\n                timestamp = None\n            \n            # Check each pattern\n            for event_type, pattern in patterns.items():\n                match = pattern.search(line)\n                if match:\n                    event = {\n                        'timestamp': timestamp,\n                        'type': event_type,\n                        'line': line.strip()\n                    }\n                    \n                    # Add specific fields based on event type\n                    if event_type == 'ssh_login':\n                        event['user'] = match.group(1)\n                        event['ip'] = match.group(2)\n                    elif event_type == 'ssh_failed':\n                        event['user'] = match.group(1)\n                        event['ip'] = match.group(2)\n                    elif event_type == 'sudo':\n                        event['user'] = match.group(1)\n                        event['command'] = match.group(2)\n                    elif event_type == 'useradd':\n                        event['user'] = match.group(1)\n                    \n                    events.append(event)\n                    break\n    \n    return events\n\n# Parse auth log\nauth_events = parse_auth_log('/evidence/var/log/auth.log')\n\n# Create timeline\nauth_events.sort(key=lambda x: x['timestamp'] or datetime.min)\n\n# Analyze suspicious activity\nfailed_attempts = [e for e in auth_events if e['type'] == 'ssh_failed']\nif len(failed_attempts) &gt; 10:\n    print(f\"Possible brute force attack: {len(failed_attempts)} failed attempts\")\n    \n    # Group by IP\n    from collections import Counter\n    ips = Counter([e['ip'] for e in failed_attempts if 'ip' in e])\n    for ip, count in ips.most_common(5):\n        print(f\"  {ip}: {count} attempts\")\n```\n\n#### User Account Forensics\n\n```python\ndef analyze_user_accounts(passwd_path, shadow_path):\n    \"\"\"Analyze user accounts from /etc/passwd and /etc/shadow\"\"\"\n    \n    users = []\n    \n    # Parse passwd\n    with open(passwd_path, 'r') as f:\n        for line in f:\n            parts = line.strip().split(':')\n            if len(parts) &gt;= 7:\n                users.append({\n                    'username': parts[0],\n                    'uid': int(parts[2]),\n                    'gid': int(parts[3]),\n                    'home': parts[5],\n                    'shell': parts[6],\n                    'source': 'passwd'\n                })\n    \n    # Parse shadow for password info\n    if os.path.exists(shadow_path):\n        with open(shadow_path, 'r') as f:\n            for line in f:\n                parts = line.strip().split(':')\n                if len(parts) &gt;= 8:\n                    username = parts[0]\n                    password = parts[1]\n                    \n                    # Find corresponding user\n                    for user in users:\n                        if user['username'] == username:\n                            user['password_hash'] = password\n                            user['last_change'] = parts[2]\n                            user['min_age'] = parts[3]\n                            user['max_age'] = parts[4]\n                            user['warning'] = parts[5]\n                            user['inactive'] = parts[6]\n                            user['expire'] = parts[7]\n                            \n                            # Check if password is locked/disabled\n                            if password.startswith('!') or password.startswith('*'):\n                                user['account_status'] = 'locked'\n                            elif password == '':\n                                user['account_status'] = 'no_password'\n                            else:\n                                user['account_status'] = 'has_password'\n                            break\n    \n    return users\n\nusers = analyze_user_accounts(\n    '/evidence/etc/passwd',\n    '/evidence/etc/shadow'\n)\n\n# Check for suspicious accounts\nfor user in users:\n    # Non-standard shells\n    if user['shell'] not in ['/bin/bash', '/bin/sh', '/bin/zsh']:\n        print(f\"Suspicious shell: {user['username']} uses {user['shell']}\")\n    \n    # Accounts with UID 0 (root) besides root\n    if user['uid'] == 0 and user['username'] != 'root':\n        print(f\"Privileged account: {user['username']} has UID 0\")\n    \n    # Accounts without passwords\n    if user.get('account_status') == 'no_password':\n        print(f\"No password: {user['username']}\")\n```\n\n---\n\n### 7.4 Cron Persistence Detection\n\nCron jobs are commonly used for persistence by both system administrators and attackers.\n\n#### Cron Locations\n\n```bash\n# System crontab\n/etc/crontab\n\n# System cron directories\n/etc/cron.d/\n/etc/cron.daily/\n/etc/cron.hourly/\n/etc/cron.weekly/\n/etc/cron.monthly/\n\n# User crontabs\n/var/spool/cron/crontabs/ (user-specific)\n/var/spool/cron/ (some distros)\n```\n\n#### Cron Analysis Script\n\n```python\ndef analyze_cron_jobs(root_path):\n    \"\"\"Analyze all cron jobs for suspicious entries\"\"\"\n    \n    suspicious = []\n    \n    # Locations to check\n    cron_locations = [\n        os.path.join(root_path, 'etc/crontab'),\n        os.path.join(root_path, 'etc/cron.d'),\n        os.path.join(root_path, 'var/spool/cron'),\n        os.path.join(root_path, 'var/spool/cron/crontabs'),\n    ]\n    \n    suspicious_patterns = [\n        'wget', 'curl', 'nc ', 'ncat', 'bash -i',\n        'base64 -d', 'chmod 777', '&gt;/dev/tcp/',\n        'mkfifo', 'mknod', 'socat', 'perl -e',\n        'python -c', 'php -r', 'ruby -e',\n        'openssl enc -d', 'gpg -d'\n    ]\n    \n    for location in cron_locations:\n        if os.path.isfile(location):\n            # Single file\n            analyze_cron_file(location, suspicious, suspicious_patterns)\n        elif os.path.isdir(location):\n            # Directory of cron files\n            for root, dirs, files in os.walk(location):\n                for file in files:\n                    file_path = os.path.join(root, file)\n                    analyze_cron_file(file_path, suspicious, suspicious_patterns)\n    \n    return suspicious\n\ndef analyze_cron_file(file_path, suspicious, patterns):\n    \"\"\"Analyze individual cron file\"\"\"\n    \n    try:\n        with open(file_path, 'r') as f:\n            lines = f.readlines()\n        \n        for line_num, line in enumerate(lines, 1):\n            line = line.strip()\n            \n            # Skip comments and empty lines\n            if not line or line.startswith('#'):\n                continue\n            \n            # Check each pattern\n            for pattern in patterns:\n                if pattern in line:\n                    suspicious.append({\n                        'file': file_path,\n                        'line': line_num,\n                        'content': line,\n                        'pattern': pattern\n                    })\n                    break\n            \n            # Check for unusual scheduling\n            parts = line.split()\n            if len(parts) &gt; 5:\n                # Common scheduling intervals\n                if parts[0] == '*':\n                    # Running every minute - suspicious for persistence\n                    suspicious.append({\n                        'file': file_path,\n                        'line': line_num,\n                        'content': line,\n                        'pattern': 'every_minute'\n                    })\n    except Exception as e:\n        print(f\"Error reading {file_path}: {e}\")\n\n# Run analysis\nsuspicious_crons = analyze_cron_jobs('/evidence')\nfor cron in suspicious_crons:\n    print(f\"\\nSuspicious cron: {cron['file']}:{cron['line']}\")\n    print(f\"  {cron['content']}\")\n    print(f\"  Reason: {cron['pattern']}\")\n```\n\n---\n\n### 7.5 Linux Log Tampering Detection\n\nAttackers often attempt to cover their tracks by modifying logs.\n\n#### Log Integrity Checks\n\n```python\ndef detect_log_tampering(log_path):\n    \"\"\"Detect signs of log tampering\"\"\"\n    \n    indicators = []\n    \n    if not os.path.exists(log_path):\n        return indicators\n    \n    # Check file metadata\n    stat = os.stat(log_path)\n    \n    # 1. Check for gaps in timestamps\n    timestamps = []\n    with open(log_path, 'r', errors='ignore') as f:\n        for line in f:\n            # Try to extract timestamp (simplified)\n            if len(line) &gt; 15:\n                try:\n                    # Common syslog format\n                    ts_str = line[0:15]\n                    # Would parse actual timestamp here\n                    timestamps.append(line[0:15])\n                except:\n                    pass\n    \n    # Check for unusual patterns\n    if len(timestamps) &gt; 0:\n        # Look for gaps (would need proper timestamp parsing)\n        pass\n    \n    # 2. Check for log rotation anomalies\n    log_dir = os.path.dirname(log_path)\n    log_base = os.path.basename(log_path)\n    \n    rotated = [f for f in os.listdir(log_dir) if f.startswith(log_base + '.')]\n    if rotated:\n        # Check if rotated logs are missing or have wrong permissions\n        pass\n    \n    # 3. Check for null bytes (often used to hide entries)\n    with open(log_path, 'rb') as f:\n        data = f.read()\n        if b'\\x00' in data:\n            indicators.append({\n                'type': 'null_bytes',\n                'description': 'Null bytes found in log file',\n                'severity': 'high'\n            })\n    \n    # 4. Check for unusual characters\n    unusual_chars = re.findall(rb'[^\\x20-\\x7e\\r\\n\\t]', data)\n    if len(unusual_chars) &gt; len(data) * 0.01:  # &gt;1% unusual\n        indicators.append({\n            'type': 'unusual_chars',\n            'description': f'{len(unusual_chars)} unusual characters found',\n            'severity': 'medium'\n        })\n    \n    # 5. Check file permissions\n    if stat.st_mode &amp; 0o777 != 0o644:  # Not standard permissions\n        indicators.append({\n            'type': 'bad_permissions',\n            'description': f'Unusual permissions: {oct(stat.st_mode &amp; 0o777)}',\n            'severity': 'low'\n        })\n    \n    # 6. Check if file was recently modified (after intrusion date)\n    # (would compare to known timeline)\n    \n    return indicators\n\n# Check all logs for tampering\nlog_files = [\n    '/evidence/var/log/auth.log',\n    '/evidence/var/log/syslog',\n    '/evidence/var/log/kern.log',\n    '/evidence/var/log/secure',\n]\n\nfor log in log_files:\n    if os.path.exists(log):\n        indicators = detect_log_tampering(log)\n        if indicators:\n            print(f\"\\nTampering indicators in {log}:\")\n            for i in indicators:\n                print(f\"  [{i['severity']}] {i['description']}\")\n```\n\n#### Recovering Deleted Log Entries\n\n```python\ndef recover_deleted_log_entries(disk_image_path, log_patterns):\n    \"\"\"Carve log entries from unallocated space\"\"\"\n    \n    with open(disk_image_path, 'rb') as f:\n        data = f.read()\n    \n    recovered = []\n    \n    # Common syslog patterns\n    for pattern in log_patterns:\n        # Find all occurrences\n        for match in re.finditer(pattern.encode(), data):\n            # Get surrounding context\n            start = max(0, match.start() - 100)\n            end = min(len(data), match.end() + 200)\n            context = data[start:end]\n            \n            # Try to extract full log line\n            # Find line boundaries\n            line_start = context.rfind(b'\\n', 0, 100) + 1\n            line_end = context.find(b'\\n', 200)\n            \n            if line_end &gt; line_start:\n                line = context[line_start:line_end]\n                try:\n                    line_str = line.decode('utf-8', errors='ignore')\n                    recovered.append({\n                        'offset': start + line_start,\n                        'content': line_str,\n                        'pattern': pattern\n                    })\n                except:\n                    pass\n    \n    return recovered\n\n# Recover SSH authentication entries\nrecovered = recover_deleted_log_entries(\n    'evidence.dd',\n    ['sshd.*Accepted', 'sshd.*Failed', 'sudo:']\n)\n\nfor entry in recovered[:20]:  # Show first 20\n    print(f\"Recovered: {entry['content']}\")\n```\n\n---\n\n### 7.6 macOS Forensics Deep Dive\n\nmacOS presents unique artifacts due to its Unix foundation with Apple-specific additions.\n\n#### macOS File System Layout\n\n```\n/System/           # System files (read-only)\n/Library/          # System-wide application support\n/Users/            # User home directories\n/Applications/     # Installed applications\n/private/          # Unix-style system files\n  /var/            # Logs, spool files\n  /etc/            # Configuration (symlink to /private/etc)\n  /tmp/            # Temporary files\n/Volumes/          # Mounted volumes\n/.fseventsd/       # File system events logs\n/.Spotlight-V100/  # Spotlight indexes\n```\n\n#### Key macOS Artifacts\n\n| Artifact | Location | Forensic Value |\n|----------|----------|----------------|\n| Unified Logs | /private/var/log/ | Comprehensive system logs |\n| System Logs | /var/log/system.log | Traditional syslog |\n| Install History | /Library/Receipts/ | Installed software |\n| User Data | /Users/[user]/ | User-specific artifacts |\n| Keychains | ~/Library/Keychains/ | Saved passwords |\n| Safari Data | ~/Library/Safari/ | Browser history |\n| Mail Data | ~/Library/Mail/ | Email artifacts |\n| iCloud Data | ~/Library/Mobile Documents/ | Cloud-synced files |\n| Time Machine | /Volumes/Backup/ | Backups |\n| Sleep Images | /private/var/vm/ | Memory sleep images |\n\n---\n\n### 7.7 macOS Unified Logs\n\nStarting with macOS 10.12 (Sierra), Apple introduced a unified logging system.\n\n#### Accessing Unified Logs\n\n```bash\n# Collect logs for a specific time period\nlog collect --last 1d --output system_logs.logarchive\n\n# Show logs for a specific process\nlog show --predicate 'process == \"kernel\"'\n\n# Export to text\nlog show --archive system_logs.logarchive &gt; logs.txt\n\n# Stream live logs\nlog stream --predicate 'eventMessage contains \"error\"'\n```\n\n#### Parsing Unified Logs with Python\n\n```python\nimport subprocess\nimport plistlib\nfrom datetime import datetime\n\ndef parse_unified_logs(logarchive_path):\n    \"\"\"Extract and parse macOS unified logs\"\"\"\n    \n    # Use log command to export\n    cmd = ['log', 'show', '--archive', logarchive_path, '--style', 'json']\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    \n    logs = []\n    for line in result.stdout.split('\\n'):\n        if line.strip():\n            try:\n                import json\n                entry = json.loads(line)\n                \n                log_entry = {\n                    'timestamp': datetime.fromisoformat(entry.get('timestamp', '')),\n                    'process': entry.get('process', ''),\n                    'sender': entry.get('sender', ''),\n                    'message': entry.get('eventMessage', ''),\n                    'level': entry.get('level', ''),\n                    'pid': entry.get('pid'),\n                    'activity': entry.get('activity'),\n                }\n                logs.append(log_entry)\n            except:\n                continue\n    \n    return logs\n\n# Analyze logs for suspicious activity\ndef analyze_macos_logs(logarchive_path):\n    \"\"\"Analyze macOS logs for security events\"\"\"\n    \n    logs = parse_unified_logs(logarchive_path)\n    \n    security_events = []\n    \n    for log in logs:\n        message = log['message'].lower()\n        \n        # SSH connections\n        if 'ssh' in message and 'accepted' in message:\n            security_events.append({\n                'type': 'ssh_login',\n                'timestamp': log['timestamp'],\n                'details': log['message']\n            })\n        \n        # Sudo usage\n        if 'sudo' in message and 'command' in message:\n            security_events.append({\n                'type': 'sudo_usage',\n                'timestamp': log['timestamp'],\n                'details': log['message']\n            })\n        \n        # Gatekeeper/Quarantine\n        if 'gatekeeper' in message or 'quarantine' in message:\n            security_events.append({\n                'type': 'gatekeeper',\n                'timestamp': log['timestamp'],\n                'details': log['message']\n            })\n        \n        # Application launches\n        if 'launch' in message and 'application' in message:\n            if 'malware' in message or 'unidentified' in message:\n                security_events.append({\n                    'type': 'suspicious_launch',\n                    'timestamp': log['timestamp'],\n                    'details': log['message']\n                })\n    \n    return security_events\n\n# Run analysis\nevents = analyze_macos_logs('system_logs.logarchive')\nfor event in events:\n    print(f\"[{event['timestamp']}] {event['type']}: {event['details']}\")\n```\n\n---\n\n### 7.8 macOS Spotlight Artifacts\n\nSpotlight maintains extensive indexes of user files.\n\n#### Spotlight Database Analysis\n\n```python\nimport sqlite3\nimport os\n\ndef analyze_spotlight(spotlight_path):\n    \"\"\"Extract forensic data from Spotlight index\"\"\"\n    \n    # Spotlight index is a SQLite database\n    index_db = os.path.join(spotlight_path, 'store.db')\n    \n    if not os.path.exists(index_db):\n        return None\n    \n    conn = sqlite3.connect(index_db)\n    cursor = conn.cursor()\n    \n    # Get table list\n    cursor.execute(\"SELECT name FROM sqlite_master WHERE type='table'\")\n    tables = cursor.fetchall()\n    \n    spotlight_data = {}\n    \n    # Common Spotlight tables\n    tables_of_interest = [\n        'files',           # File paths and metadata\n        'metadata',        # Extended attributes\n        'content',         # File content snippets\n        'search_history',  # User search terms\n        'bundle_data',     # Application bundles\n        'volume_info',     # Volume information\n    ]\n    \n    for table in tables_of_interest:\n        try:\n            cursor.execute(f\"SELECT * FROM {table} LIMIT 100\")\n            rows = cursor.fetchall()\n            \n            # Get column names\n            cursor.execute(f\"PRAGMA table_info({table})\")\n            columns = [col[1] for col in cursor.fetchall()]\n            \n            table_data = []\n            for row in rows:\n                row_dict = {}\n                for i, col in enumerate(columns):\n                    row_dict[col] = row[i]\n                table_data.append(row_dict)\n            \n            spotlight_data[table] = table_data\n            \n        except sqlite3.OperationalError:\n            # Table doesn't exist\n            pass\n    \n    conn.close()\n    return spotlight_data\n\n# Extract Spotlight data\nspotlight = analyze_spotlight('/evidence/.Spotlight-V100/Store-V1/')\n\n# Look for files matching keywords\nif 'files' in spotlight:\n    suspicious_files = []\n    keywords = ['password', 'secret', 'confidential', 'private', 'backup']\n    \n    for file in spotlight['files']:\n        path = file.get('path', '')\n        if any(keyword in path.lower() for keyword in keywords):\n            suspicious_files.append({\n                'path': path,\n                'inode': file.get('inode'),\n                'flags': file.get('flags')\n            })\n    \n    print(f\"Found {len(suspicious_files)} files with sensitive keywords\")\n    for f in suspicious_files[:10]:\n        print(f\"  {f['path']}\")\n\n# Check search history\nif 'search_history' in spotlight:\n    print(\"\\nUser search history:\")\n    for search in spotlight['search_history']:\n        print(f\"  {search.get('search_string')} - {search.get('timestamp')}\")\n```\n\n#### Recovering Deleted Spotlight Entries\n\n```python\ndef recover_deleted_spotlight_entries(spotlight_path):\n    \"\"\"Recover deleted entries from Spotlight journal\"\"\"\n    \n    journal_path = os.path.join(spotlight_path, 'journal')\n    \n    if not os.path.exists(journal_path):\n        return []\n    \n    with open(journal_path, 'rb') as f:\n        data = f.read()\n    \n    # Look for file paths in journal\n    # File paths are stored as UTF-8 strings\n    import re\n    \n    # Find possible file paths\n    path_pattern = re.compile(b'/[\\\\w/.-]+\\\\.[a-zA-Z]{3,4}')\n    paths = path_pattern.findall(data)\n    \n    # Find possible search terms\n    search_pattern = re.compile(b'[\\\\w\\\\s]{5,50}')\n    \n    recovered = []\n    \n    for path in paths[:50]:  # Limit\n        try:\n            path_str = path.decode('utf-8', errors='ignore')\n            recovered.append({\n                'type': 'file_path',\n                'content': path_str,\n                'offset': data.find(path)\n            })\n        except:\n            pass\n    \n    return recovered\n\nrecovered = recover_deleted_spotlight_entries('/evidence/.Spotlight-V100/Store-V1/')\nprint(f\"Recovered {len(recovered)} deleted entries\")\n```\n\n---\n\n### 7.9 Time Machine Backups Analysis\n\nTime Machine creates incremental backups that can be forensic goldmines.\n\n#### Time Machine Structure\n\n```python\ndef analyze_time_machine(backup_path):\n    \"\"\"Analyze Time Machine backup structure\"\"\"\n    \n    # Time Machine stores backups in:\n    # /Volumes/Backup/Backups.backupdb/MacName/YYYY-MM-DD-HHMMSS/\n    \n    backup_info = {\n        'backups': [],\n        'total_size': 0,\n        'earliest': None,\n        'latest': None\n    }\n    \n    for root, dirs, files in os.walk(backup_path):\n        # Check if this is a backup folder\n        if 'Macintosh HD' in dirs:\n            backup_date = os.path.basename(root)\n            \n            # Parse date from folder name\n            try:\n                date = datetime.strptime(backup_date, '%Y-%m-%d-%H%M%S')\n            except:\n                date = None\n            \n            # Get size\n            size = 0\n            for r, d, f in os.walk(os.path.join(root, 'Macintosh HD')):\n                for file in f:\n                    file_path = os.path.join(r, file)\n                    try:\n                        size += os.path.getsize(file_path)\n                    except:\n                        pass\n            \n            backup = {\n                'date': date,\n                'path': root,\n                'size': size,\n                'files_count': 0  # Could count files\n            }\n            \n            backup_info['backups'].append(backup)\n            backup_info['total_size'] += size\n    \n    # Sort by date\n    backup_info['backups'].sort(key=lambda x: x['date'] or datetime.min)\n    \n    if backup_info['backups']:\n        backup_info['earliest'] = backup_info['backups'][0]['date']\n        backup_info['latest'] = backup_info['backups'][-1]['date']\n    \n    return backup_info\n\n# Analyze backup\ntm_info = analyze_time_machine('/evidence/Backups.backupdb/')\n\nprint(f\"Time Machine Analysis:\")\nprint(f\"  Total backups: {len(tm_info['backups'])}\")\nprint(f\"  Total size: {tm_info['total_size'] / (1024**3):.2f} GB\")\nprint(f\"  Earliest: {tm_info['earliest']}\")\nprint(f\"  Latest: {tm_info['latest']}\")\nprint(f\"\\nBackup timeline:\")\nfor backup in tm_info['backups']:\n    print(f\"  {backup['date']}: {backup['size'] / (1024**3):.2f} GB\")\n```\n\n#### Extracting Specific Files from Backups\n\n```python\ndef find_files_in_time_machine(backup_path, filename_pattern):\n    \"\"\"Search for specific files across all Time Machine backups\"\"\"\n    \n    matches = []\n    \n    # Walk through all backups\n    for root, dirs, files in os.walk(backup_path):\n        # Check each file\n        for file in files:\n            if filename_pattern.lower() in file.lower():\n                # Found a match\n                full_path = os.path.join(root, file)\n                \n                # Get backup date from path\n                path_parts = full_path.split(os.sep)\n                for part in path_parts:\n                    try:\n                        date = datetime.strptime(part, '%Y-%m-%d-%H%M%S')\n                        break\n                    except:\n                        date = None\n                \n                # Get file metadata\n                stat = os.stat(full_path)\n                \n                matches.append({\n                    'filename': file,\n                    'path': full_path,\n                    'backup_date': date,\n                    'size': stat.st_size,\n                    'modified': datetime.fromtimestamp(stat.st_mtime)\n                })\n    \n    return matches\n\n# Search for specific files\nfound = find_files_in_time_machine(\n    '/evidence/Backups.backupdb/',\n    'secret.docx'\n)\n\nprint(f\"Found {len(found)} matching files:\")\nfor f in found:\n    print(f\"\\n  File: {f['filename']}\")\n    print(f\"  Backup: {f['backup_date']}\")\n    print(f\"  Path: {f['path']}\")\n    print(f\"  Size: {f['size']} bytes\")\n    print(f\"  Modified: {f['modified']}\")\n```\n\n---\n\n## Chapter 8 \u2013 Data Recovery &amp; Carving\n\n---\n\n### 8.1 Deleted File Recovery\n\nUnderstanding how file systems handle deletion is crucial for recovery.\n\n#### File Deletion by File System\n\n**FAT32 Deletion:**\n- First byte of filename set to 0xE5\n- Directory entry remains until overwritten\n- Clusters marked as free in FAT\n- Data remains until clusters reused\n\n**NTFS Deletion:**\n- MFT entry flags changed from \"in use\" to \"not in use\"\n- File name removed from directory index\n- $BITMAP marks clusters as free\n- Data runs remain in MFT entry until overwritten\n- MFT entry itself remains until reused\n\n**ext2/3/4 Deletion:**\n- Inode marked as free\n- Directory entry removed (or inode cleared)\n- Block bitmap updated\n- Data blocks marked as free\n- Journal may retain metadata\n\n#### Recovery Strategies by Time Since Deletion\n\n| Time Since Deletion | Recovery Success | Technique |\n|--------------------|------------------|-----------|\n| Minutes | Very High | File system recovery tools |\n| Hours | High | Carving from unallocated |\n| Days | Medium | Signature-based carving |\n| Weeks | Low | Deep sector analysis |\n| Months | Very Low | Specialized techniques |\n\n#### File Recovery Tools\n\n**TestDisk/PhotoRec:**\n```bash\n# Recover all files by signature\nphotorec /dev/sdb1\n\n# Recover specific file types\nphotorec /dev/sdb1 -d recovered/ -f jpg,pdf,doc\n\n# Log recovery session\nphotorec /dev/sdb1 -d recovered/ -l recovery.log\n```\n\n**Foremost:**\n```bash\n# Basic carving\nforemost -i image.dd -o output/\n\n# Carve specific file types\nforemost -t jpg,pdf,doc -i image.dd -o output/\n\n# Use custom configuration\nforemost -c foremost.conf -i image.dd -o output/\n```\n\n**Scalpel:**\n```bash\n# Configure scalpel.conf first\nscalpel image.dd -o output/\n```\n\n**Recuva (Windows):**\n- GUI-based recovery\n- Deep scan option\n- Preview before recovery\n- Secure overwrite option\n\n#### Custom Recovery Script\n\n```python\nimport os\nimport struct\n\ndef recover_deleted_ntfs_files(image_path, partition_offset):\n    \"\"\"Recover deleted files from NTFS by parsing MFT\"\"\"\n    \n    from pytsk3 import Img_Info, FS_Info\n    \n    img = Img_Info(image_path)\n    fs = FS_Info(img, offset=partition_offset)\n    \n    # Open MFT\n    mft = fs.open_meta(file=0)\n    \n    recovered = []\n    mft_size = mft.info.meta.size\n    mft_entry_size = 1024\n    \n    for i in range(mft_size // mft_entry_size):\n        # Read MFT entry\n        entry_data = mft.read_random(i * mft_entry_size, mft_entry_size)\n        \n        # Check signature\n        if entry_data[0:4] != b'FILE':\n            continue\n        \n        # Check if deleted (not in use)\n        flags = struct.unpack(' 100:  # Minimum size\n                output_file = os.path.join(\n                    output_dir, \n                    f\"{sig_name}_{file_count:04d}.{sig_info.get('ext', 'bin')}\"\n                )\n                \n                with open(output_file, 'wb') as out:\n                    out.write(file_data)\n                \n                carved_files.append({\n                    'type': sig_name,\n                    'file': output_file,\n                    'offset': header_pos,\n                    'size': len(file_data)\n                })\n                \n                file_count += 1\n            \n            # Move past this header\n            offset = header_pos + 1\n    \n    return carved_files\n\n# Define signatures\nsignatures = {\n    'jpeg': {\n        'header': 'FFD8FF',\n        'footer': 'FFD9',\n        'ext': 'jpg'\n    },\n    'pdf': {\n        'header': '25504446',\n        'footer': '2525454F46',\n        'ext': 'pdf'\n    },\n    'png': {\n        'header': '89504E470D0A1A0A',\n        'footer': '49454E44AE426082',\n        'ext': 'png'\n    },\n    'zip': {\n        'header': '504B0304',\n        'footer': '504B0506',\n        'ext': 'zip'\n    }\n}\n\n# Carve files\ncarved = carve_by_signature('evidence.dd', signatures, 'carved/')\nfor f in carved:\n    print(f\"Carved {f['type']}: {f['file']} ({f['size']} bytes at {f['offset']})\")\n```\n\n#### Advanced Carving Techniques\n\n**Bifragment Gap Carving:**\nSome files may be fragmented. Advanced carvers can handle this:\n\n```python\ndef bifragment_carving(data, header, footer, max_gap=1024*1024):\n    \"\"\"Carve files that may be split into two fragments\"\"\"\n    \n    fragments = []\n    \n    # Find all headers\n    header_positions = []\n    pos = 0\n    while True:\n        pos = data.find(header, pos)\n        if pos == -1:\n            break\n        header_positions.append(pos)\n        pos += 1\n    \n    # Find all footers\n    footer_positions = []\n    pos = 0\n    while True:\n        pos = data.find(footer, pos)\n        if pos == -1:\n            break\n        footer_positions.append(pos)\n        pos += 1\n    \n    # Try to match headers with footers\n    for h_pos in header_positions:\n        for f_pos in footer_positions:\n            if f_pos &gt; h_pos:\n                gap = f_pos - (h_pos + len(header))\n                if 0 &lt;= gap &lt;= max_gap:\n                    # Valid bifragment file\n                    fragments.append({\n                        'header_pos': h_pos,\n                        'footer_pos': f_pos,\n                        'gap': gap,\n                        'size': f_pos + len(footer) - h_pos\n                    })\n                    break  # Take first valid footer\n    \n    return fragments\n```\n\n---\n\n### 8.3 Entropy Analysis\n\nEntropy measures randomness in data and can identify encrypted or compressed content.\n\n#### Calculating Entropy\n\n```python\nimport math\nfrom collections import Counter\n\ndef calculate_entropy(data):\n    \"\"\"Calculate Shannon entropy of data\"\"\"\n    \n    if not data:\n        return 0\n    \n    entropy = 0\n    counter = Counter(data)\n    data_len = len(data)\n    \n    for count in counter.values():\n        probability = count / data_len\n        entropy -= probability * math.log2(probability)\n    \n    return entropy\n\ndef analyze_file_entropy(file_path, block_size=4096):\n    \"\"\"Analyze entropy of file in blocks\"\"\"\n    \n    results = []\n    \n    with open(file_path, 'rb') as f:\n        block_num = 0\n        while True:\n            block = f.read(block_size)\n            if not block:\n                break\n            \n            entropy = calculate_entropy(block)\n            \n            results.append({\n                'block': block_num,\n                'offset': block_num * block_size,\n                'entropy': entropy,\n                'size': len(block)\n            })\n            \n            block_num += 1\n    \n    return results\n\n# Analyze entropy\nentropy_results = analyze_file_entropy('evidence.dd')\n\n# Identify high-entropy regions (encrypted/compressed)\nhigh_entropy = [r for r in entropy_results if r['entropy'] &gt; 7.5]\nlow_entropy = [r for r in entropy_results if r['entropy'] &lt; 4.0]\n\nprint(f\"High entropy blocks (&gt;7.5): {len(high_entropy)}\")\nprint(f\"Low entropy blocks (&lt;4.0): {len(low_entropy)}\")\n\n# Plot entropy (would use matplotlib in practice)\nfor r in entropy_results[:100]:\n    print(f\"Block {r['block']:4d}: entropy={r['entropy']:.2f}\")\n```\n\n#### Entropy-Based File Classification\n\n```python\ndef classify_by_entropy(data):\n    \"\"\"Classify data type based on entropy\"\"\"\n    \n    entropy = calculate_entropy(data)\n    \n    if entropy &lt; 4.0:\n        return \"Plain text / Low entropy\"\n    elif entropy &lt; 6.0:\n        return \"Typical text / Source code\"\n    elif entropy &lt; 7.0:\n        return \"Compressed / Encoded\"\n    elif entropy &lt; 7.8:\n        return \"Encrypted / High compression\"\n    else:\n        return \"Random / Encrypted\"\n    \ndef find_encrypted_regions(image_path, threshold=7.5, min_size=4096):\n    \"\"\"Find regions that may contain encrypted data\"\"\"\n    \n    encrypted_regions = []\n    \n    with open(image_path, 'rb') as f:\n        pos = 0\n        while True:\n            block = f.read(4096)\n            if not block:\n                break\n            \n            entropy = calculate_entropy(block)\n            \n            if entropy &gt; threshold:\n                # Found high entropy region\n                start_pos = pos\n                \n                # Read consecutive high entropy blocks\n                high_blocks = [block]\n                while True:\n                    next_block = f.read(4096)\n                    if not next_block:\n                        break\n                    \n                    next_entropy = calculate_entropy(next_block)\n                    if next_entropy &gt; threshold:\n                        high_blocks.append(next_block)\n                        pos += 4096\n                    else:\n                        # End of high entropy region\n                        f.seek(-4096, 1)  # Seek back\n                        break\n                \n                # Combine blocks\n                region_data = b''.join(high_blocks)\n                region_size = len(region_data)\n                \n                if region_size &gt;= min_size:\n                    encrypted_regions.append({\n                        'offset': start_pos,\n                        'size': region_size,\n                        'entropy': calculate_entropy(region_data)\n                    })\n            \n            pos += 4096\n    \n    return encrypted_regions\n\n# Find encrypted regions\nencrypted = find_encrypted_regions('evidence.dd')\nfor region in encrypted:\n    print(f\"Encrypted region at {region['offset']}: {region['size']} bytes, entropy={region['entropy']:.2f}\")\n```\n\n---\n\n### 8.4 Hidden Data Detection\n\n#### Alternate Data Streams (NTFS)\n\nADS allows hiding data in NTFS files:\n\n```python\ndef detect_ads(directory):\n    \"\"\"Detect Alternate Data Streams in NTFS\"\"\"\n    \n    ads_list = []\n    \n    for root, dirs, files in os.walk(directory):\n        for file in files:\n            file_path = os.path.join(root, file)\n            \n            # Use streams command (Windows)\n            if os.name == 'nt':\n                import subprocess\n                result = subprocess.run(\n                    ['streams', '-nobanner', file_path],\n                    capture_output=True,\n                    text=True\n                )\n                \n                for line in result.stdout.split('\\n'):\n                    if ':' in line and 'data' in line:\n                        ads_list.append({\n                            'file': file_path,\n                            'stream': line.strip()\n                        })\n    \n    return ads_list\n\n# PowerShell equivalent\ndef detect_ads_powershell(directory):\n    \"\"\"Use PowerShell to detect ADS\"\"\"\n    \n    import subprocess\n    \n    ps_script = f\"\"\"\n    Get-ChildItem -Path {directory} -Recurse -File | ForEach-Object {{\n        $streams = Get-Item -Path $_.FullName -Stream * | Where-Object {{$_.Stream -ne ':$DATA'}}\n        if ($streams) {{\n            [PSCustomObject]@{{\n                File = $_.FullName\n                Streams = ($streams.Stream -join ', ')\n            }}\n        }}\n    }}\n    \"\"\"\n    \n    result = subprocess.run(\n        ['powershell', '-Command', ps_script],\n        capture_output=True,\n        text=True\n    )\n    \n    return result.stdout\n```\n\n#### Steganography Detection\n\nBasic statistical detection:\n\n```python\ndef detect_steganography(image_path):\n    \"\"\"Basic steganography detection\"\"\"\n    \n    from PIL import Image\n    import numpy as np\n    \n    # Load image\n    img = Image.open(image_path)\n    img_array = np.array(img)\n    \n    # Check LSB patterns\n    # In natural images, LSBs should be random\n    # Steganography often introduces patterns\n    \n    # Extract LSBs\n    lsbs = img_array &amp; 1\n    \n    # Calculate statistics\n    # Uniform distribution of 0/1 suggests hidden data\n    zero_count = np.sum(lsbs == 0)\n    one_count = np.sum(lsbs == 1)\n    total = zero_count + one_count\n    \n    if total &gt; 0:\n        zero_ratio = zero_count / total\n        one_ratio = one_count / total\n        \n        # Check for imbalance\n        imbalance = abs(zero_ratio - one_ratio)\n        \n        # Check for patterns (simplified)\n        # Real detection uses chi-square test\n        suspicious = imbalance &lt; 0.1  # Too uniform\n        \n        return {\n            'image': image_path,\n            'zero_ratio': zero_ratio,\n            'one_ratio': one_ratio,\n            'imbalance': imbalance,\n            'suspicious': suspicious\n        }\n    \n    return None\n\n# Check images\nimport glob\nfor img_file in glob.glob('images/*.jpg'):\n    result = detect_steganography(img_file)\n    if result and result['suspicious']:\n        print(f\"Suspicious: {result['image']}\")\n        print(f\"  0/1 ratio: {result['zero_ratio']:.3f}/{result['one_ratio']:.3f}\")\n```\n\n---\n\n### 8.5 Slack Space Analysis\n\nSlack space is the unused space between the end of a file and the end of its last cluster.\n\n#### Types of Slack Space\n\n**RAM Slack:** From end of file to end of sector\n**Drive Slack:** From end of last sector to end of cluster\n\n```python\ndef extract_slack_space(image_path, partition_offset, cluster_size):\n    \"\"\"Extract slack space from all files\"\"\"\n    \n    from pytsk3 import Img_Info, FS_Info\n    \n    img = Img_Info(image_path)\n    fs = FS_Info(img, offset=partition_offset)\n    \n    slack_data = []\n    \n    # Walk through all files\n    def process_dir(dir_path):\n        try:\n            directory = fs.open_dir(dir_path)\n            for entry in directory:\n                if entry.info.name.name in [b'.', b'..']:\n                    continue\n                \n                if entry.info.meta.type == 0x02:  # Directory\n                    subdir = os.path.join(dir_path, entry.info.name.name.decode())\n                    process_dir(subdir)\n                else:\n                    # File\n                    file_size = entry.info.meta.size\n                    \n                    # Calculate clusters used\n                    clusters_used = (file_size + cluster_size - 1) // cluster_size\n                    allocated_size = clusters_used * cluster_size\n                    \n                    if allocated_size &gt; file_size:\n                        slack_size = allocated_size - file_size\n                        \n                        # Read slack space\n                        try:\n                            file_obj = fs.open(entry.info.meta.addr)\n                            \n                            # Seek to end of file\n                            slack_data_start = file_size\n                            slack = file_obj.read_random(slack_data_start, slack_size)\n                            \n                            if slack and any(b != 0 for b in slack):\n                                slack_data.append({\n                                    'file': entry.info.name.name.decode(errors='ignore'),\n                                    'path': os.path.join(dir_path, entry.info.name.name.decode(errors='ignore')),\n                                    'file_size': file_size,\n                                    'slack_size': slack_size,\n                                    'slack_data': slack.hex()[:100] + '...' if slack_size &gt; 50 else slack.hex(),\n                                    'slack_offset': slack_data_start\n                                })\n                        except Exception as e:\n                            pass\n        except Exception as e:\n            print(f\"Error processing {dir_path}: {e}\")\n    \n    process_dir('/')\n    \n    return slack_data\n\n# Extract slack space\nslack = extract_slack_space('evidence.dd', 2048*512, 4096)\nprint(f\"Found {len(slack)} files with non-zero slack space\")\nfor s in slack[:10]:\n    print(f\"\\nFile: {s['path']}\")\n    print(f\"  File size: {s['file_size']}\")\n    print(f\"  Slack size: {s['slack_size']}\")\n    print(f\"  Slack preview: {s['slack_data']}\")\n```\n\n#### Automated Slack Space Carving\n\n```python\ndef carve_from_slack(slack_data, signatures):\n    \"\"\"Carve files from slack space data\"\"\"\n    \n    carved = []\n    \n    for slack_entry in slack_data:\n        slack_bytes = bytes.fromhex(slack_entry['slack_data'].replace('...', ''))\n        \n        # Check each signature\n        for sig_name, sig_info in signatures.items():\n            header = bytes.fromhex(sig_info['header'])\n            \n            if header in slack_bytes:\n                # Found potential file fragment in slack\n                carved.append({\n                    'source_file': slack_entry['path'],\n                    'slack_offset': slack_entry['slack_offset'],\n                    'signature': sig_name,\n                    'data': slack_bytes.hex()[:100]\n                })\n    \n    return carved\n\n# Carve from slack\nsignatures = {\n    'pdf': {'header': '25504446'},\n    'jpg': {'header': 'FFD8FF'},\n    'zip': {'header': '504B0304'}\n}\n\ncarved_slack = carve_from_slack(slack, signatures)\nfor c in carved_slack:\n    print(f\"Found {c['signature']} in slack of {c['source_file']}\")\n```\n\n---\n\n\n# PART IV \u2013 MEMORY &amp; MALWARE FORENSICS\n\n---\n\n## Chapter 9 \u2013 Memory Forensics\n\n---\n\n### 9.1 Introduction to Memory Forensics\n\nMemory forensics involves the analysis of volatile memory (RAM) from a running computer system. This discipline has become critical because modern malware often exists only in memory, never touching the hard drive.\n\n#### Why Memory Forensics?\n\n**Traditional disk forensics limitations:**\n- Encrypted filesystems cannot be accessed without keys (keys in memory)\n- Malware may be memory-resident only (fileless malware)\n- Running processes, network connections, and open files are lost on shutdown\n- Encryption keys, passwords, and decrypted data exist only in memory\n- Rootkits hide files and registry keys but must run in memory\n\n**What memory contains:**\n- Running processes and their threads\n- Loaded kernel modules and drivers\n- Open network connections and sockets\n- Active network connections (including hidden ones)\n- Process memory (code, stack, heap)\n- Kernel data structures\n- Registry hives (in cached form)\n- Passwords and cryptographic keys\n- Malware code and artifacts\n- Command history\n- Recently executed commands\n- Clipboard contents\n\n#### Order of Volatility\n\nWhen collecting evidence, always follow the order of volatility:\n\n```\nMOST VOLATILE (collect first)\n    \u2193\n1. CPU registers, cache\n2. System memory (RAM)\n3. Network state (connections, routing tables)\n4. Running processes\n5. Temporary filesystems (/tmp, /proc)\n6. Disk storage\n    \u2193\nLEAST VOLATILE (collect last)\n```\n\n---\n\n### 9.2 Memory Acquisition Techniques\n\n#### Hardware-Based Acquisition\n\n**Hardware tools:**\n- **Tribble:** PCI card that captures memory via DMA\n- **FireWire/Thunderbolt DMA:** Direct memory access via external ports\n- **Cold boot attacks:** Physically cooling RAM modules to preserve data\n\n**Advantages:**\n- Bypasses operating system\n- Cannot be subverted by rootkits\n- Captures complete physical memory\n\n**Disadvantages:**\n- Requires physical access\n- Specialized hardware needed\n- May not work on newer systems (IOMMU)\n\n#### Software-Based Acquisition\n\n**Windows Tools:**\n\n```powershell\n# FTK Imager (GUI and CLI)\nftkimager.exe memory --capture --output memory.raw\n\n# DumpIt (simple, creates raw file)\nDumpIt.exe /quiet /output memory.raw\n\n# WinPmem (open source)\nwinpmem_mini_x64_rc2.exe memory.raw\n\n# Belkasoft RAM Capturer\nRAMCapturer64.exe /output memory.raw\n\n# Comae Toolkit\nDumpIt.exe /quiet /output memory.raw\n```\n\n**Linux Tools:**\n\n```bash\n# LiME (Linux Memory Extractor)\ninsmod lime.ko \"path=memory.lime format=lime\"\n\n# fmem (loadable kernel module)\ninsmod fmem.ko\ndd if=/dev/fmem of=memory.raw bs=1M\n\n# /dev/mem (if available)\ndd if=/dev/mem of=memory.raw bs=1M\n\n# avml (Azure VM logger)\n./avml memory.raw\n```\n\n**macOS Tools:**\n\n```bash\n# OSXPMem\nsudo osxpmem -o memory.aff4\n\n# Mac Memory Reader (FireWire)\n./macmemoryreader &gt; memory.raw\n```\n\n#### Virtual Machine Memory Acquisition\n\n```bash\n# VMware\n# Suspend or snapshot the VM, capture .vmem file\n\n# VirtualBox\nVBoxManage debugvm \"VM Name\" dumpvmcore --filename=memory.elf\n\n# Hyper-V\n# Export VM, capture .bin file\n\n# QEMU/KVM\n# Memory in qemu process address space\ngdb --pid $(pgrep qemu) -ex \"dump memory memory.raw 0 0x$(cat /proc/$(pgrep qemu)/maps | grep heap | cut -d'-' -f2)\"\n```\n\n#### Memory Acquisition Best Practices\n\n**Checklist for Memory Acquisition:**\n\n```\n\u2610 Verify tool integrity (hash before use)\n\u2610 Document system state (screenshots of running processes)\n\u2610 Use write-blocked media for output\n\u2610 Capture from trusted media (forensic USB)\n\u2610 Calculate hash of output immediately\n\u2610 Note acquisition time (critical for timeline)\n\u2610 Record system uptime\n\u2610 Document any errors or warnings\n```\n\n**Sample Acquisition Script:**\n\n```python\nimport subprocess\nimport hashlib\nimport datetime\nimport os\n\ndef acquire_memory(output_path, tool_path):\n    \"\"\"Acquire memory with documentation\"\"\"\n    \n    # Create acquisition log\n    log = []\n    log.append(f\"Memory Acquisition Log\")\n    log.append(f\"Date/Time: {datetime.datetime.now()}\")\n    log.append(f\"System: {os.uname() if hasattr(os, 'uname') else 'Windows'}\")\n    log.append(f\"Tool: {tool_path}\")\n    \n    # Run acquisition\n    try:\n        cmd = [tool_path, output_path]\n        result = subprocess.run(cmd, capture_output=True, text=True)\n        \n        log.append(f\"Tool output: {result.stdout}\")\n        if result.stderr:\n            log.append(f\"Errors: {result.stderr}\")\n        \n        # Calculate hash\n        sha256 = hashlib.sha256()\n        with open(output_path, 'rb') as f:\n            for chunk in iter(lambda: f.read(65536), b''):\n                sha256.update(chunk)\n        \n        log.append(f\"SHA256: {sha256.hexdigest()}\")\n        log.append(f\"File size: {os.path.getsize(output_path)} bytes\")\n        \n        # Save log\n        with open(output_path + '.txt', 'w') as f:\n            f.write('\\n'.join(log))\n        \n        return True\n        \n    except Exception as e:\n        log.append(f\"Acquisition failed: {str(e)}\")\n        with open(output_path + '.error.txt', 'w') as f:\n            f.write('\\n'.join(log))\n        return False\n```\n\n---\n\n### 9.3 Memory Analysis with Volatility\n\nVolatility is the most widely used memory forensics framework.\n\n#### Volatility Basics\n\n**Installation:**\n\n```bash\n# Volatility 2 (Python 2)\ngit clone https://github.com/volatilityfoundation/volatility.git\ncd volatility\npython setup.py install\n\n# Volatility 3 (Python 3)\ngit clone https://github.com/volatilityfoundation/volatility3.git\ncd volatility3\npython3 setup.py install\n```\n\n**Basic Commands:**\n\n```bash\n# Get memory image info (Vol2)\npython vol.py -f memory.raw imageinfo\n\n# Vol3\npython vol.py -f memory.raw windows.info\n\n# List processes\npython vol.py -f memory.raw windows.pslist\npython vol.py -f memory.raw windows.psscan\npython vol.py -f memory.raw windows.pstree\n\n# List network connections\npython vol.py -f memory.raw windows.netstat\n\n# List loaded DLLs\npython vol.py -f memory.raw windows.dlllist\n\n# Dump process\npython vol.py -f memory.raw windows.memdump --pid 1234 --dump\n```\n\n#### Profile Identification\n\n```python\ndef identify_profile(memory_image):\n    \"\"\"Identify correct Volatility profile\"\"\"\n    \n    import subprocess\n    import re\n    \n    # Run imageinfo\n    cmd = ['python', 'vol.py', '-f', memory_image, 'imageinfo']\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    \n    # Extract suggested profiles\n    profiles = re.findall(r'Suggested Profile\\(s\\) : (.*)', result.stdout)\n    \n    if profiles:\n        suggested = profiles[0].split(',')\n        return [p.strip() for p in suggested]\n    \n    return None\n\n# Get profiles\nprofiles = identify_profile('memory.raw')\nprint(f\"Suggested profiles: {profiles}\")\n```\n\n#### Process Enumeration\n\nDifferent process listing techniques can reveal hidden processes:\n\n```python\nimport subprocess\nimport json\n\ndef enumerate_processes(memory_image, profile):\n    \"\"\"Enumerate processes using multiple techniques\"\"\"\n    \n    processes = {\n        'pslist': [],\n        'psscan': [],\n        'pstree': []\n    }\n    \n    # pslist (walks linked list - can be hidden)\n    cmd = ['python', 'vol.py', '-f', memory_image, '--profile', profile, 'pslist', '--output=json']\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    try:\n        processes['pslist'] = json.loads(result.stdout)\n    except:\n        pass\n    \n    # psscan (scans memory - harder to hide)\n    cmd = ['python', 'vol.py', '-f', memory_image, '--profile', profile, 'psscan', '--output=json']\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    try:\n        processes['psscan'] = json.loads(result.stdout)\n    except:\n        pass\n    \n    # Compare for hidden processes\n    pslist_pids = {p['PID'] for p in processes['pslist']}\n    psscan_pids = {p['PID'] for p in processes['psscan']}\n    \n    hidden = psscan_pids - pslist_pids\n    if hidden:\n        print(f\"Hidden processes detected: {hidden}\")\n        for pid in hidden:\n            for p in processes['psscan']:\n                if p['PID'] == pid:\n                    print(f\"  {p['PID']}: {p['ImageFileName']}\")\n    \n    return processes\n\n# Run enumeration\nprocs = enumerate_processes('memory.raw', 'Win10x64_19041')\n```\n\n#### Network Artifact Extraction\n\n```python\ndef analyze_network_artifacts(memory_image, profile):\n    \"\"\"Extract and analyze network connections\"\"\"\n    \n    # Get network connections\n    cmd = ['python', 'vol.py', '-f', memory_image, '--profile', profile, 'netscan', '--output=json']\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    \n    connections = []\n    try:\n        data = json.loads(result.stdout)\n        for conn in data.get('rows', []):\n            connections.append({\n                'pid': conn.get('PID'),\n                'process': conn.get('Process'),\n                'local': conn.get('Local'),\n                'remote': conn.get('Remote'),\n                'state': conn.get('State'),\n                'created': conn.get('Created')\n            })\n    except:\n        pass\n    \n    # Analyze for suspicious connections\n    suspicious = []\n    for conn in connections:\n        # Check for common C2 ports\n        if conn['remote']:\n            port = conn['remote'].split(':')[-1]\n            if port in ['4444', '1337', '31337', '8080', '8443']:\n                suspicious.append(conn)\n        \n        # Check for connections to known bad IPs (would use threat intel)\n        # ...\n    \n    return {\n        'all': connections,\n        'suspicious': suspicious\n    }\n\n# Analyze network\nnetworks = analyze_network_artifacts('memory.raw', 'Win10x64_19041')\nprint(f\"Found {len(networks['suspicious'])} suspicious connections\")\n```\n\n---\n\n### 9.4 Advanced Memory Analysis\n\n#### Detecting Code Injection\n\n```python\ndef detect_code_injection(memory_image, profile):\n    \"\"\"Detect various code injection techniques\"\"\"\n    \n    import subprocess\n    import json\n    \n    findings = []\n    \n    # 1. Malfind - detect injected code\n    cmd = ['python', 'vol.py', '-f', memory_image, '--profile', profile, 'malfind', '--output=json']\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    \n    try:\n        malfind_results = json.loads(result.stdout)\n        for entry in malfind_results.get('rows', []):\n            findings.append({\n                'type': 'malfind',\n                'pid': entry.get('PID'),\n                'process': entry.get('Process'),\n                'address': entry.get('Address'),\n                'protection': entry.get('Protection'),\n                'hexdump': entry.get('Hexdump')[:50] + '...' if entry.get('Hexdump') else ''\n            })\n    except:\n        pass\n    \n    # 2. Hollowfind - detect process hollowing\n    cmd = ['python', 'vol.py', '-f', memory_image, '--profile', profile, 'hollowfind', '--output=json']\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    \n    # 3. LDrmodules - detect unlinked DLLs\n    cmd = ['python', 'vol.py', '-f', memory_image, '--profile', profile, 'ldrmodules', '--output=json']\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    \n    try:\n        ldrmodules = json.loads(result.stdout)\n        for entry in ldrmodules.get('rows', []):\n            # Check for modules not in all 3 lists\n            in_load = entry.get('InLoad')\n            in_init = entry.get('InInit')\n            in_mem = entry.get('InMem')\n            \n            if not (in_load and in_init and in_mem):\n                findings.append({\n                    'type': 'unlinked_dll',\n                    'pid': entry.get('PID'),\n                    'process': entry.get('Process'),\n                    'dll': entry.get('DllBase'),\n                    'path': entry.get('Path'),\n                    'in_load': in_load,\n                    'in_init': in_init,\n                    'in_mem': in_mem\n                })\n    except:\n        pass\n    \n    return findings\n\n# Detect injection\ninjections = detect_code_injection('memory.raw', 'Win10x64_19041')\nfor finding in injections:\n    print(f\"\\n[{finding['type']}] PID {finding['pid']}: {finding.get('process', '')}\")\n    if 'path' in finding:\n        print(f\"  DLL: {finding['path']}\")\n    if 'hexdump' in finding:\n        print(f\"  Code: {finding['hexdump']}\")\n```\n\n#### Rootkit Detection\n\n```python\ndef detect_rootkits(memory_image, profile):\n    \"\"\"Detect kernel-level rootkits\"\"\"\n    \n    findings = []\n    \n    # 1. Check SSDT hooks\n    cmd = ['python', 'vol.py', '-f', memory_image, '--profile', profile, 'ssdt', '--output=json']\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    \n    try:\n        ssdt = json.loads(result.stdout)\n        for entry in ssdt.get('rows', []):\n            # Check if function is in kernel or unknown module\n            if 'UNKNOWN' in entry.get('Module', '') or 'hook' in entry.get('Module', '').lower():\n                findings.append({\n                    'type': 'ssdt_hook',\n                    'table': entry.get('Table'),\n                    'index': entry.get('Index'),\n                    'function': entry.get('Function'),\n                    'module': entry.get('Module')\n                })\n    except:\n        pass\n    \n    # 2. Check IDT\n    cmd = ['python', 'vol.py', '-f', memory_image, '--profile', profile, 'idt']\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    \n    # 3. Check drivers\n    cmd = ['python', 'vol.py', '-f', memory_image, '--profile', profile, 'modscan', '--output=json']\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    \n    # 4. Check for hidden modules\n    cmd = ['python', 'vol.py', '-f', memory_image, '--profile', profile, 'unloadedmodules']\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    \n    return findings\n```\n\n#### Extracting Passwords and Keys\n\n```python\ndef extract_credentials(memory_image, profile):\n    \"\"\"Extract passwords and cryptographic keys from memory\"\"\"\n    \n    credentials = []\n    \n    # 1. Extract cached domain credentials\n    cmd = ['python', 'vol.py', '-f', memory_image, '--profile', profile, 'cachedump']\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    \n    for line in result.stdout.split('\\n'):\n        if ':' in line and len(line) &gt; 10:\n            credentials.append({\n                'type': 'cached_domain',\n                'value': line.strip()\n            })\n    \n    # 2. Extract LSA secrets\n    cmd = ['python', 'vol.py', '-f', memory_image, '--profile', profile, 'lsadump']\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    \n    # 3. Extract hashes\n    cmd = ['python', 'vol.py', '-f', memory_image, '--profile', profile, 'hashdump']\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    \n    for line in result.stdout.split('\\n'):\n        if ':' in line and len(line.split(':')) &gt;= 4:\n            credentials.append({\n                'type': 'ntlm_hash',\n                'value': line.strip()\n            })\n    \n    # 4. Extract DPAPI keys\n    cmd = ['python', 'vol.py', '-f', memory_image, '--profile', profile, 'masterskey']\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    \n    return credentials\n\n# Extract credentials\ncreds = extract_credentials('memory.raw', 'Win10x64_19041')\nfor cred in creds[:10]:\n    print(f\"[{cred['type']}] {cred['value']}\")\n```\n\n---\n\n### 9.5 Volatility 3 Deep Dive\n\nVolatility 3 represents a complete rewrite with improved architecture.\n\n#### Key Differences from Volatility 2\n\n| Feature | Volatility 2 | Volatility 3 |\n|---------|--------------|--------------|\n| Python | 2.7 | 3.6+ |\n| Profiles | Separate files | Symbol tables |\n| Plugins | Python 2 | Python 3 |\n| Performance | Slower | Faster |\n| Layer support | Limited | Enhanced |\n| Windows support | Good | Better |\n| Linux/macOS | Limited | Improved |\n\n#### Working with Symbol Tables\n\n```python\nimport volatility3\nfrom volatility3.framework import contexts\nfrom volatility3.framework.automagic import symbol_cache\n\ndef get_available_symbols():\n    \"\"\"List available symbol tables\"\"\"\n    \n    symbols = symbol_cache.SymbolTableProvider().list_symbol_tables()\n    for sym in symbols:\n        print(f\"{sym['name']} - {sym['os']} {sym['version']}\")\n\ndef analyze_with_vol3(memory_image):\n    \"\"\"Perform analysis with Volatility 3\"\"\"\n    \n    from volatility3.framework import contexts\n    from volatility3.framework.automagic import automagic\n    from volatility3.framework import plugins\n    \n    # Create context\n    ctx = contexts.Context()\n    \n    # Add memory file\n    config_path = f\"plugins.FileScan.FILE\"\n    ctx.config[config_path] = memory_image\n    \n    # Run automagic\n    magic = automagic.available()\n    \n    # Run specific plugin\n    from volatility3.plugins.windows import pslist\n    result = pslist.PsList.run(ctx, symbol_cache.SymbolTableProvider())\n    \n    return result\n```\n\n---\n\n### 9.6 Memory Analysis for Malware Detection\n\n#### Process Memory Dumping\n\n```python\ndef dump_suspicious_processes(memory_image, profile, output_dir):\n    \"\"\"Dump processes that appear suspicious\"\"\"\n    \n    import subprocess\n    import os\n    \n    # Get process list\n    cmd = ['python', 'vol.py', '-f', memory_image, '--profile', profile, 'pslist']\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    \n    suspicious_pids = []\n    \n    # Parse process list\n    lines = result.stdout.split('\\n')[2:]  # Skip header\n    for line in lines:\n        if not line.strip():\n            continue\n        \n        parts = line.split()\n        if len(parts) &gt;= 6:\n            pid = parts[1]\n            name = parts[0]\n            ppid = parts[2]\n            threads = parts[4]\n            \n            # Check for suspicious indicators\n            suspicious = False\n            \n            # Unusual names\n            if name.lower() in ['svchost.exe', 'lsass.exe', 'winlogon.exe']:\n                # Check if running from wrong location\n                suspicious = True\n            \n            # Too many threads for a simple process\n            if int(threads) &gt; 100 and name.lower() not in ['svchost.exe', 'explorer.exe']:\n                suspicious = True\n            \n            if suspicious:\n                suspicious_pids.append(pid)\n                print(f\"Suspicious process: {name} (PID: {pid})\")\n                \n                # Dump process\n                dump_cmd = ['python', 'vol.py', '-f', memory_image, '--profile', profile, \n                           'memdump', '--pid', pid, '--dump-dir', output_dir]\n                subprocess.run(dump_cmd)\n    \n    return suspicious_pids\n\n# Dump suspicious processes\ndump_suspicious_processes('memory.raw', 'Win10x64_19041', 'dumped_procs/')\n```\n\n#### Extracting Network Indicators\n\n```python\ndef extract_network_indicators(memory_image, profile):\n    \"\"\"Extract network indicators for threat intelligence\"\"\"\n    \n    import re\n    \n    indicators = {\n        'ips': set(),\n        'domains': set(),\n        'ports': set(),\n        'user_agents': set()\n    }\n    \n    # Get network connections\n    cmd = ['python', 'vol.py', '-f', memory_image, '--profile', profile, 'netscan']\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    \n    ip_pattern = re.compile(r'\\d+\\.\\d+\\.\\d+\\.\\d+')\n    domain_pattern = re.compile(r'[a-zA-Z0-9][a-zA-Z0-9\\-\\.]+\\.[a-zA-Z]{2,}')\n    \n    for line in result.stdout.split('\\n'):\n        # Extract IPs\n        ips = ip_pattern.findall(line)\n        for ip in ips:\n            if not ip.startswith(('127.', '192.168.', '10.', '172.')):\n                indicators['ips'].add(ip)\n        \n        # Extract ports\n        if ':' in line:\n            parts = line.split(':')\n            for part in parts:\n                if part.isdigit() and 1 &lt;= int(part) &lt;= 65535:\n                    indicators['ports'].add(part)\n    \n    # Get IE history/URLs\n    cmd = ['python', 'vol.py', '-f', memory_image, '--profile', profile, 'iehistory']\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    \n    domains = domain_pattern.findall(result.stdout)\n    for domain in domains:\n        indicators['domains'].add(domain)\n    \n    return indicators\n\n# Extract indicators\niocs = extract_network_indicators('memory.raw', 'Win10x64_19041')\nprint(\"Network Indicators:\")\nprint(f\"  IPs: {', '.join(iocs['ips'])}\")\nprint(f\"  Domains: {', '.join(iocs['domains'])}\")\nprint(f\"  Ports: {', '.join(iocs['ports'])}\")\n```\n\n---\n\n## Chapter 10 \u2013 Malware Forensics\n\n---\n\n### 10.1 Introduction to Malware Analysis\n\nMalware forensics involves examining malicious software to understand its functionality, origin, and impact.\n\n#### Types of Malware Analysis\n\n| Type | Description | Tools | Time Required |\n|------|-------------|-------|---------------|\n| Static Analysis | Examining code without execution | IDA Pro, Ghidra, strings, PEview | Hours to days |\n| Dynamic Analysis | Running malware in controlled environment | Sandboxes, Process Monitor, Wireshark | Hours |\n| Code Analysis | Deep reverse engineering | Debuggers, disassemblers | Days to weeks |\n| Memory Analysis | Examining malware in RAM | Volatility, Rekall | Hours |\n| Network Analysis | Capturing communication | Wireshark, tcpdump, INetSim | Hours |\n\n#### Malware Analysis Lab Setup\n\n**Physical Lab Requirements:**\n\n```\nHardware:\n- Isolated network (no internet)\n- Multiple analysis machines\n- Hardware write blockers\n- Network tap for monitoring\n- External storage for evidence\n\nSoftware:\n- Virtualization (VMware, VirtualBox)\n- Snapshot capability\n- Network simulation (INetSim, FakeDNS)\n- Monitoring tools\n- Analysis tools\n```\n\n**Virtual Lab Configuration:**\n\n```python\ndef setup_malware_lab():\n    \"\"\"Configure virtual lab for malware analysis\"\"\"\n    \n    lab_config = {\n        'host_only_network': '192.168.56.0/24',\n        'analysis_vm': {\n            'ip': '192.168.56.10',\n            'os': 'Windows 10',\n            'tools': [\n                'Process Monitor',\n                'Process Explorer',\n                'Wireshark',\n                'Regshot',\n                'API Monitor',\n                'OllyDbg',\n                'x64dbg'\n            ]\n        },\n        'monitoring_vm': {\n            'ip': '192.168.56.20',\n            'os': 'Ubuntu',\n            'services': {\n                'dns': 'FakeDNS',\n                'http': 'INetSim',\n                'smtp': 'INetSim',\n                'ftp': 'pyftpdlib'\n            },\n            'tools': [\n                'tcpdump',\n                'Wireshark',\n                'Snort',\n                'Bro/Zeek'\n            ]\n        }\n    }\n    \n    return lab_config\n```\n\n---\n\n### 10.2 Static Analysis Workflow\n\nStatic analysis examines malware without executing it.\n\n#### Initial Triage\n\n```python\nimport hashlib\nimport pefile\nimport struct\nfrom datetime import datetime\n\ndef initial_malware_triage(file_path):\n    \"\"\"Perform initial static analysis on suspected malware\"\"\"\n    \n    results = {}\n    \n    # 1. Calculate hashes\n    with open(file_path, 'rb') as f:\n        data = f.read()\n        results['md5'] = hashlib.md5(data).hexdigest()\n        results['sha1'] = hashlib.sha1(data).hexdigest()\n        results['sha256'] = hashlib.sha256(data).hexdigest()\n    \n    # 2. Get file info\n    stat = os.stat(file_path)\n    results['size'] = stat.st_size\n    results['created'] = datetime.fromtimestamp(stat.st_ctime)\n    results['modified'] = datetime.fromtimestamp(stat.st_mtime)\n    \n    # 3. Check file type\n    import magic\n    results['file_type'] = magic.from_file(file_path)\n    results['mime_type'] = magic.from_file(file_path, mime=True)\n    \n    # 4. Strings extraction\n    results['strings'] = extract_strings(file_path, min_length=4)\n    \n    # 5. Check for known signatures (YARA)\n    results['yara_matches'] = scan_with_yara(file_path)\n    \n    return results\n\ndef extract_strings(file_path, min_length=4):\n    \"\"\"Extract ASCII and Unicode strings from file\"\"\"\n    \n    strings = []\n    \n    with open(file_path, 'rb') as f:\n        data = f.read()\n    \n    # ASCII strings\n    current = ''\n    for byte in data:\n        if 32 &lt;= byte &lt;= 126:  # Printable ASCII\n            current += chr(byte)\n        else:\n            if len(current) &gt;= min_length:\n                strings.append(('ascii', current))\n            current = ''\n    \n    # Unicode strings (simplified - would need proper UTF-16 parsing)\n    for i in range(0, len(data)-1, 2):\n        if data[i] == 0 and 32 &lt;= data[i+1] &lt;= 126:\n            # Potential Unicode\n            pass\n    \n    return strings\n```\n\n#### PE File Analysis\n\n```python\ndef analyze_pe_file(file_path):\n    \"\"\"Perform deep analysis of PE file structure\"\"\"\n    \n    pe = pefile.PE(file_path)\n    \n    analysis = {\n        'dos_header': {},\n        'file_header': {},\n        'optional_header': {},\n        'sections': [],\n        'imports': [],\n        'exports': [],\n        'resources': [],\n        'certificates': []\n    }\n    \n    # DOS Header\n    analysis['dos_header'] = {\n        'e_magic': hex(pe.DOS_HEADER.e_magic),\n        'e_lfanew': pe.DOS_HEADER.e_lfanew\n    }\n    \n    # File Header\n    analysis['file_header'] = {\n        'machine': hex(pe.FILE_HEADER.Machine),\n        'number_of_sections': pe.FILE_HEADER.NumberOfSections,\n        'time_date_stamp': pe.FILE_HEADER.TimeDateStamp,\n        'datetime': datetime.fromtimestamp(pe.FILE_HEADER.TimeDateStamp),\n        'characteristics': hex(pe.FILE_HEADER.Characteristics)\n    }\n    \n    # Optional Header\n    analysis['optional_header'] = {\n        'magic': hex(pe.OPTIONAL_HEADER.Magic),\n        'address_of_entry_point': hex(pe.OPTIONAL_HEADER.AddressOfEntryPoint),\n        'image_base': hex(pe.OPTIONAL_HEADER.ImageBase),\n        'section_alignment': pe.OPTIONAL_HEADER.SectionAlignment,\n        'file_alignment': pe.OPTIONAL_HEADER.FileAlignment,\n        'major_subsystem_version': pe.OPTIONAL_HEADER.MajorSubsystemVersion,\n        'subsystem': pe.OPTIONAL_HEADER.Subsystem,\n        'dll_characteristics': hex(pe.OPTIONAL_HEADER.DllCharacteristics)\n    }\n    \n    # Sections\n    for section in pe.sections:\n        section_info = {\n            'name': section.Name.decode().strip('\\x00'),\n            'virtual_address': hex(section.VirtualAddress),\n            'virtual_size': section.Misc_VirtualSize,\n            'raw_size': section.SizeOfRawData,\n            'characteristics': hex(section.Characteristics),\n            'entropy': section.get_entropy()\n        }\n        analysis['sections'].append(section_info)\n    \n    # Imports\n    if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):\n        for entry in pe.DIRECTORY_ENTRY_IMPORT:\n            dll = entry.dll.decode()\n            for imp in entry.imports:\n                if imp.name:\n                    analysis['imports'].append({\n                        'dll': dll,\n                        'name': imp.name.decode(),\n                        'address': hex(imp.address)\n                    })\n    \n    # Exports\n    if hasattr(pe, 'DIRECTORY_ENTRY_EXPORT'):\n        for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols:\n            analysis['exports'].append({\n                'name': exp.name.decode() if exp.name else '',\n                'address': hex(exp.address),\n                'ordinal': exp.ordinal\n            })\n    \n    # Resources\n    if hasattr(pe, 'DIRECTORY_ENTRY_RESOURCE'):\n        for resource_type in pe.DIRECTORY_ENTRY_RESOURCE.entries:\n            if hasattr(resource_type, 'directory'):\n                for resource_id in resource_type.directory.entries:\n                    if hasattr(resource_id, 'directory'):\n                        for resource_lang in resource_id.directory.entries:\n                            data = pe.get_data(resource_lang.data.struct.OffsetToData, \n                                             resource_lang.data.struct.Size)\n                            analysis['resources'].append({\n                                'type': resource_type.name,\n                                'id': resource_id.name if hasattr(resource_id, 'name') else resource_id.id,\n                                'language': resource_lang.id,\n                                'size': len(data),\n                                'entropy': calculate_entropy(data)\n                            })\n    \n    return analysis\n\n# Analyze malware sample\npe_analysis = analyze_pe_file('malware.exe')\nprint(f\"Compile time: {pe_analysis['file_header']['datetime']}\")\nprint(f\"Entry point: {pe_analysis['optional_header']['address_of_entry_point']}\")\nprint(f\"Sections: {len(pe_analysis['sections'])}\")\nfor section in pe_analysis['sections']:\n    print(f\"  {section['name']}: entropy={section['entropy']:.2f}\")\n```\n\n#### Detecting Packers and Obfuscation\n\n```python\ndef detect_packing(pe_analysis):\n    \"\"\"Detect if PE file is packed or obfuscated\"\"\"\n    \n    indicators = []\n    \n    # 1. High section entropy\n    for section in pe_analysis['sections']:\n        if section['entropy'] &gt; 7.0:\n            indicators.append({\n                'type': 'high_entropy',\n                'section': section['name'],\n                'entropy': section['entropy']\n            })\n    \n    # 2. Few imports (typical of packed files)\n    if len(pe_analysis['imports']) &lt; 10:\n        indicators.append({\n            'type': 'few_imports',\n            'count': len(pe_analysis['imports'])\n        })\n    \n    # 3. Suspicious section names\n    suspicious_sections = ['UPX', 'UPX0', 'UPX1', 'UPX2', 'ASPack', 'PACK', \n                          'THEMIDA', 'ENIGMA', 'VMProtect', 'VProtect']\n    \n    for section in pe_analysis['sections']:\n        if any(sus in section['name'] for sus in suspicious_sections):\n            indicators.append({\n                'type': 'suspicious_section',\n                'name': section['name']\n            })\n    \n    # 4. Raw size vs virtual size discrepancy\n    for section in pe_analysis['sections']:\n        if section['virtual_size'] &gt; section['raw_size'] * 10:\n            indicators.append({\n                'type': 'size_discrepancy',\n                'section': section['name'],\n                'virtual': section['virtual_size'],\n                'raw': section['raw_size']\n            })\n    \n    # 5. Entry point in unusual section\n    entry_section = None\n    entry_rva = int(pe_analysis['optional_header']['address_of_entry_point'], 16)\n    \n    for section in pe_analysis['sections']:\n        start = int(section['virtual_address'], 16)\n        end = start + section['virtual_size']\n        if start &lt;= entry_rva &lt; end:\n            entry_section = section['name']\n            break\n    \n    if entry_section not in ['.text', 'CODE']:\n        indicators.append({\n            'type': 'unusual_entry',\n            'section': entry_section\n        })\n    \n    return indicators\n\n# Check for packing\npacking = detect_packing(pe_analysis)\nif packing:\n    print(\"Packing indicators detected:\")\n    for ind in packing:\n        print(f\"  {ind['type']}: {ind}\")\n```\n\n---\n\n### 10.3 PE File Structure Deep Dive\n\n#### PE File Format\n\n```\nDOS MZ Header (64 bytes)\n    \u2193\nDOS Stub (variable)\n    \u2193\nPE Header (4 bytes - \"PE\\0\\0\")\n    \u2193\nFile Header (20 bytes)\n    \u2193\nOptional Header (usually 224 bytes)\n    \u2193\nSection Headers (array)\n    \u2193\nSections (data)\n```\n\n#### Parsing PE Headers Manually\n\n```python\ndef parse_pe_headers(file_path):\n    \"\"\"Manually parse PE headers without pefile\"\"\"\n    \n    with open(file_path, 'rb') as f:\n        data = f.read()\n    \n    # Check DOS header\n    if data[0:2] != b'MZ':\n        raise ValueError(\"Not a valid PE file\")\n    \n    # Get PE header offset\n    pe_offset = struct.unpack(' 1000:  # Limit output\n            break\n    \n    return instructions\n\ndef find_string_references(disassembly):\n    \"\"\"Find references to strings in disassembly\"\"\"\n    \n    string_refs = []\n    \n    for insn in disassembly:\n        # Look for push instructions with addresses\n        if insn['mnemonic'] == 'push':\n            try:\n                addr = int(insn['operands'], 16)\n                if addr &gt; 0x400000 and addr &lt; 0x80000000:  # User-mode address range\n                    string_refs.append({\n                        'instruction': f\"{insn['address']}: {insn['mnemonic']} {insn['operands']}\",\n                        'referenced_address': hex(addr)\n                    })\n            except:\n                pass\n    \n    return string_refs\n```\n\n#### Identifying API Calls\n\n```python\ndef identify_api_calls(disassembly, imports):\n    \"\"\"Identify API calls in disassembly\"\"\"\n    \n    api_calls = []\n    \n    # Common patterns for API calls\n    patterns = [\n        ('call', 'eax'),\n        ('call', 'ecx'),\n        ('call', 'edx'),\n        ('call', 'ebx'),\n        ('call', 'esi'),\n        ('call', 'edi'),\n        ('call', 'ebp'),\n        ('call', '[eax]'),\n        ('call', '[ecx]'),\n        ('call', '[edx]'),\n        ('call', '[ebx]'),\n        ('call', '[esi]'),\n        ('call', '[edi]'),\n        ('call', '[ebp]'),\n    ]\n    \n    for i, insn in enumerate(disassembly):\n        for pattern in patterns:\n            if insn['mnemonic'] == pattern[0] and pattern[1] in insn['operands']:\n                # Look back for loading of API address\n                for j in range(max(0, i-10), i):\n                    prev = disassembly[j]\n                    if 'mov' in prev['mnemonic'] and 'eax' in prev['operands']:\n                        # Check if moving an import address\n                        for imp in imports:\n                            if imp['address'] in prev['operands']:\n                                api_calls.append({\n                                    'address': insn['address'],\n                                    'api': imp['name'],\n                                    'dll': imp['dll']\n                                })\n                                break\n    \n    return api_calls\n```\n\n#### Control Flow Graph Generation\n\n```python\ndef generate_control_flow(disassembly):\n    \"\"\"Generate simple control flow graph\"\"\"\n    \n    nodes = {}\n    edges = []\n    \n    for i, insn in enumerate(disassembly):\n        nodes[insn['address']] = {\n            'instruction': f\"{insn['mnemonic']} {insn['operands']}\",\n            'type': 'normal'\n        }\n        \n        # Identify jumps\n        if insn['mnemonic'] in ['jmp', 'je', 'jne', 'jg', 'jl', 'jge', 'jle']:\n            try:\n                target = insn['operands'].split()[0]  # Get first operand\n                if target.startswith('0x'):\n                    edges.append({\n                        'from': insn['address'],\n                        'to': target,\n                        'type': insn['mnemonic']\n                    })\n            except:\n                pass\n            \n            # Sequential flow after jump\n            if i &lt; len(disassembly) - 1:\n                next_addr = disassembly[i+1]['address']\n                edges.append({\n                    'from': insn['address'],\n                    'to': next_addr,\n                    'type': 'sequential'\n                })\n    \n    return {'nodes': nodes, 'edges': edges}\n```\n\n---\n\n### 10.6 YARA Rules for Malware Detection\n\n#### Creating YARA Rules\n\n```yaml\nrule Suspicious_Malware_Generic\n{\n    meta:\n        description = \"Generic rule for suspicious malware\"\n        author = \"Forensic Examiner\"\n        date = \"2023-06-15\"\n        severity = \"high\"\n    \n    strings:\n        $s1 = \"CreateRemoteThread\" nocase\n        $s2 = \"VirtualAllocEx\" nocase\n        $s3 = \"WriteProcessMemory\" nocase\n        $s4 = \"SetWindowsHookEx\" nocase\n        $s5 = \"GetProcAddress\" nocase\n        \n        $mz = \"MZ\"\n        $pe = \"PE\\x00\\x00\"\n        \n        $ip1 = \"http://\" ascii\n        $ip2 = \"https://\" ascii\n        $ip3 = \"ftp://\" ascii\n        \n        $crypt1 = \"AES\" ascii\n        $crypt2 = \"RSA\" ascii\n        $crypt3 = \"RC4\" ascii\n        \n    condition:\n        $mz at 0 and $pe at 0x3C and\n        (2 of ($s*)) and\n        (any of ($ip*))\n}\n```\n\n#### Scanning with YARA\n\n```python\nimport yara\n\ndef compile_yara_rules(rule_files):\n    \"\"\"Compile YARA rules from files\"\"\"\n    \n    rules = yara.compile(filepaths=rule_files)\n    return rules\n\ndef scan_file_with_yara(file_path, rules):\n    \"\"\"Scan file with YARA rules\"\"\"\n    \n    matches = rules.match(file_path)\n    \n    results = []\n    for match in matches:\n        rule_result = {\n            'rule': match.rule,\n            'namespace': match.namespace,\n            'tags': match.tags,\n            'meta': match.meta,\n            'strings': []\n        }\n        \n        for string_match in match.strings:\n            rule_result['strings'].append({\n                'identifier': string_match.identifier,\n                'data': string_match.instances[0].matched_data[:50].hex() if string_match.instances else ''\n            })\n        \n        results.append(rule_result)\n    \n    return results\n\ndef scan_memory_with_yara(process_memory, rules):\n    \"\"\"Scan process memory with YARA rules\"\"\"\n    \n    matches = rules.match(data=process_memory)\n    \n    return [{'rule': m.rule, 'meta': m.meta} for m in matches]\n\n# Example usage\nrules = compile_yara_rules({'malware': 'malware_rules.yar'})\nmatches = scan_file_with_yara('suspicious.exe', rules)\nfor match in matches:\n    print(f\"Rule matched: {match['rule']}\")\n    print(f\"  Description: {match['meta'].get('description', 'N/A')}\")\n```\n\n---\n\n### 10.7 Building Indicators of Compromise (IOCs)\n\n#### IOC Structure\n\n```python\nclass IndicatorOfCompromise:\n    \"\"\"Structure for IOCs\"\"\"\n    \n    def __init__(self, name, description):\n        self.name = name\n        self.description = description\n        self.created = datetime.now()\n        self.modified = datetime.now()\n        self.author = \"\"\n        self.severity = \"medium\"\n        self.file_hashes = []\n        self.file_paths = []\n        self.registry_keys = []\n        self.process_names = []\n        self.network_indicators = []\n        self.mutexes = []\n        self.services = []\n        self.yara_rules = []\n    \n    def add_file_hash(self, hash_value, hash_type=\"sha256\"):\n        self.file_hashes.append({\n            'value': hash_value,\n            'type': hash_type\n        })\n    \n    def add_network_indicator(self, indicator, indicator_type=\"ip\"):\n        self.network_indicators.append({\n            'value': indicator,\n            'type': indicator_type\n        })\n    \n    def to_dict(self):\n        return {\n            'name': self.name,\n            'description': self.description,\n            'created': self.created.isoformat(),\n            'modified': self.modified.isoformat(),\n            'author': self.author,\n            'severity': self.severity,\n            'indicators': {\n                'file_hashes': self.file_hashes,\n                'file_paths': self.file_paths,\n                'registry_keys': self.registry_keys,\n                'process_names': self.process_names,\n                'network': self.network_indicators,\n                'mutexes': self.mutexes,\n                'services': self.services,\n                'yara_rules': self.yara_rules\n            }\n        }\n\n# Create IOC from analysis\ndef create_ioc_from_analysis(static_results, dynamic_results, network_results):\n    \"\"\"Create comprehensive IOC from analysis results\"\"\"\n    \n    ioc = IndicatorOfComPromise(\n        name=\"Suspicious Malware Sample\",\n        description=\"IOC from analysis of unknown malware\"\n    )\n    \n    # Add file hashes from static analysis\n    ioc.add_file_hash(static_results['sha256'], 'sha256')\n    ioc.add_file_hash(static_results['sha1'], 'sha1')\n    ioc.add_file_hash(static_results['md5'], 'md5')\n    \n    # Add file paths from dynamic analysis\n    for file_change in dynamic_results.get('files_added', []):\n        ioc.file_paths.append(file_change)\n    \n    # Add network indicators\n    for ip in network_results.get('suspicious_ips', []):\n        ioc.add_network_indicator(ip, 'ip')\n    \n    for dns in network_results.get('dns_queries', []):\n        ioc.add_network_indicator(dns['query'], 'domain')\n    \n    return ioc.to_dict()\n```\n\n#### IOC Formats\n\n```python\ndef export_ioc_to_stix(ioc):\n    \"\"\"Export IOC to STIX format\"\"\"\n    \n    import json\n    \n    stix_package = {\n        \"type\": \"bundle\",\n        \"id\": f\"bundle--{uuid.uuid4()}\",\n        \"objects\": [\n            {\n                \"type\": \"indicator\",\n                \"id\": f\"indicator--{uuid.uuid4()}\",\n                \"created\": ioc['created'],\n                \"modified\": ioc['modified'],\n                \"name\": ioc['name'],\n                \"description\": ioc['description'],\n                \"pattern\": generate_stix_pattern(ioc),\n                \"valid_from\": ioc['created'],\n                \"labels\": [ioc['severity']]\n            }\n        ]\n    }\n    \n    return json.dumps(stix_package, indent=2)\n\ndef export_ioc_to_openioc(ioc):\n    \"\"\"Export IOC to OpenIOC format\"\"\"\n    \n    import xml.etree.ElementTree as ET\n    \n    root = ET.Element(\"ioc\")\n    root.set(\"xmlns\", \"http://schemas.mandiant.com/2010/ioc\")\n    root.set(\"xmlns:xsi\", \"http://www.w3.org/2001/XMLSchema-instance\")\n    root.set(\"xsi:schemaLocation\", \"http://schemas.mandiant.com/2010/ioc ioc.xsd\")\n    \n    # Add metadata\n    meta = ET.SubElement(root, \"metadata\")\n    \n    # Add indicators\n    indicators = ET.SubElement(root, \"definition\")\n    \n    for file_hash in ioc['indicators']['file_hashes']:\n        indicator = ET.SubElement(indicators, \"Indicator\")\n        indicator.set(\"operator\", \"OR\")\n        \n        item = ET.SubElement(indicator, \"IndicatorItem\")\n        item.set(\"condition\", \"is\")\n        \n        context = ET.SubElement(item, \"Context\")\n        context.text = f\"FileItem/{file_hash['type'].upper()}\"\n        \n        content = ET.SubElement(item, \"Content\")\n        content.text = file_hash['value']\n    \n    return ET.tostring(root, encoding='unicode')\n```\n\n---\n\n\n# PART V \u2013 NETWORK &amp; CLOUD FORENSICS\n\n---\n\n## Chapter 11 \u2013 Network Forensics\n\n---\n\n### 11.1 Introduction to Network Forensics\n\nNetwork forensics involves the monitoring, capture, storage, and analysis of network traffic to investigate security incidents, gather evidence, and reconstruct events. Unlike computer forensics which deals with persistent data, network forensics deals with volatile data that exists only for milliseconds.\n\n#### Why Network Forensics?\n\n**What network forensics reveals:**\n- Initial compromise vector (phishing, exploit, etc.)\n- Command and control communication\n- Data exfiltration attempts\n- Lateral movement within the network\n- Malware downloads and beaconing\n- Authentication attempts (successful and failed)\n- Protocol violations and anomalies\n- Timing of attacks\n- Scope of compromise\n\n**Network vs Host-based Forensics:**\n\n| Aspect | Network Forensics | Host Forensics |\n|--------|-------------------|----------------|\n| Data source | Network traffic | Disk, memory, logs |\n| Persistence | Volatile (unless captured) | Persistent |\n| Coverage | Multiple systems | Single system |\n| Visibility | Communications | Local activities |\n| Encryption | Limited | Can access after decryption |\n| Timeline | Real-time | Historical |\n\n#### Network Forensic Process\n\n```\n1. PREPARATION\n   - Define scope\n   - Identify network architecture\n   - Prepare capture points\n   - Legal authorization\n\n2. COLLECTION\n   - Packet capture (full or metadata)\n   - Flow data collection\n   - Log aggregation\n   - Preserve evidence\n\n3. EXAMINATION\n   - Filter and reduce data\n   - Reconstruct sessions\n   - Extract artifacts\n   - Identify anomalies\n\n4. ANALYSIS\n   - Timeline reconstruction\n   - Correlate with host logs\n   - Identify attack patterns\n   - Trace attacker actions\n\n5. REPORTING\n   - Document findings\n   - Create visualizations\n   - Expert testimony preparation\n```\n\n---\n\n### 11.2 TCP/IP Packet Dissection\n\nUnderstanding packet structure is fundamental to network forensics.\n\n#### OSI Model and TCP/IP Stack\n\n```\nOSI Model              TCP/IP Model          Protocols\n7. Application             |                 HTTP, FTP, SMTP\n6. Presentation            | Application      SSL/TLS\n5. Session                 |                 \n4. Transport               | Transport        TCP, UDP\n3. Network                 | Internet         IP, ICMP\n2. Data Link               | Network Access   Ethernet, WiFi\n1. Physical                |                 \n```\n\n#### Packet Structure Deep Dive\n\n**Ethernet Frame (Layer 2):**\n```\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Destination MAC (6 bytes)                        \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Source MAC (6 bytes)                             \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Type/Length (2 bytes)                             \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Payload (46-1500 bytes)                           \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 FCS (4 bytes)                                     \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n**IPv4 Header (Layer 3):**\n```\n 0                   1                   2                   3\n 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|Version|  IHL  |Type of Service|          Total Length         |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|         Identification        |Flags|      Fragment Offset    |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|  Time to Live |    Protocol   |         Header Checksum       |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|                       Source Address                          |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|                    Destination Address                        |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|                    Options                    |    Padding    |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n```\n\n**TCP Header (Layer 4):**\n```\n 0                   1                   2                   3\n 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|          Source Port          |       Destination Port        |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|                        Sequence Number                        |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|                     Acknowledgment Number                      |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n| Data  | |U|A|P|R|S|F|                                         |\n| Offset| |R|C|S|S|Y|I|             Window                      |\n|       | |G|K|H|T|N|N|                                         |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|           Checksum            |         Urgent Pointer        |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|                    Options                    |    Padding    |\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n```\n\n#### Packet Parsing with Python\n\n```python\nimport struct\nimport socket\nfrom datetime import datetime\n\nclass PacketParser:\n    \"\"\"Parse network packets from raw capture\"\"\"\n    \n    def __init__(self, packet_data):\n        self.raw_data = packet_data\n        self.protocols = []\n        \n    def parse_ethernet(self):\n        \"\"\"Parse Ethernet frame\"\"\"\n        eth_header = self.raw_data[0:14]\n        eth = struct.unpack('!6s6sH', eth_header)\n        \n        dest_mac = self._format_mac(eth[0])\n        src_mac = self._format_mac(eth[1])\n        eth_type = socket.ntohs(eth[2])\n        \n        self.protocols.append({\n            'layer': 'Ethernet',\n            'src_mac': src_mac,\n            'dest_mac': dest_mac,\n            'type': hex(eth_type)\n        })\n        \n        # Return next protocol data\n        return self.raw_data[14:], eth_type\n    \n    def _format_mac(self, mac_bytes):\n        \"\"\"Format MAC address bytes to string\"\"\"\n        return ':'.join(f'{b:02x}' for b in mac_bytes)\n    \n    def parse_ipv4(self, data):\n        \"\"\"Parse IPv4 header\"\"\"\n        ip_header = data[0:20]\n        iph = struct.unpack('!BBHHHBBH4s4s', ip_header)\n        \n        version_ihl = iph[0]\n        version = version_ihl &gt;&gt; 4\n        ihl = version_ihl &amp; 0xF\n        ip_header_length = ihl * 4\n        \n        ttl = iph[5]\n        protocol = iph[6]\n        src_ip = socket.inet_ntoa(iph[8])\n        dest_ip = socket.inet_ntoa(iph[9])\n        \n        self.protocols.append({\n            'layer': 'IPv4',\n            'src_ip': src_ip,\n            'dest_ip': dest_ip,\n            'protocol': protocol,\n            'ttl': ttl\n        })\n        \n        return data[ip_header_length:], protocol\n    \n    def parse_tcp(self, data):\n        \"\"\"Parse TCP header\"\"\"\n        tcp_header = data[0:20]\n        tcph = struct.unpack('!HHLLBBHHH', tcp_header)\n        \n        src_port = tcph[0]\n        dest_port = tcph[1]\n        sequence = tcph[2]\n        ack = tcph[3]\n        data_offset = (tcph[4] &gt;&gt; 4) * 4\n        flags = tcph[5]\n        \n        # Parse TCP flags\n        flags_str = ''\n        if flags &amp; 0x01: flags_str += 'FIN '\n        if flags &amp; 0x02: flags_str += 'SYN '\n        if flags &amp; 0x04: flags_str += 'RST '\n        if flags &amp; 0x08: flags_str += 'PSH '\n        if flags &amp; 0x10: flags_str += 'ACK '\n        if flags &amp; 0x20: flags_str += 'URG '\n        \n        self.protocols.append({\n            'layer': 'TCP',\n            'src_port': src_port,\n            'dest_port': dest_port,\n            'sequence': sequence,\n            'ack': ack,\n            'flags': flags_str.strip()\n        })\n        \n        return data[data_offset:]\n    \n    def parse_udp(self, data):\n        \"\"\"Parse UDP header\"\"\"\n        udp_header = data[0:8]\n        udph = struct.unpack('!HHHH', udp_header)\n        \n        src_port = udph[0]\n        dest_port = udph[1]\n        length = udph[2]\n        checksum = udph[3]\n        \n        self.protocols.append({\n            'layer': 'UDP',\n            'src_port': src_port,\n            'dest_port': dest_port,\n            'length': length,\n            'checksum': checksum\n        })\n        \n        return data[8:]\n    \n    def parse_all(self):\n        \"\"\"Parse all protocol layers\"\"\"\n        data = self.raw_data\n        \n        # Ethernet\n        data, eth_type = self.parse_ethernet()\n        \n        # IP (assuming Ethernet type 0x0800 for IPv4)\n        if eth_type == 0x0800:\n            data, ip_proto = self.parse_ipv4(data)\n            \n            # Transport layer\n            if ip_proto == 6:  # TCP\n                self.parse_tcp(data)\n            elif ip_proto == 17:  # UDP\n                self.parse_udp(data)\n        \n        return self.protocols\n\n# Usage example\nwith open('capture.pcap', 'rb') as f:\n    # Skip pcap header (24 bytes) for simplicity\n    packet_data = f.read()\n    \nparser = PacketParser(packet_data)\nprotocols = parser.parse_all()\nfor p in protocols:\n    print(f\"{p['layer']}: {p}\")\n```\n\n---\n\n### 11.3 PCAP Analysis Methodology\n\nPCAP (Packet Capture) files contain raw network traffic and are the primary evidence source in network forensics.\n\n#### PCAP File Structure\n\n```\nGlobal Header (24 bytes)\n    \u2193\nPacket Header (16 bytes)\n    \u2193\nPacket Data (variable)\n    \u2193\nPacket Header (16 bytes)\n    \u2193\nPacket Data (variable)\n    \u2193\n...\n```\n\n**Global Header:**\n- Magic number (4 bytes): 0xa1b2c3d4 (little-endian) or 0xd4c3b2a1 (big-endian)\n- Version major/minor (2+2 bytes)\n- Timezone offset (4 bytes)\n- Timestamp accuracy (4 bytes)\n- Snapshot length (4 bytes)\n- Link layer type (4 bytes)\n\n**Packet Header:**\n- Timestamp seconds (4 bytes)\n- Timestamp microseconds (4 bytes)\n- Captured length (4 bytes)\n- Original length (4 bytes)\n\n#### PCAP Analysis with Scapy\n\n```python\nfrom scapy.all import *\nimport pandas as pd\nfrom collections import Counter\n\ndef analyze_pcap(pcap_file):\n    \"\"\"Comprehensive PCAP analysis\"\"\"\n    \n    packets = rdpcap(pcap_file)\n    \n    analysis = {\n        'summary': {\n            'total_packets': len(packets),\n            'start_time': packets[0].time if packets else None,\n            'end_time': packets[-1].time if packets else None,\n            'duration': packets[-1].time - packets[0].time if len(packets) &gt; 1 else 0\n        },\n        'protocols': Counter(),\n        'ip_communications': Counter(),\n        'ports': Counter(),\n        'conversations': [],\n        'http_requests': [],\n        'dns_queries': [],\n        'tls_certificates': [],\n        'suspicious_traffic': []\n    }\n    \n    for pkt in packets:\n        # Protocol distribution\n        if IP in pkt:\n            proto = pkt[IP].proto\n            if proto == 6:\n                analysis['protocols']['TCP'] += 1\n            elif proto == 17:\n                analysis['protocols']['UDP'] += 1\n            elif proto == 1:\n                analysis['protocols']['ICMP'] += 1\n        \n        # IP communications\n        if IP in pkt:\n            comm = f\"{pkt[IP].src} -&gt; {pkt[IP].dst}\"\n            analysis['ip_communications'][comm] += 1\n        \n        # Port analysis\n        if TCP in pkt:\n            analysis['ports'][pkt[TCP].sport] += 1\n            analysis['ports'][pkt[TCP].dport] += 1\n        elif UDP in pkt:\n            analysis['ports'][pkt[UDP].sport] += 1\n            analysis['ports'][pkt[UDP].dport] += 1\n        \n        # Conversations (complete TCP streams)\n        if TCP in pkt and pkt[TCP].flags &amp; 0x01:  # SYN\n            conversation = {\n                'src_ip': pkt[IP].src,\n                'src_port': pkt[TCP].sport,\n                'dst_ip': pkt[IP].dst,\n                'dst_port': pkt[TCP].dport,\n                'start_time': pkt.time\n            }\n            analysis['conversations'].append(conversation)\n        \n        # HTTP requests\n        if TCP in pkt and pkt[TCP].dport == 80 and Raw in pkt:\n            payload = pkt[Raw].load.decode('utf-8', errors='ignore')\n            if payload.startswith(('GET', 'POST', 'PUT', 'DELETE')):\n                analysis['http_requests'].append({\n                    'time': pkt.time,\n                    'src_ip': pkt[IP].src,\n                    'dst_ip': pkt[IP].dst,\n                    'request': payload.split('\\n')[0]\n                })\n        \n        # DNS queries\n        if UDP in pkt and pkt[UDP].dport == 53 and DNS in pkt:\n            if pkt[DNS].qd:\n                query = pkt[DNS].qd.qname.decode('utf-8', errors='ignore')\n                analysis['dns_queries'].append({\n                    'time': pkt.time,\n                    'src_ip': pkt[IP].src,\n                    'query': query,\n                    'type': pkt[DNS].qd.qtype\n                })\n        \n        # TLS handshakes (Client Hello)\n        if TCP in pkt and Raw in pkt:\n            payload = pkt[Raw].load\n            if len(payload) &gt; 0 and payload[0] == 0x16:  # TLS Handshake\n                if len(payload) &gt; 5 and payload[5] == 0x01:  # Client Hello\n                    analysis['tls_certificates'].append({\n                        'time': pkt.time,\n                        'src_ip': pkt[IP].src,\n                        'dst_ip': pkt[IP].dst,\n                        'dst_port': pkt[TCP].dport\n                    })\n    \n    return analysis\n\n# Run analysis\npcap_analysis = analyze_pcap('capture.pcap')\nprint(f\"Total packets: {pcap_analysis['summary']['total_packets']}\")\nprint(f\"Duration: {pcap_analysis['summary']['duration']:.2f} seconds\")\nprint(f\"Top protocols: {pcap_analysis['protocols'].most_common(5)}\")\nprint(f\"Top conversations: {pcap_analysis['ip_communications'].most_common(5)}\")\n```\n\n#### Session Reconstruction\n\n```python\ndef reconstruct_tcp_streams(pcap_file):\n    \"\"\"Reconstruct complete TCP sessions from PCAP\"\"\"\n    \n    packets = rdpcap(pcap_file)\n    streams = {}\n    \n    for pkt in packets:\n        if TCP in pkt and IP in pkt:\n            # Create stream identifier\n            stream_id = (pkt[IP].src, pkt[TCP].sport, pkt[IP].dst, pkt[TCP].dport)\n            reverse_id = (pkt[IP].dst, pkt[TCP].dport, pkt[IP].src, pkt[TCP].sport)\n            \n            # Initialize stream if new\n            if stream_id not in streams and reverse_id not in streams:\n                streams[stream_id] = {\n                    'packets': [],\n                    'data': b'',\n                    'start_time': pkt.time,\n                    'end_time': pkt.time,\n                    'src_ip': pkt[IP].src,\n                    'src_port': pkt[TCP].sport,\n                    'dst_ip': pkt[IP].dst,\n                    'dst_port': pkt[TCP].dport\n                }\n            \n            # Get the correct stream\n            if stream_id in streams:\n                stream = streams[stream_id]\n            else:\n                stream = streams[reverse_id]\n            \n            # Add packet\n            stream['packets'].append({\n                'time': pkt.time,\n                'seq': pkt[TCP].seq,\n                'flags': pkt[TCP].flags,\n                'len': len(pkt[TCP].payload)\n            })\n            \n            # Add data if present\n            if Raw in pkt:\n                stream['data'] += bytes(pkt[Raw].load)\n            \n            stream['end_time'] = max(stream['end_time'], pkt.time)\n            \n            # Check for stream end\n            if pkt[TCP].flags &amp; 0x01:  # FIN\n                stream['state'] = 'FIN'\n            elif pkt[TCP].flags &amp; 0x04:  # RST\n                stream['state'] = 'RST'\n    \n    # Process streams\n    results = []\n    for stream_id, stream in streams.items():\n        if len(stream['data']) &gt; 0:\n            results.append({\n                'src': f\"{stream['src_ip']}:{stream['src_port']}\",\n                'dst': f\"{stream['dst_ip']}:{stream['dst_port']}\",\n                'duration': stream['end_time'] - stream['start_time'],\n                'packets': len(stream['packets']),\n                'data_size': len(stream['data']),\n                'data': stream['data'][:500],  # First 500 bytes\n                'state': stream.get('state', 'ACTIVE')\n            })\n    \n    return results\n\n# Reconstruct streams\nstreams = reconstruct_tcp_streams('capture.pcap')\nfor stream in streams:\n    print(f\"\\nStream: {stream['src']} -&gt; {stream['dst']}\")\n    print(f\"  Duration: {stream['duration']:.2f}s\")\n    print(f\"  Packets: {stream['packets']}\")\n    print(f\"  Data size: {stream['data_size']} bytes\")\n```\n\n---\n\n### 11.4 DNS Tunneling Detection\n\nDNS tunneling is a technique used to bypass firewalls by encapsulating data in DNS queries and responses.\n\n#### DNS Tunneling Characteristics\n\n**Normal DNS:**\n- Short queries (most &lt; 30 characters)\n- Low frequency\n- Consistent patterns\n- Standard record types (A, AAAA, MX, etc.)\n\n**DNS Tunneling:**\n- Long subdomains (up to 255 characters)\n- High frequency of queries\n- Base64/hex encoded data\n- Unusual record types (TXT, NULL)\n- Consistent packet sizes\n- Fixed TTL values\n\n#### Detection Algorithm\n\n```python\ndef detect_dns_tunneling(pcap_file, threshold=0.8):\n    \"\"\"Detect potential DNS tunneling activity\"\"\"\n    \n    packets = rdpcap(pcap_file)\n    \n    dns_queries = []\n    suspicious = []\n    \n    for pkt in packets:\n        if UDP in pkt and pkt[UDP].dport == 53 and DNS in pkt:\n            if pkt[DNS].qd:\n                query = pkt[DNS].qd.qname.decode('utf-8', errors='ignore').rstrip('.')\n                query_type = pkt[DNS].qd.qtype\n                \n                dns_queries.append({\n                    'time': pkt.time,\n                    'src_ip': pkt[IP].src,\n                    'query': query,\n                    'type': query_type,\n                    'length': len(query)\n                })\n    \n    # Group by source IP\n    from collections import defaultdict\n    by_ip = defaultdict(list)\n    for q in dns_queries:\n        by_ip[q['src_ip']].append(q)\n    \n    for ip, queries in by_ip.items():\n        if len(queries) &lt; 10:  # Not enough data\n            continue\n        \n        # Calculate metrics\n        avg_length = sum(q['length'] for q in queries) / len(queries)\n        max_length = max(q['length'] for q in queries)\n        \n        # Check entropy of subdomains\n        subdomain_entropy = []\n        for q in queries:\n            parts = q['query'].split('.')\n            if len(parts) &gt; 2:  # Has subdomain\n                subdomain = parts[0]\n                entropy = calculate_entropy(subdomain.encode())\n                subdomain_entropy.append(entropy)\n        \n        avg_entropy = sum(subdomain_entropy) / len(subdomain_entropy) if subdomain_entropy else 0\n        \n        # Check for base64-like characters\n        base64_chars = set('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=')\n        base64_ratio = []\n        for q in queries:\n            subdomain = q['query'].split('.')[0]\n            if subdomain:\n                base64_count = sum(1 for c in subdomain if c in base64_chars)\n                base64_ratio.append(base64_count / len(subdomain))\n        \n        avg_base64 = sum(base64_ratio) / len(base64_ratio) if base64_ratio else 0\n        \n        # Check frequency (queries per second)\n        times = [q['time'] for q in queries]\n        times.sort()\n        intervals = [times[i+1] - times[i] for i in range(len(times)-1)]\n        avg_interval = sum(intervals) / len(intervals) if intervals else 0\n        \n        # Calculate suspicious score\n        score = 0\n        \n        # Long queries\n        if avg_length &gt; 50:\n            score += 0.3\n        if max_length &gt; 200:\n            score += 0.2\n        \n        # High entropy\n        if avg_entropy &gt; 4.5:\n            score += 0.3\n        \n        # Base64-like\n        if avg_base64 &gt; 0.8:\n            score += 0.3\n        \n        # High frequency\n        if avg_interval &lt; 0.1:  # More than 10 per second\n            score += 0.2\n        \n        if score &gt; threshold:\n            suspicious.append({\n                'src_ip': ip,\n                'score': score,\n                'query_count': len(queries),\n                'avg_length': avg_length,\n                'max_length': max_length,\n                'avg_entropy': avg_entropy,\n                'avg_base64_ratio': avg_base64,\n                'avg_interval': avg_interval,\n                'sample_queries': [q['query'] for q in queries[:5]]\n            })\n    \n    return suspicious\n\ndef calculate_entropy(data):\n    \"\"\"Calculate Shannon entropy of data\"\"\"\n    import math\n    from collections import Counter\n    \n    if not data:\n        return 0\n    \n    entropy = 0\n    counter = Counter(data)\n    data_len = len(data)\n    \n    for count in counter.values():\n        probability = count / data_len\n        entropy -= probability * math.log2(probability)\n    \n    return entropy\n\n# Detect DNS tunneling\ntunneling = detect_dns_tunneling('capture.pcap')\nfor t in tunneling:\n    print(f\"\\nSuspicious DNS from {t['src_ip']} (score: {t['score']:.2f})\")\n    print(f\"  Queries: {t['query_count']}\")\n    print(f\"  Avg length: {t['avg_length']:.1f}\")\n    print(f\"  Avg entropy: {t['avg_entropy']:.2f}\")\n    print(f\"  Sample queries: {t['sample_queries']}\")\n```\n\n---\n\n### 11.5 IDS Log Correlation\n\nIntrusion Detection System (IDS) logs provide alerts about suspicious activity.\n\n#### Parsing IDS Logs\n\n```python\nimport json\nimport csv\nfrom datetime import datetime\n\ndef parse_snort_logs(log_file):\n    \"\"\"Parse Snort alert logs\"\"\"\n    \n    alerts = []\n    \n    with open(log_file, 'r') as f:\n        for line in f:\n            try:\n                # Snort unified2 format or CSV\n                if log_file.endswith('.csv'):\n                    parts = line.strip().split(',')\n                    if len(parts) &gt; 5:\n                        alerts.append({\n                            'timestamp': parts[0],\n                            'sid': parts[1],\n                            'signature': parts[2],\n                            'classification': parts[3],\n                            'priority': parts[4],\n                            'src_ip': parts[5],\n                            'src_port': parts[6],\n                            'dst_ip': parts[7],\n                            'dst_port': parts[8],\n                            'protocol': parts[9]\n                        })\n            except:\n                continue\n    \n    return alerts\n\ndef parse_suricata_eve_logs(eve_file):\n    \"\"\"Parse Suricata EVE JSON logs\"\"\"\n    \n    alerts = []\n    \n    with open(eve_file, 'r') as f:\n        for line in f:\n            try:\n                event = json.loads(line)\n                \n                if event.get('event_type') == 'alert':\n                    alert = {\n                        'timestamp': event.get('timestamp'),\n                        'src_ip': event.get('src_ip'),\n                        'src_port': event.get('src_port'),\n                        'dst_ip': event.get('dest_ip'),\n                        'dst_port': event.get('dest_port'),\n                        'proto': event.get('proto'),\n                        'alert': {\n                            'action': event['alert'].get('action'),\n                            'signature': event['alert'].get('signature'),\n                            'category': event['alert'].get('category'),\n                            'severity': event['alert'].get('severity')\n                        }\n                    }\n                    alerts.append(alert)\n            except:\n                continue\n    \n    return alerts\n```\n\n#### Correlating IDS Alerts with PCAP\n\n```python\ndef correlate_alerts_with_pcap(alert_log, pcap_file, time_window=60):\n    \"\"\"Correlate IDS alerts with packet captures\"\"\"\n    \n    # Load alerts\n    alerts = parse_suricata_eve_logs(alert_log)\n    \n    # Load packets\n    packets = rdpcap(pcap_file)\n    \n    correlation = []\n    \n    for alert in alerts:\n        alert_time = datetime.fromisoformat(alert['timestamp'].replace('Z', '+00:00')).timestamp()\n        \n        # Find packets within time window\n        matching_packets = []\n        for pkt in packets:\n            if abs(pkt.time - alert_time) &lt;= time_window:\n                # Check if packet matches alert source/dest\n                if IP in pkt:\n                    if (pkt[IP].src == alert['src_ip'] and \n                        pkt[IP].dst == alert['dst_ip']):\n                        matching_packets.append(pkt)\n        \n        correlation.append({\n            'alert': alert,\n            'matching_packets': len(matching_packets),\n            'packets': matching_packets[:10]  # First 10\n        })\n    \n    return correlation\n\n# Correlate alerts\ncorrelated = correlate_alerts_with_pcap('eve.json', 'capture.pcap')\nfor c in correlated:\n    print(f\"Alert: {c['alert']['alert']['signature']}\")\n    print(f\"  Matching packets: {c['matching_packets']}\")\n```\n\n---\n\n### 11.6 NetFlow Analysis\n\nNetFlow provides summarized network traffic data, useful for identifying patterns without full packet capture.\n\n#### NetFlow v5 Header\n\n```\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Version (2) | Count (2)                          \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 SysUptime (4)                                    \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 UnixSecs (4)                                     \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 UnixNsecs (4)                                    \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 FlowSequence (4)                                 \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 EngineType (1) | EngineID (1) | SamplingMode (2)\u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n#### NetFlow Record Format\n\n```\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 SrcAddr (4)                                      \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 DstAddr (4)                                      \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 NextHop (4)                                      \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Input (2) | Output (2)                           \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Packets (4)                                      \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Octets (4)                                       \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 First (4)                                        \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Last (4)                                         \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 SrcPort (2) | DstPort (2)                        \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Padding (1) | TCPFlags (1) | Protocol (1) | Tos (1)\u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 SrcAS (2) | DstAS (2)                            \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 SrcMask (1) | DstMask (1) | Padding (2)          \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n#### NetFlow Analysis\n\n```python\nimport struct\nfrom collections import defaultdict\n\ndef parse_netflow_v5(nf_file):\n    \"\"\"Parse NetFlow v5 records\"\"\"\n    \n    flows = []\n    \n    with open(nf_file, 'rb') as f:\n        while True:\n            # Read header (24 bytes)\n            header_data = f.read(24)\n            if len(header_data) &lt; 24:\n                break\n            \n            header = struct.unpack('!HHIIIIBBH', header_data)\n            version = header[0]\n            count = header[1]\n            \n            # Read flows\n            for _ in range(count):\n                flow_data = f.read(48)\n                if len(flow_data) &lt; 48:\n                    break\n                \n                flow = struct.unpack('!IIIIHHIIIIIIHHBBBBBBH', flow_data)\n                \n                flows.append({\n                    'src_ip': socket.inet_ntoa(struct.pack('!I', flow[0])),\n                    'dst_ip': socket.inet_ntoa(struct.pack('!I', flow[1])),\n                    'next_hop': socket.inet_ntoa(struct.pack('!I', flow[2])),\n                    'input_iface': flow[4],\n                    'output_iface': flow[5],\n                    'packets': flow[6],\n                    'bytes': flow[7],\n                    'first_seen': flow[8],\n                    'last_seen': flow[9],\n                    'src_port': flow[10],\n                    'dst_port': flow[11],\n                    'tcp_flags': flow[13],\n                    'protocol': flow[14],\n                    'tos': flow[15]\n                })\n    \n    return flows\n\ndef analyze_netflow(flows):\n    \"\"\"Analyze NetFlow data\"\"\"\n    \n    analysis = {\n        'total_flows': len(flows),\n        'total_bytes': sum(f['bytes'] for f in flows),\n        'total_packets': sum(f['packets'] for f in flows),\n        'top_src_ips': Counter(),\n        'top_dst_ips': Counter(),\n        'top_ports': Counter(),\n        'protocols': Counter(),\n        'conversations': Counter()\n    }\n    \n    for flow in flows:\n        analysis['top_src_ips'][flow['src_ip']] += flow['bytes']\n        analysis['top_dst_ips'][flow['dst_ip']] += flow['bytes']\n        analysis['top_ports'][flow['dst_port']] += flow['bytes']\n        analysis['protocols'][flow['protocol']] += 1\n        \n        conv = f\"{flow['src_ip']}:{flow['src_port']} -&gt; {flow['dst_ip']}:{flow['dst_port']}\"\n        analysis['conversations'][conv] += flow['bytes']\n    \n    return analysis\n\n# Analyze NetFlow\nflows = parse_netflow_v5('netflow.dat')\nanalysis = analyze_netflow(flows)\nprint(f\"Total flows: {analysis['total_flows']}\")\nprint(f\"Total bytes: {analysis['total_bytes']:,}\")\nprint(f\"Top source IPs by bytes:\")\nfor ip, bytes in analysis['top_src_ips'].most_common(5):\n    print(f\"  {ip}: {bytes:,} bytes\")\n```\n\n---\n\n### 11.7 Timeline Reconstruction\n\nCreating a timeline from network traffic helps understand the sequence of attack events.\n\n#### Network Timeline Creation\n\n```python\ndef create_network_timeline(pcap_file, alert_log=None):\n    \"\"\"Create comprehensive timeline from network evidence\"\"\"\n    \n    timeline = []\n    \n    # Load packets\n    packets = rdpcap(pcap_file)\n    \n    # Add packet events\n    for pkt in packets:\n        if IP in pkt:\n            event = {\n                'timestamp': pkt.time,\n                'type': 'packet',\n                'src_ip': pkt[IP].src,\n                'dst_ip': pkt[IP].dst,\n                'protocol': 'TCP' if TCP in pkt else 'UDP' if UDP in pkt else 'Other'\n            }\n            \n            if TCP in pkt:\n                event['src_port'] = pkt[TCP].sport\n                event['dst_port'] = pkt[TCP].dport\n                event['flags'] = str(pkt[TCP].flags)\n            elif UDP in pkt:\n                event['src_port'] = pkt[UDP].sport\n                event['dst_port'] = pkt[UDP].dport\n            \n            # Extract interesting payloads\n            if Raw in pkt:\n                payload = pkt[Raw].load\n                if b'HTTP' in payload or b'GET' in payload or b'POST' in payload:\n                    event['type'] = 'http_request'\n                    event['payload'] = payload[:100].decode('utf-8', errors='ignore')\n                elif b'SMTP' in payload or b'MAIL' in payload:\n                    event['type'] = 'smtp'\n            \n            timeline.append(event)\n    \n    # Add alert events\n    if alert_log:\n        alerts = parse_suricata_eve_logs(alert_log)\n        for alert in alerts:\n            timeline.append({\n                'timestamp': datetime.fromisoformat(alert['timestamp'].replace('Z', '+00:00')).timestamp(),\n                'type': 'alert',\n                'src_ip': alert['src_ip'],\n                'dst_ip': alert['dst_ip'],\n                'signature': alert['alert']['signature'],\n                'severity': alert['alert']['severity']\n            })\n    \n    # Sort by timestamp\n    timeline.sort(key=lambda x: x['timestamp'])\n    \n    return timeline\n\ndef visualize_timeline(timeline):\n    \"\"\"Create simple text visualization of timeline\"\"\"\n    \n    from datetime import datetime\n    \n    for event in timeline:\n        dt = datetime.fromtimestamp(event['timestamp'])\n        time_str = dt.strftime('%Y-%m-%d %H:%M:%S')\n        \n        if event['type'] == 'alert':\n            print(f\"{time_str} [ALERT] {event['signature']} {event['src_ip']} -&gt; {event['dst_ip']}\")\n        elif event['type'] == 'http_request':\n            print(f\"{time_str} [HTTP] {event['src_ip']} -&gt; {event['dst_ip']} {event.get('payload', '')[:50]}\")\n        elif event['type'] == 'packet':\n            if event.get('flags') and 'S' in event['flags']:  # SYN\n                print(f\"{time_str} [CONN] {event['src_ip']}:{event.get('src_port', '')} -&gt; {event['dst_ip']}:{event.get('dst_port', '')}\")\n\n# Create and visualize timeline\ntimeline = create_network_timeline('capture.pcap', 'eve.json')\nvisualize_timeline(timeline[:20])  # First 20 events\n```\n\n---\n\n## Chapter 12 \u2013 Cloud &amp; Virtualization Forensics\n\n---\n\n### 12.1 Introduction to Cloud Forensics\n\nCloud forensics extends traditional digital forensics to cloud computing environments, where data may be distributed across multiple jurisdictions and service models.\n\n#### Cloud Service Models and Forensic Implications\n\n| Model | Customer Control | Provider Control | Forensic Challenges |\n|-------|-----------------|-------------------|---------------------|\n| **IaaS** (AWS EC2, Azure VM) | OS, apps, data | Hypervisor, hardware | VM snapshot access, network isolation |\n| **PaaS** (Azure SQL, Google App Engine) | Data only | Platform, runtime | Limited log access, API-only evidence |\n| **SaaS** (Office 365, Salesforce) | Content only | Everything | API-only access, multi-tenancy |\n\n#### Cloud Deployment Models\n\n```\nPublic Cloud:    Shared infrastructure, multiple tenants\n    \u2193\nPrivate Cloud:   Dedicated infrastructure, single tenant\n    \u2193\nHybrid Cloud:    Mix of public and private\n    \u2193\nCommunity Cloud: Shared by several organizations\n```\n\n#### Cloud Forensic Challenges\n\n1. **Jurisdiction**: Data may be stored in multiple countries\n2. **Multi-tenancy**: Evidence comingled with other customers\n3. **Data volatility**: Auto-scaling deletes instances\n4. **Access**: Limited to provider APIs\n5. **Encryption**: Customer-managed keys\n6. **Chain of custody**: Multiple parties involved\n7. **Legal**: Terms of service vs. legal requirements\n\n---\n\n### 12.2 AWS Log Analysis\n\nAmazon Web Services provides extensive logging through multiple services.\n\n#### AWS CloudTrail\n\nCloudTrail records all API calls made in your AWS account.\n\n**CloudTrail Log Example:**\n```json\n{\n    \"eventVersion\": \"1.08\",\n    \"userIdentity\": {\n        \"type\": \"IAMUser\",\n        \"principalId\": \"AIDA123456789EXAMPLE\",\n        \"arn\": \"arn:aws:iam::123456789012:user/johndoe\",\n        \"accountId\": \"123456789012\",\n        \"accessKeyId\": \"AKIA123456789EXAMPLE\",\n        \"userName\": \"johndoe\"\n    },\n    \"eventTime\": \"2023-06-15T14:23:45Z\",\n    \"eventSource\": \"ec2.amazonaws.com\",\n    \"eventName\": \"RunInstances\",\n    \"awsRegion\": \"us-east-1\",\n    \"sourceIPAddress\": \"192.168.1.100\",\n    \"userAgent\": \"AWS CLI\",\n    \"requestParameters\": {\n        \"instancesSet\": {\n            \"items\": [{\n                \"imageId\": \"ami-12345678\",\n                \"instanceType\": \"t2.micro\"\n            }]\n        }\n    },\n    \"responseElements\": {\n        \"instancesSet\": {\n            \"items\": [{\n                \"instanceId\": \"i-1234567890abcdef0\"\n            }]\n        }\n    }\n}\n```\n\n#### Parsing CloudTrail Logs\n\n```python\nimport json\nimport gzip\nimport os\nfrom datetime import datetime\nfrom collections import Counter\n\ndef parse_cloudtrail_logs(log_directory):\n    \"\"\"Parse AWS CloudTrail logs from directory\"\"\"\n    \n    events = []\n    \n    for root, dirs, files in os.walk(log_directory):\n        for file in files:\n            if file.endswith('.json.gz') or file.endswith('.json'):\n                file_path = os.path.join(root, file)\n                \n                # Handle compressed logs\n                if file.endswith('.gz'):\n                    with gzip.open(file_path, 'rt') as f:\n                        data = json.load(f)\n                else:\n                    with open(file_path, 'r') as f:\n                        data = json.load(f)\n                \n                # Extract records\n                for record in data.get('Records', []):\n                    events.append({\n                        'event_time': datetime.fromisoformat(record['eventTime'].replace('Z', '+00:00')),\n                        'event_name': record['eventName'],\n                        'event_source': record['eventSource'],\n                        'user': record['userIdentity'].get('userName', 'Unknown'),\n                        'source_ip': record.get('sourceIPAddress', 'Unknown'),\n                        'region': record['awsRegion'],\n                        'user_agent': record.get('userAgent', 'Unknown'),\n                        'request': record.get('requestParameters', {}),\n                        'response': record.get('responseElements', {})\n                    })\n    \n    return events\n\ndef analyze_cloudtrail(events):\n    \"\"\"Analyze CloudTrail events for suspicious activity\"\"\"\n    \n    analysis = {\n        'total_events': len(events),\n        'time_range': {\n            'start': min(e['event_time'] for e in events) if events else None,\n            'end': max(e['event_time'] for e in events) if events else None\n        },\n        'event_counts': Counter(e['event_name'] for e in events),\n        'user_counts': Counter(e['user'] for e in events),\n        'source_ips': Counter(e['source_ip'] for e in events),\n        'suspicious_events': []\n    }\n    \n    # Identify suspicious patterns\n    suspicious_patterns = [\n        'ConsoleLogin', 'CreateUser', 'CreateAccessKey',\n        'DeleteTrail', 'StopLogging', 'UpdateTrail',\n        'AuthorizeSecurityGroupIngress', 'RunInstances',\n        'CreateKeyPair', 'DeleteKeyPair', 'ModifyInstanceAttribute'\n    ]\n    \n    for event in events:\n        # Check for sensitive events\n        if event['event_name'] in suspicious_patterns:\n            analysis['suspicious_events'].append(event)\n        \n        # Check for unusual source IPs\n        if not event['source_ip'].startswith(('10.', '172.', '192.168.')):\n            if event['source_ip'] not in analysis['source_ips']:\n                # External IP\n                analysis['suspicious_events'].append(event)\n    \n    return analysis\n\n# Parse and analyze CloudTrail\nevents = parse_cloudtrail_logs('aws_logs/')\nanalysis = analyze_cloudtrail(events)\nprint(f\"Total events: {analysis['total_events']}\")\nprint(f\"Time range: {analysis['time_range']['start']} to {analysis['time_range']['end']}\")\nprint(f\"Top events: {analysis['event_counts'].most_common(5)}\")\nprint(f\"Suspicious events: {len(analysis['suspicious_events'])}\")\n```\n\n#### AWS VPC Flow Logs\n\nVPC Flow Logs capture IP traffic information for network interfaces.\n\n**Flow Log Format:**\n```\nversion account-id interface-id srcaddr dstaddr srcport dstport protocol packets bytes start end action log-status\n2 123456789012 eni-12345678 192.168.1.10 10.0.0.5 12345 80 6 10 1024 1686824050 1686824080 ACCEPT OK\n```\n\n#### Analyzing VPC Flow Logs\n\n```python\ndef parse_vpc_flow_logs(log_file):\n    \"\"\"Parse VPC Flow Logs\"\"\"\n    \n    flows = []\n    \n    with open(log_file, 'r') as f:\n        for line in f:\n            if line.startswith('#'):\n                continue\n            \n            parts = line.strip().split()\n            if len(parts) &gt;= 14:\n                flow = {\n                    'version': parts[0],\n                    'account_id': parts[1],\n                    'interface_id': parts[2],\n                    'src_ip': parts[3],\n                    'dst_ip': parts[4],\n                    'src_port': int(parts[5]) if parts[5] != '-' else None,\n                    'dst_port': int(parts[6]) if parts[6] != '-' else None,\n                    'protocol': parts[7],\n                    'packets': int(parts[8]),\n                    'bytes': int(parts[9]),\n                    'start_time': datetime.fromtimestamp(int(parts[10])),\n                    'end_time': datetime.fromtimestamp(int(parts[11])),\n                    'action': parts[12],\n                    'log_status': parts[13]\n                }\n                flows.append(flow)\n    \n    return flows\n\ndef detect_data_exfiltration(flows, threshold_bytes=100000000):\n    \"\"\"Detect potential data exfiltration in VPC flows\"\"\"\n    \n    # Group by destination IP\n    from collections import defaultdict\n    by_dest = defaultdict(list)\n    \n    for flow in flows:\n        if flow['action'] == 'ACCEPT':\n            by_dest[flow['dst_ip']].append(flow)\n    \n    suspicious = []\n    \n    for dest_ip, dest_flows in by_dest.items():\n        total_bytes = sum(f['bytes'] for f in dest_flows)\n        \n        if total_bytes &gt; threshold_bytes:\n            # Check if destination is external\n            if not dest_ip.startswith(('10.', '172.16.', '172.17.', '172.18.', '172.19.',\n                                      '172.20.', '172.21.', '172.22.', '172.23.',\n                                      '172.24.', '172.25.', '172.26.', '172.27.',\n                                      '172.28.', '172.29.', '172.30.', '172.31.',\n                                      '192.168.')):\n                suspicious.append({\n                    'dest_ip': dest_ip,\n                    'total_bytes': total_bytes,\n                    'total_packets': sum(f['packets'] for f in dest_flows),\n                    'flow_count': len(dest_flows),\n                    'time_range': {\n                        'start': min(f['start_time'] for f in dest_flows),\n                        'end': max(f['end_time'] for f in dest_flows)\n                    }\n                })\n    \n    return suspicious\n\n# Analyze flows\nflows = parse_vpc_flow_logs('vpc_flows.log')\nexfiltration = detect_data_exfiltration(flows)\nfor ex in exfiltration:\n    print(f\"\\nSuspicious exfiltration to {ex['dest_ip']}\")\n    print(f\"  Bytes: {ex['total_bytes']:,}\")\n    print(f\"  Flows: {ex['flow_count']}\")\n    print(f\"  Time: {ex['time_range']['start']} to {ex['time_range']['end']}\")\n```\n\n#### AWS S3 Access Logs\n\n```python\ndef parse_s3_access_logs(log_file):\n    \"\"\"Parse S3 server access logs\"\"\"\n    \n    accesses = []\n    \n    with open(log_file, 'r') as f:\n        for line in f:\n            # S3 log format (space-separated with quotes)\n            parts = line.split()\n            if len(parts) &gt;= 15:\n                access = {\n                    'bucket_owner': parts[0],\n                    'bucket': parts[1],\n                    'time': datetime.strptime(f\"{parts[2]} {parts[3]}\", '[%d/%b/%Y:%H:%M:%S %z'),\n                    'remote_ip': parts[4],\n                    'requester': parts[5].strip('\"'),\n                    'request_id': parts[6],\n                    'operation': parts[7],\n                    'key': parts[8].strip('\"'),\n                    'request_uri': parts[9].strip('\"'),\n                    'status_code': int(parts[10]),\n                    'error_code': parts[11].strip('\"') if parts[11] != '-' else None,\n                    'bytes_sent': int(parts[12]) if parts[12] != '-' else 0,\n                    'object_size': int(parts[13]) if parts[13] != '-' else 0,\n                    'total_time': int(parts[14]) if parts[14] != '-' else 0\n                }\n                accesses.append(access)\n    \n    return accesses\n\ndef detect_s3_data_theft(accesses, threshold_bytes=10000000):\n    \"\"\"Detect potential data theft from S3 buckets\"\"\"\n    \n    # Group by requester and key\n    from collections import defaultdict\n    by_requester = defaultdict(lambda: defaultdict(int))\n    \n    for access in accesses:\n        if access['operation'] in ['REST.GET.OBJECT', 'REST.GET.OBJECT_GET']:\n            by_requester[access['requester']][access['key']] += access['bytes_sent']\n    \n    suspicious = []\n    \n    for requester, downloads in by_requester.items():\n        total_bytes = sum(downloads.values())\n        \n        if total_bytes &gt; threshold_bytes:\n            suspicious.append({\n                'requester': requester,\n                'total_bytes': total_bytes,\n                'files_downloaded': len(downloads),\n                'largest_files': sorted(downloads.items(), key=lambda x: x[1], reverse=True)[:5],\n                'time_range': {\n                    'start': min(a['time'] for a in accesses if a['requester'] == requester),\n                    'end': max(a['time'] for a in accesses if a['requester'] == requester)\n                }\n            })\n    \n    return suspicious\n```\n\n---\n\n### 12.3 Azure Monitoring Logs\n\nAzure provides multiple logging services through Azure Monitor.\n\n#### Azure Activity Log\n\n```python\nimport requests\nfrom azure.identity import ClientSecretCredential\nfrom azure.monitor.query import LogsQueryClient\n\ndef query_azure_activity_logs(tenant_id, client_id, client_secret, subscription_id):\n    \"\"\"Query Azure Activity Logs\"\"\"\n    \n    # Authenticate\n    credential = ClientSecretCredential(tenant_id, client_id, client_secret)\n    client = LogsQueryClient(credential)\n    \n    # Query Activity Log\n    query = f\"\"\"\n    AzureActivity\n    | where TimeGenerated &gt; ago(7d)\n    | project TimeGenerated, OperationName, Caller, Resource, \n              ResourceGroup, _ResourceId, HttpRequest\n    | order by TimeGenerated desc\n    \"\"\"\n    \n    response = client.query_workspace(\n        workspace_id=subscription_id,\n        query=query,\n        timespan=timedelta(days=7)\n    )\n    \n    events = []\n    for row in response.tables[0].rows:\n        events.append({\n            'time': row[0],\n            'operation': row[1],\n            'caller': row[2],\n            'resource': row[3],\n            'resource_group': row[4],\n            'resource_id': row[5]\n        })\n    \n    return events\n\ndef analyze_azure_activity(events):\n    \"\"\"Analyze Azure Activity Logs for security events\"\"\"\n    \n    analysis = {\n        'total_events': len(events),\n        'operations': Counter(),\n        'callers': Counter(),\n        'resources': Counter(),\n        'suspicious': []\n    }\n    \n    suspicious_operations = [\n        'Delete', 'Update', 'Write', 'Create',\n        'Authorize', 'Add', 'Remove', 'Reset'\n    ]\n    \n    for event in events:\n        analysis['operations'][event['operation']] += 1\n        analysis['callers'][event['caller']] += 1\n        analysis['resources'][event['resource']] += 1\n        \n        # Check for suspicious operations\n        if any(sus in event['operation'] for sus in suspicious_operations):\n            analysis['suspicious'].append(event)\n        \n        # Check for unusual callers\n        if event['caller'] and not '@' in event['caller']:\n            # Probably not a user email\n            analysis['suspicious'].append(event)\n    \n    return analysis\n```\n\n#### Azure Security Center Alerts\n\n```python\ndef parse_azure_security_alerts(alert_file):\n    \"\"\"Parse Azure Security Center alerts\"\"\"\n    \n    alerts = []\n    \n    with open(alert_file, 'r') as f:\n        data = json.load(f)\n        \n        for alert in data.get('value', []):\n            parsed = {\n                'id': alert.get('id'),\n                'name': alert.get('name'),\n                'type': alert.get('type'),\n                'time': alert.get('properties', {}).get('timeGenerated'),\n                'vendor': alert.get('properties', {}).get('vendorName'),\n                'severity': alert.get('properties', {}).get('severity'),\n                'description': alert.get('properties', {}).get('description'),\n                'alert_type': alert.get('properties', {}).get('alertType'),\n                'entities': alert.get('properties', {}).get('entities', [])\n            }\n            alerts.append(parsed)\n    \n    return alerts\n\ndef correlate_azure_alerts(alerts, time_window=3600):\n    \"\"\"Correlate related Azure alerts\"\"\"\n    \n    correlations = []\n    processed = set()\n    \n    for i, alert in enumerate(alerts):\n        if alert['id'] in processed:\n            continue\n        \n        alert_time = datetime.fromisoformat(alert['time'].replace('Z', '+00:00'))\n        \n        # Find related alerts within time window\n        related = [alert]\n        processed.add(alert['id'])\n        \n        for j, other in enumerate(alerts):\n            if other['id'] in processed:\n                continue\n            \n            other_time = datetime.fromisoformat(other['time'].replace('Z', '+00:00'))\n            time_diff = abs((other_time - alert_time).total_seconds())\n            \n            if time_diff &lt;= time_window:\n                # Check if entities overlap\n                if any(e in alert['entities'] for e in other['entities']):\n                    related.append(other)\n                    processed.add(other['id'])\n        \n        if len(related) &gt; 1:\n            correlations.append({\n                'time': alert_time,\n                'alerts': related,\n                'count': len(related),\n                'severities': [a['severity'] for a in related]\n            })\n    \n    return correlations\n```\n\n---\n\n### 12.4 Google Cloud Audit Logs\n\nGoogle Cloud provides audit logs for all services.\n\n#### Google Cloud Logging\n\n```python\nfrom google.cloud import logging\nfrom google.cloud.logging import DESCENDING\n\ndef query_gcp_audit_logs(project_id, days=7):\n    \"\"\"Query Google Cloud Audit Logs\"\"\"\n    \n    client = logging.Client(project=project_id)\n    \n    # Build filter\n    filter_str = f\"\"\"\n    logName=\"projects/{project_id}/logs/cloudaudit.googleapis.com%2Factivity\"\n    AND timestamp &gt;= \"{datetime.now() - timedelta(days=days)}\"\n    \"\"\"\n    \n    entries = []\n    for entry in client.list_entries(filter_=filter_str, order_by=DESCENDING):\n        entries.append({\n            'timestamp': entry.timestamp,\n            'severity': entry.severity,\n            'log_name': entry.log_name,\n            'resource': entry.resource,\n            'payload': entry.payload,\n            'proto_payload': entry.proto_payload\n        })\n        \n        if len(entries) &gt;= 10000:  # Limit\n            break\n    \n    return entries\n\ndef parse_gcp_audit_log(entry):\n    \"\"\"Parse individual GCP audit log entry\"\"\"\n    \n    if entry['proto_payload']:\n        payload = entry['proto_payload']\n        \n        parsed = {\n            'timestamp': entry['timestamp'],\n            'method': payload.get('methodName'),\n            'service': payload.get('serviceName'),\n            'resource': payload.get('resourceName'),\n            'authentication': payload.get('authenticationInfo', {}),\n            'authorization': payload.get('authorizationInfo', []),\n            'request': payload.get('request', {}),\n            'response': payload.get('response', {})\n        }\n        \n        return parsed\n    \n    return None\n```\n\n---\n\n### 12.5 Virtual Machine Artifacts\n\nVirtual machines present unique forensic artifacts beyond physical systems.\n\n#### VM File Types\n\n| Hypervisor | VM Files | Description |\n|------------|----------|-------------|\n| **VMware** | .vmdk | Virtual disk |\n| | .vmem | Memory file (when suspended) |\n| | .vmss | Suspended state |\n| | .vmsn | Snapshot |\n| | .log | VM logs |\n| **Hyper-V** | .vhdx | Virtual disk |\n| | .vmcx | Configuration |\n| | .vmrs | Runtime state |\n| | .bin | Memory file |\n| **VirtualBox** | .vdi | Virtual disk |\n| | .sav | Saved state |\n\n#### Acquiring VM Evidence\n\n```python\nimport subprocess\nimport os\nimport shutil\n\ndef acquire_vm_evidence(vm_path, output_dir):\n    \"\"\"Acquire forensic evidence from VM\"\"\"\n    \n    evidence = {}\n    \n    # 1. Copy VM files\n    if os.path.exists(vm_path):\n        vm_name = os.path.basename(vm_path)\n        vm_evidence_dir = os.path.join(output_dir, vm_name)\n        os.makedirs(vm_evidence_dir, exist_ok=True)\n        \n        # Copy all VM files\n        for item in os.listdir(vm_path):\n            src = os.path.join(vm_path, item)\n            dst = os.path.join(vm_evidence_dir, item)\n            \n            if os.path.isfile(src):\n                shutil.copy2(src, dst)\n                evidence[item] = {\n                    'path': dst,\n                    'size': os.path.getsize(src),\n                    'modified': datetime.fromtimestamp(os.path.getmtime(src))\n                }\n    \n    # 2. Convert VMDK to raw for analysis\n    for file in evidence:\n        if file.endswith('.vmdk') and not file.endswith('-flat.vmdk'):\n            vmdk_path = evidence[file]['path']\n            raw_path = vmdk_path.replace('.vmdk', '.raw')\n            \n            try:\n                # Use qemu-img to convert\n                subprocess.run([\n                    'qemu-img', 'convert', '-f', 'vmdk',\n                    '-O', 'raw', vmdk_path, raw_path\n                ], check=True)\n                \n                evidence['raw_disk'] = {\n                    'path': raw_path,\n                    'size': os.path.getsize(raw_path)\n                }\n            except:\n                print(f\"Failed to convert {vmdk_path}\")\n    \n    return evidence\n\ndef parse_vm_logs(vm_path):\n    \"\"\"Parse VM logs for forensic evidence\"\"\"\n    \n    logs = []\n    \n    # Find log files\n    for root, dirs, files in os.walk(vm_path):\n        for file in files:\n            if file.endswith('.log'):\n                log_path = os.path.join(root, file)\n                \n                with open(log_path, 'r') as f:\n                    for line in f:\n                        # Parse VMware log format\n                        if '|' in line:\n                            parts = line.split('|')\n                            if len(parts) &gt;= 4:\n                                logs.append({\n                                    'timestamp': parts[0].strip(),\n                                    'thread': parts[1].strip(),\n                                    'level': parts[2].strip(),\n                                    'module': parts[3].strip(),\n                                    'message': '|'.join(parts[4:]).strip()\n                                })\n    \n    return logs\n```\n\n#### Analyzing VM Snapshots\n\n```python\ndef analyze_vm_snapshots(vm_path):\n    \"\"\"Analyze VM snapshots for timeline\"\"\"\n    \n    snapshots = []\n    \n    # Look for snapshot files\n    for root, dirs, files in os.walk(vm_path):\n        for file in files:\n            if file.endswith('.vmsn') or file.endswith('.vmss'):\n                snapshot_path = os.path.join(root, file)\n                stat = os.stat(snapshot_path)\n                \n                snapshots.append({\n                    'file': file,\n                    'path': snapshot_path,\n                    'type': 'snapshot' if file.endswith('.vmsn') else 'suspended',\n                    'created': datetime.fromtimestamp(stat.st_ctime),\n                    'modified': datetime.fromtimestamp(stat.st_mtime),\n                    'size': stat.st_size\n                })\n    \n    # Sort by time\n    snapshots.sort(key=lambda x: x['created'])\n    \n    return snapshots\n\ndef extract_snapshot_memory(vmsn_path):\n    \"\"\"Extract memory from VMware snapshot\"\"\"\n    \n    # vmsn files contain memory state\n    # This is complex - typically use volatility with vmware snapshot support\n    \n    import volatility3\n    \n    # Volatility 3 can analyze .vmsn files directly\n    result = subprocess.run([\n        'python3', 'vol.py', '-f', vmsn_path, 'windows.info'\n    ], capture_output=True, text=True)\n    \n    return result.stdout\n```\n\n---\n\n### 12.6 Container Forensics\n\nContainers (Docker, Kubernetes) present new forensic challenges.\n\n#### Docker Container Artifacts\n\n```python\nimport docker\nimport tarfile\nimport io\n\ndef analyze_docker_container(container_id):\n    \"\"\"Forensic analysis of Docker container\"\"\"\n    \n    client = docker.from_env()\n    \n    analysis = {}\n    \n    try:\n        container = client.containers.get(container_id)\n        \n        # Basic info\n        analysis['info'] = {\n            'id': container.id,\n            'name': container.name,\n            'image': container.image.tags,\n            'status': container.status,\n            'created': container.attrs['Created'],\n            'command': container.attrs['Config']['Cmd'],\n            'entrypoint': container.attrs['Config']['Entrypoint']\n        }\n        \n        # Export filesystem\n        bits, stat = container.get_archive('/')\n        \n        # Save to tar file\n        with open(f\"{container_id}_fs.tar\", 'wb') as f:\n            for chunk in bits:\n                f.write(chunk)\n        \n        # Get logs\n        analysis['logs'] = container.logs(timestamps=True).decode('utf-8', errors='ignore')\n        \n        # Get process list\n        top = container.top()\n        analysis['processes'] = top.get('Processes', [])\n        \n        # Get mounts\n        analysis['mounts'] = container.attrs.get('Mounts', [])\n        \n    except Exception as e:\n        print(f\"Error analyzing container: {e}\")\n    \n    return analysis\n\ndef analyze_container_image(image_name):\n    \"\"\"Analyze container image layers\"\"\"\n    \n    client = docker.from_env()\n    \n    analysis = {\n        'layers': [],\n        'config': {},\n        'vulnerabilities': []\n    }\n    \n    try:\n        image = client.images.get(image_name)\n        \n        # Get image history\n        history = image.history()\n        for layer in history:\n            analysis['layers'].append({\n                'id': layer.get('Id'),\n                'created': layer.get('Created'),\n                'created_by': layer.get('CreatedBy'),\n                'size': layer.get('Size'),\n                'tags': layer.get('Tags', [])\n            })\n        \n        # Get image config\n        analysis['config'] = image.attrs.get('Config', {})\n        \n        # Check for vulnerabilities (simplified)\n        # In practice, use Trivy, Clair, etc.\n        \n    except Exception as e:\n        print(f\"Error analyzing image: {e}\")\n    \n    return analysis\n```\n\n#### Kubernetes Forensics\n\n```python\nfrom kubernetes import client, config\n\ndef analyze_kubernetes_cluster(kubeconfig_path):\n    \"\"\"Forensic analysis of Kubernetes cluster\"\"\"\n    \n    # Load config\n    config.load_kube_config(config_file=kubeconfig_path)\n    \n    v1 = client.CoreV1Api()\n    apps_v1 = client.AppsV1Api()\n    \n    analysis = {\n        'nodes': [],\n        'pods': [],\n        'services': [],\n        'events': [],\n        'configmaps': [],\n        'secrets': []\n    }\n    \n    # Get nodes\n    nodes = v1.list_node()\n    for node in nodes.items:\n        analysis['nodes'].append({\n            'name': node.metadata.name,\n            'status': node.status.conditions[-1].type if node.status.conditions else 'Unknown',\n            'addresses': [addr.address for addr in node.status.addresses],\n            'capacity': node.status.capacity,\n            'labels': node.metadata.labels\n        })\n    \n    # Get pods\n    pods = v1.list_pod_for_all_namespaces()\n    for pod in pods.items:\n        analysis['pods'].append({\n            'namespace': pod.metadata.namespace,\n            'name': pod.metadata.name,\n            'status': pod.status.phase,\n            'node': pod.spec.node_name,\n            'containers': [c.name for c in pod.spec.containers],\n            'labels': pod.metadata.labels,\n            'start_time': pod.status.start_time\n        })\n    \n    # Get events\n    events = v1.list_event_for_all_namespaces()\n    for event in events.items:\n        analysis['events'].append({\n            'namespace': event.metadata.namespace,\n            'type': event.type,\n            'reason': event.reason,\n            'message': event.message,\n            'source': event.source.component if event.source else None,\n            'first_seen': event.first_timestamp,\n            'last_seen': event.last_timestamp,\n            'count': event.count\n        })\n    \n    # Get configmaps (be careful with sensitive data)\n    configmaps = v1.list_config_map_for_all_namespaces()\n    for cm in configmaps.items:\n        analysis['configmaps'].append({\n            'namespace': cm.metadata.namespace,\n            'name': cm.metadata.name,\n            'keys': list(cm.data.keys()) if cm.data else []\n        })\n    \n    return analysis\n\ndef get_pod_logs(pod_namespace, pod_name, container_name=None):\n    \"\"\"Get logs from specific pod\"\"\"\n    \n    config.load_kube_config()\n    v1 = client.CoreV1Api()\n    \n    # Get logs\n    logs = v1.read_namespaced_pod_log(\n        name=pod_name,\n        namespace=pod_namespace,\n        container=container_name,\n        timestamps=True,\n        tail_lines=1000  # Last 1000 lines\n    )\n    \n    return logs\n```\n\n---\n\n### 12.7 Kubernetes Investigation Workflow\n\n#### Complete Kubernetes Incident Response\n\n```python\ndef kubernetes_incident_response(kubeconfig_path, compromised_namespace, compromised_pod):\n    \"\"\"Complete incident response workflow for Kubernetes\"\"\"\n    \n    import yaml\n    from datetime import datetime\n    \n    incident_data = {\n        'timestamp': datetime.now(),\n        'cluster_info': {},\n        'pod_info': {},\n        'container_logs': {},\n        'network_policies': [],\n        'rbac_info': {},\n        'timeline': []\n    }\n    \n    # Load config\n    config.load_kube_config(config_file=kubeconfig_path)\n    v1 = client.CoreV1Api()\n    rbac_v1 = client.RbacAuthorizationV1Api()\n    networking_v1 = client.NetworkingV1Api()\n    \n    # 1. Get pod details\n    pod = v1.read_namespaced_pod(compromised_pod, compromised_namespace)\n    incident_data['pod_info'] = {\n        'name': pod.metadata.name,\n        'namespace': pod.metadata.namespace,\n        'uid': pod.metadata.uid,\n        'labels': pod.metadata.labels,\n        'annotations': pod.metadata.annotations,\n        'node': pod.spec.node_name,\n        'containers': [],\n        'status': pod.status.phase,\n        'start_time': pod.status.start_time\n    }\n    \n    # 2. Get container info and logs\n    for container in pod.spec.containers:\n        container_info = {\n            'name': container.name,\n            'image': container.image,\n            'command': container.command,\n            'args': container.args,\n            'ports': [p.container_port for p in container.ports] if container.ports else [],\n            'env': [{'name': e.name, 'value': e.value} for e in container.env] if container.env else []\n        }\n        \n        # Get logs\n        try:\n            logs = v1.read_namespaced_pod_log(\n                name=compromised_pod,\n                namespace=compromised_namespace,\n                container=container.name,\n                timestamps=True,\n                tail_lines=10000\n            )\n            incident_data['container_logs'][container.name] = logs\n        except:\n            incident_data['container_logs'][container.name] = \"Logs unavailable\"\n        \n        incident_data['pod_info']['containers'].append(container_info)\n    \n    # 3. Get events for this pod\n    events = v1.list_namespaced_event(compromised_namespace)\n    for event in events.items:\n        if event.involved_object.name == compromised_pod:\n            incident_data['timeline'].append({\n                'time': event.last_timestamp or event.first_timestamp,\n                'type': event.type,\n                'reason': event.reason,\n                'message': event.message,\n                'source': event.source.component if event.source else None\n            })\n    \n    # 4. Check network policies affecting this pod\n    network_policies = networking_v1.list_namespaced_network_policy(compromised_namespace)\n    for np in network_policies.items:\n        # Check if policy selects this pod\n        if np.spec.pod_selector.match_labels:\n            if all(item in pod.metadata.labels.items() \n                   for item in np.spec.pod_selector.match_labels.items()):\n                incident_data['network_policies'].append({\n                    'name': np.metadata.name,\n                    'policy_types': np.spec.policy_types,\n                    'ingress_rules': len(np.spec.ingress) if np.spec.ingress else 0,\n                    'egress_rules': len(np.spec.egress) if np.spec.egress else 0\n                })\n    \n    # 5. Check RBAC permissions\n    roles = rbac_v1.list_namespaced_role(compromised_namespace)\n    rolebindings = rbac_v1.list_namespaced_role_binding(compromised_namespace)\n    \n    incident_data['rbac_info'] = {\n        'roles': [],\n        'bindings': []\n    }\n    \n    for role in roles.items:\n        incident_data['rbac_info']['roles'].append({\n            'name': role.metadata.name,\n            'rules': len(role.rules)\n        })\n    \n    for binding in rolebindings.items:\n        # Check if this binding affects the pod's service account\n        if binding.subjects:\n            for subject in binding.subjects:\n                if subject.kind == 'ServiceAccount' and subject.namespace == compromised_namespace:\n                    incident_data['rbac_info']['bindings'].append({\n                        'name': binding.metadata.name,\n                        'role': binding.role_ref.name,\n                        'subject': subject.name\n                    })\n    \n    # 6. Export for preservation\n    with open(f\"k8s_incident_{compromised_namespace}_{compromised_pod}.yaml\", 'w') as f:\n        yaml.dump(incident_data, f)\n    \n    return incident_data\n\n# Run investigation\nincident = kubernetes_incident_response(\n    '~/.kube/config',\n    'production',\n    'compromised-pod-abc123'\n)\n\nprint(f\"Investigation complete for pod {incident['pod_info']['name']}\")\nprint(f\"Containers: {len(incident['pod_info']['containers'])}\")\nprint(f\"Events found: {len(incident['timeline'])}\")\n```\n\n#### Container Image Forensics\n\n```python\ndef analyze_container_image_filesystem(image_name):\n    \"\"\"Extract and analyze container image filesystem\"\"\"\n    \n    import tarfile\n    import tempfile\n    import os\n    \n    client = docker.from_env()\n    \n    # Pull image if not present\n    try:\n        image = client.images.get(image_name)\n    except:\n        print(f\"Pulling image {image_name}\")\n        image = client.images.pull(image_name)\n    \n    # Save image to tar\n    with tempfile.NamedTemporaryFile(suffix='.tar', delete=False) as tmp:\n        with open(tmp.name, 'wb') as f:\n            for chunk in image.save():\n                f.write(chunk)\n    \n    # Extract tar\n    extract_dir = tempfile.mkdtemp()\n    with tarfile.open(tmp.name) as tar:\n        tar.extractall(extract_dir)\n    \n    # Analyze layers\n    layers = []\n    for item in os.listdir(extract_dir):\n        if os.path.isdir(os.path.join(extract_dir, item)):\n            # Check if it's a layer directory\n            layer_path = os.path.join(extract_dir, item, 'layer.tar')\n            if os.path.exists(layer_path):\n                layer_info = analyze_layer(layer_path)\n                layers.append(layer_info)\n    \n    # Cleanup\n    os.unlink(tmp.name)\n    # In practice, would clean up extract_dir\n    \n    return {\n        'image': image_name,\n        'layers': layers,\n        'total_layers': len(layers)\n    }\n\ndef analyze_layer(layer_tar_path):\n    \"\"\"Analyze a single container layer\"\"\"\n    \n    import hashlib\n    \n    analysis = {\n        'files': [],\n        'suspicious_files': [],\n        'total_size': 0,\n        'hash': None\n    }\n    \n    # Calculate layer hash\n    with open(layer_tar_path, 'rb') as f:\n        analysis['hash'] = hashlib.sha256(f.read()).hexdigest()\n    \n    # Analyze contents\n    with tarfile.open(layer_tar_path) as tar:\n        for member in tar.getmembers():\n            file_info = {\n                'name': member.name,\n                'size': member.size,\n                'mode': member.mode,\n                'type': 'dir' if member.isdir() else 'file' if member.isfile() else 'link',\n                'mtime': member.mtime\n            }\n            analysis['files'].append(file_info)\n            analysis['total_size'] += member.size\n            \n            # Check for suspicious files\n            suspicious_patterns = ['.sh', 'bash', 'python', 'perl', 'wget', 'curl']\n            if any(pattern in member.name for pattern in suspicious_patterns):\n                analysis['suspicious_files'].append(file_info)\n    \n    return analysis\n```\n\n---\n\n# PART VI \u2013 MOBILE, IoT &amp; EMERGING TECH\n\n---\n\n## Chapter 13 \u2013 Mobile Forensics\n\n---\n\n### 13.1 Introduction to Mobile Forensics\n\nMobile devices have become ubiquitous and contain vast amounts of personal and professional data. Unlike traditional computers, mobile devices present unique challenges including encryption, diverse operating systems, and constant network connectivity.\n\n#### Mobile Device Evidence Types\n\n| Data Category | Examples | Forensic Value |\n|--------------|----------|----------------|\n| **Communications** | Calls, SMS, MMS, VoIP logs | Contacts, timeline |\n| **Messaging Apps** | WhatsApp, Signal, Telegram | Conversations, media |\n| **Location Data** | GPS coordinates, WiFi networks | Movement tracking |\n| **Application Data** | Social media, email, notes | User activity |\n| **System Data** | Call logs, contacts, calendars | Personal information |\n| **Media** | Photos, videos, audio files | Visual evidence |\n| **Cloud Data** | iCloud, Google Drive, OneDrive | Extended storage |\n\n#### Mobile Forensic Process\n\n```\n1. SEIZURE\n   - Isolate from network (Faraday bag)\n   - Preserve power (don't let battery die)\n   - Document device state\n   - Note lock screen/passcode\n\n2. ACQUISITION\n   - Logical (file system access)\n   - Physical (bit-for-bit copy)\n   - Chip-off (direct memory read)\n   - Cloud (backup extraction)\n\n3. EXAMINATION\n   - Parse databases\n   - Extract artifacts\n   - Recover deleted data\n   - Decrypt if possible\n\n4. ANALYSIS\n   - Timeline creation\n   - Communications mapping\n   - Location tracking\n   - App usage patterns\n\n5. REPORTING\n   - Document findings\n   - Visualize relationships\n   - Expert testimony\n```\n\n---\n\n### 13.2 Android File System\n\nAndroid is based on Linux and uses similar file system structures.\n\n#### Android Partition Layout\n\n```\n/boot          - Kernel and ramdisk\n/system         - System files (read-only)\n/data           - User data and apps\n/cache          - Temporary files\n/recovery       - Recovery mode\n/sdcard         - External/emulated storage\n```\n\n#### Key Android Forensic Locations\n\n| Path | Content | Forensic Value |\n|------|---------|----------------|\n| /data/data/com.android.providers.telephony/databases/mmssms.db | SMS/MMS messages | Communications |\n| /data/data/com.android.providers.contacts/databases/contacts2.db | Contacts | Contact list |\n| /data/data/com.android.providers.calendar/databases/calendar.db | Calendar events | Schedule |\n| /data/data/com.android.browser/databases/browser.db | Browser history | Web activity |\n| /data/data/com.google.android.gms/databases/ | Google services | Location, searches |\n| /data/data/com.whatsapp/databases/ | WhatsApp data | Messages, media |\n| /data/system/gesture.key | Screen lock pattern | Authentication |\n| /data/system/password.key | Password hash | Authentication |\n| /data/misc/wifi/wpa_supplicant.conf | WiFi passwords | Network access |\n\n#### Android SQLite Database Analysis\n\n```python\nimport sqlite3\nimport os\nfrom datetime import datetime\n\ndef analyze_android_sms(mmssms_db):\n    \"\"\"Analyze Android SMS/MMS database\"\"\"\n    \n    conn = sqlite3.connect(mmssms_db)\n    cursor = conn.cursor()\n    \n    messages = []\n    \n    # Query SMS table\n    cursor.execute(\"\"\"\n        SELECT address, date, date_sent, body, type, read, status\n        FROM sms\n        ORDER BY date DESC\n    \"\"\")\n    \n    for row in cursor.fetchall():\n        # Android stores dates in milliseconds since 1970\n        date_received = datetime.fromtimestamp(int(row[1]) / 1000) if row[1] else None\n        date_sent = datetime.fromtimestamp(int(row[2]) / 1000) if row[2] else None\n        \n        # Message type: 1=inbox, 2=sent, 3=draft, 4=outbox\n        msg_type = ['Unknown', 'Inbox', 'Sent', 'Draft', 'Outbox'][row[4]] if row[4] &lt;= 4 else 'Unknown'\n        \n        messages.append({\n            'address': row[0],\n            'date_received': date_received,\n            'date_sent': date_sent,\n            'body': row[3],\n            'type': msg_type,\n            'read': bool(row[5]),\n            'status': row[6]\n        })\n    \n    conn.close()\n    return messages\n\ndef analyze_android_contacts(contacts_db):\n    \"\"\"Analyze Android contacts database\"\"\"\n    \n    conn = sqlite3.connect(contacts_db)\n    cursor = conn.cursor()\n    \n    contacts = []\n    \n    # Query contacts\n    cursor.execute(\"\"\"\n        SELECT display_name, data1, data2, data3\n        FROM view_contacts\n        WHERE display_name IS NOT NULL\n    \"\"\")\n    \n    for row in cursor.fetchall():\n        contact = {\n            'name': row[0],\n            'phone': row[1],\n            'type': row[2],\n            'label': row[3]\n        }\n        contacts.append(contact)\n    \n    conn.close()\n    return contacts\n\ndef analyze_android_call_logs(call_logs_db):\n    \"\"\"Analyze Android call logs\"\"\"\n    \n    conn = sqlite3.connect(call_logs_db)\n    cursor = conn.cursor()\n    \n    calls = []\n    \n    cursor.execute(\"\"\"\n        SELECT number, date, duration, type, name\n        FROM calls\n        ORDER BY date DESC\n    \"\"\")\n    \n    for row in cursor.fetchall():\n        # Call type: 1=incoming, 2=outgoing, 3=missed\n        call_type = ['Unknown', 'Incoming', 'Outgoing', 'Missed'][row[3]] if row[3] &lt;= 3 else 'Unknown'\n        \n        calls.append({\n            'number': row[0],\n            'date': datetime.fromtimestamp(int(row[1]) / 1000) if row[1] else None,\n            'duration': row[2],\n            'type': call_type,\n            'contact_name': row[4]\n        })\n    \n    conn.close()\n    return calls\n```\n\n#### Android App Data Analysis\n\n```python\ndef analyze_whatsapp(whatsapp_db):\n    \"\"\"Analyze WhatsApp database\"\"\"\n    \n    conn = sqlite3.connect(whatsapp_db)\n    cursor = conn.cursor()\n    \n    messages = []\n    \n    # Get messages\n    cursor.execute(\"\"\"\n        SELECT chat_list.key_remote_jid, messages.timestamp, \n               messages.data, messages.media_url, messages.media_mime_type,\n               messages.received_timestamp, messages.sender_jid\n        FROM messages\n        JOIN chat_list ON messages.chat_row_id = chat_list._id\n        ORDER BY messages.timestamp DESC\n    \"\"\")\n    \n    for row in cursor.fetchall():\n        messages.append({\n            'chat': row[0],\n            'timestamp': datetime.fromtimestamp(int(row[1]) / 1000) if row[1] else None,\n            'message': row[2],\n            'media_url': row[3],\n            'media_type': row[4],\n            'received_time': datetime.fromtimestamp(int(row[5]) / 1000) if row[5] else None,\n            'sender': row[6]\n        })\n    \n    # Get contacts\n    cursor.execute(\"SELECT jid, display_name, phone FROM wa_contacts\")\n    contacts = cursor.fetchall()\n    \n    conn.close()\n    \n    return {\n        'messages': messages,\n        'contacts': contacts\n    }\n\ndef recover_deleted_whatsapp(whatsapp_db):\n    \"\"\"Attempt recovery of deleted WhatsApp messages\"\"\"\n    \n    # WhatsApp uses SQLite with write-ahead logging\n    # Deleted messages may remain in WAL file\n    \n    wal_file = whatsapp_db + '-wal'\n    \n    if os.path.exists(wal_file):\n        with open(wal_file, 'rb') as f:\n            data = f.read()\n        \n        # Look for message patterns\n        import re\n        message_pattern = re.compile(b'[^\\x00]{5,200}')  # Non-null strings\n        \n        potential_messages = []\n        for match in message_pattern.finditer(data):\n            try:\n                msg = match.group().decode('utf-8', errors='ignore')\n                if len(msg) &gt; 10:\n                    potential_messages.append(msg)\n            except:\n                continue\n        \n        return potential_messages\n    \n    return []\n```\n\n---\n\n### 13.3 iOS Acquisition\n\niOS devices present significant challenges due to strong encryption and security features.\n\n#### iOS File System\n\n```\n/               - Root filesystem (read-only)\n/private/var/   - User data and apps\n/private/var/mobile/ - Mobile user home\n/private/var/mobile/Applications/ - Third-party apps (iOS 9 and earlier)\n/private/var/mobile/Containers/ - App containers (iOS 10+)\n/private/var/mobile/Library/ - User data\n/private/var/keychains/ - Keychain data\n```\n\n#### iOS Acquisition Methods\n\n| Method | Requirements | Data Obtained | Limitations |\n|--------|--------------|---------------|-------------|\n| **Logical** | Device unlocked | Media, contacts, messages | No deleted data |\n| **Backup** | Password (maybe) | Most user data | Encrypted backups |\n| **Physical** | Jailbreak required | Full file system | Breaks device |\n| **iCloud** | Apple ID credentials | Cloud data | Incomplete |\n| **Checkm8** | A5-A11 devices | Full physical | Hardware exploit |\n\n#### iOS Backup Analysis\n\n```python\nimport plistlib\nimport sqlite3\nimport os\nfrom datetime import datetime\n\ndef parse_ios_backup(backup_path):\n    \"\"\"Parse iOS backup directory\"\"\"\n    \n    # iOS backup structure:\n    # Info.plist - Backup information\n    # Manifest.plist - File listing\n    # Status.plist - Backup status\n    # [file_hash] - Actual files (40-character hex names)\n    \n    backup_info = {}\n    \n    # Read Info.plist\n    info_path = os.path.join(backup_path, 'Info.plist')\n    if os.path.exists(info_path):\n        with open(info_path, 'rb') as f:\n            backup_info['info'] = plistlib.load(f)\n    \n    # Read Manifest.plist\n    manifest_path = os.path.join(backup_path, 'Manifest.plist')\n    if os.path.exists(manifest_path):\n        with open(manifest_path, 'rb') as f:\n            manifest = plistlib.load(f)\n            backup_info['manifest'] = manifest\n            \n            # Get backup info\n            backup_info['device_name'] = manifest.get('Lockdown', {}).get('DeviceName')\n            backup_info['product_type'] = manifest.get('Lockdown', {}).get('ProductType')\n            backup_info['product_version'] = manifest.get('Lockdown', {}).get('ProductVersion')\n            backup_info['serial'] = manifest.get('Lockdown', {}).get('SerialNumber')\n            backup_info['backup_time'] = manifest.get('Date')\n    \n    return backup_info\n\ndef extract_ios_sms(backup_path):\n    \"\"\"Extract SMS from iOS backup\"\"\"\n    \n    # SMS database location in backup\n    # sms.db is stored with a hash name\n    \n    # Find sms.db\n    sms_db = None\n    for root, dirs, files in os.walk(backup_path):\n        for file in files:\n            if file.endswith('3d0d7e5fb2ce288813306e4d4636395e047a3d28'):  # sms.db hash\n                sms_db = os.path.join(root, file)\n                break\n    \n    if not sms_db:\n        return []\n    \n    conn = sqlite3.connect(sms_db)\n    cursor = conn.cursor()\n    \n    messages = []\n    \n    # iOS stores dates as Mac Absolute Time (seconds since 2001-01-01)\n    def mac_abs_to_datetime(mac_abs):\n        if mac_abs:\n            return datetime(2001, 1, 1) + timedelta(seconds=mac_abs)\n        return None\n    \n    cursor.execute(\"\"\"\n        SELECT message.rowid, message.date, message.text, \n               message.is_from_me, message.cache_has_attachments,\n               handle.id as contact, chat.chat_identifier\n        FROM message\n        LEFT JOIN handle ON message.handle_id = handle.ROWID\n        LEFT JOIN chat_message_join ON message.ROWID = chat_message_join.message_id\n        LEFT JOIN chat ON chat_message_join.chat_id = chat.ROWID\n        ORDER BY message.date DESC\n    \"\"\")\n    \n    for row in cursor.fetchall():\n        messages.append({\n            'id': row[0],\n            'date': mac_abs_to_datetime(row[1]),\n            'text': row[2],\n            'is_from_me': bool(row[3]),\n            'has_attachments': bool(row[4]),\n            'contact': row[5],\n            'chat': row[6]\n        })\n    \n    conn.close()\n    return messages\n\ndef extract_ios_contacts(backup_path):\n    \"\"\"Extract contacts from iOS backup\"\"\"\n    \n    # Contacts database: 31bb7ba8914766d4ba40d6dfb6113c8b614be442\n    contacts_db = None\n    \n    for root, dirs, files in os.walk(backup_path):\n        for file in files:\n            if file == '31bb7ba8914766d4ba40d6dfb6113c8b614be442':\n                contacts_db = os.path.join(root, file)\n                break\n    \n    if not contacts_db:\n        return []\n    \n    conn = sqlite3.connect(contacts_db)\n    cursor = conn.cursor()\n    \n    contacts = []\n    \n    cursor.execute(\"\"\"\n        SELECT ABPerson.ROWID, First, Last, Organization,\n               ABMultiValue.value, ABMultiValue.label\n        FROM ABPerson\n        LEFT JOIN ABMultiValue ON ABPerson.ROWID = ABMultiValue.record_id\n        WHERE ABMultiValue.property = 3  -- Phone numbers\n    \"\"\")\n    \n    for row in cursor.fetchall():\n        contact = {\n            'id': row[0],\n            'first_name': row[1],\n            'last_name': row[2],\n            'organization': row[3],\n            'phone': row[4],\n            'phone_label': row[5]\n        }\n        contacts.append(contact)\n    \n    conn.close()\n    return contacts\n```\n\n#### iOS Keychain Analysis\n\n```python\ndef extract_ios_keychain(backup_path):\n    \"\"\"Extract keychain data from iOS backup\"\"\"\n    \n    # Keychain database: keychain-2.db\n    keychain_db = None\n    \n    for root, dirs, files in os.walk(backup_path):\n        for file in files:\n            if file == 'keychain-2.db':\n                keychain_db = os.path.join(root, file)\n                break\n    \n    if not keychain_db:\n        return []\n    \n    conn = sqlite3.connect(keychain_db)\n    cursor = conn.cursor()\n    \n    items = []\n    \n    cursor.execute(\"\"\"\n        SELECT agrp, cdat, mdat, desc, labl, \n               acct, data, svce, ptcl, port\n        FROM genp  -- Generic passwords\n        UNION\n        SELECT agrp, cdat, mdat, desc, labl,\n               acct, data, svce, ptcl, port\n        FROM inet  -- Internet passwords\n    \"\"\")\n    \n    for row in cursor.fetchall():\n        items.append({\n            'group': row[0],\n            'created': row[1],\n            'modified': row[2],\n            'description': row[3],\n            'label': row[4],\n            'account': row[5],\n            'data': row[6],  # Encrypted\n            'service': row[7],\n            'protocol': row[8],\n            'port': row[9]\n        })\n    \n    conn.close()\n    return items\n```\n\n---\n\n### 13.4 Encrypted Device Challenges\n\nModern mobile devices are encrypted by default, creating significant forensic challenges.\n\n#### iOS Encryption\n\n```\nHardware: AES-256 engine in Secure Enclave\nFile-level: Per-file keys wrapped with class keys\nClass keys: Protected by user passcode\n```\n\n**iOS Data Protection Classes:**\n\n| Class | Description | Availability |\n|-------|-------------|--------------|\n| **NSFileProtectionComplete** | File only accessible when device unlocked | Device locked = inaccessible |\n| **NSFileProtectionCompleteUnlessOpen** | File can be accessed while open after unlock | Open files remain accessible |\n| **NSFileProtectionCompleteUntilFirstUserAuthentication** | Accessible after first unlock until shutdown | Most system files |\n| **NSFileProtectionNone** | No protection | Some caches |\n\n#### Android Encryption\n\n```\nFull Disk Encryption (FDE): Encrypts entire /data partition\nFile-Based Encryption (FBE): Different keys for different files\nDirect Boot: Some files accessible before user unlocks\n```\n\n#### Bypass Strategies\n\n| Technique | Success Rate | Requirements |\n|-----------|--------------|--------------|\n| **Passcode cracking** | Low (iOS) / Medium (Android) | Time, hardware |\n| **Forensic tools** | Medium | Expensive tools |\n| **Vulnerability exploit** | High | Specific iOS/Android versions |\n| **Chip-off** | High | Specialized equipment |\n| **Cloud extraction** | Medium | User credentials |\n| **Social engineering** | Variable | User cooperation |\n\n#### Passcode Extraction Attempt\n\n```python\nimport hashlib\nimport itertools\nfrom datetime import datetime\n\ndef brute_force_android_passcode(passwd_file, max_length=4):\n    \"\"\"Attempt to brute force Android passcode\"\"\"\n    \n    # Android stores password as SHA1 hash\n    with open(passwd_file, 'rb') as f:\n        target_hash = f.read().hex()\n    \n    # Common patterns\n    patterns = [\n        '1234', '0000', '1111', '1212', '123456',\n        'password', 'admin', '000000', '111111'\n    ]\n    \n    # Try common patterns first\n    for pattern in patterns:\n        hash_value = hashlib.sha1(pattern.encode()).hexdigest()\n        if hash_value == target_hash:\n            return pattern\n    \n    # Brute force digits\n    chars = '0123456789'\n    \n    for length in range(1, max_length + 1):\n        for combo in itertools.product(chars, repeat=length):\n            attempt = ''.join(combo)\n            hash_value = hashlib.sha1(attempt.encode()).hexdigest()\n            if hash_value == target_hash:\n                return attempt\n            \n            # Progress indicator for long runs\n            if int(combo[0]) % 100 == 0:\n                print(f\"Trying {attempt}\")\n    \n    return None\n\ndef check_ios_passcode(backup_path, passcode):\n    \"\"\"Check if passcode works for iOS backup\"\"\"\n    \n    # iOS encrypted backups use passcode to derive key\n    manifest_path = os.path.join(backup_path, 'Manifest.plist')\n    \n    with open(manifest_path, 'rb') as f:\n        manifest = plistlib.load(f)\n    \n    # Check if backup is encrypted\n    if manifest.get('IsEncrypted'):\n        # Would need to attempt decryption\n        # This is complex - uses PBKDF2 with salt and iterations\n        pass\n    \n    return False\n```\n\n---\n\n### 13.5 Messaging App Investigations\n\nMessaging apps contain rich evidence including messages, media, and metadata.\n\n#### WhatsApp Artifacts\n\n```python\ndef analyze_whatsapp_full(whatsapp_path):\n    \"\"\"Comprehensive WhatsApp analysis\"\"\"\n    \n    analysis = {\n        'messages': [],\n        'media': [],\n        'contacts': [],\n        'calls': [],\n        'status': [],\n        'settings': {}\n    }\n    \n    # Messages database\n    msg_db = os.path.join(whatsapp_path, 'Databases', 'msgstore.db')\n    if os.path.exists(msg_db):\n        conn = sqlite3.connect(msg_db)\n        cursor = conn.cursor()\n        \n        # Get all messages with details\n        cursor.execute(\"\"\"\n            SELECT chat_view.chat_name, messages.timestamp,\n                   messages.data, messages.media_url,\n                   messages.media_size, messages.media_mime_type,\n                   messages.received_timestamp, messages.sender_jid,\n                   messages.starred, messages.forwarded\n            FROM messages\n            LEFT JOIN chat_view ON messages.chat_row_id = chat_view._id\n            ORDER BY messages.timestamp DESC\n        \"\"\")\n        \n        for row in cursor.fetchall():\n            analysis['messages'].append({\n                'chat': row[0],\n                'timestamp': datetime.fromtimestamp(int(row[1]) / 1000) if row[1] else None,\n                'text': row[2],\n                'media_url': row[3],\n                'media_size': row[4],\n                'media_type': row[5],\n                'received_time': datetime.fromtimestamp(int(row[6]) / 1000) if row[6] else None,\n                'sender': row[7],\n                'starred': bool(row[8]),\n                'forwarded': bool(row[9])\n            })\n        \n        # Get contacts\n        cursor.execute(\"SELECT jid, display_name, phone FROM wa_contacts\")\n        analysis['contacts'] = [\n            {'jid': r[0], 'name': r[1], 'phone': r[2]}\n            for r in cursor.fetchall()\n        ]\n        \n        # Get calls\n        cursor.execute(\"\"\"\n            SELECT jid, timestamp, duration, call_result\n            FROM wa_calls\n            ORDER BY timestamp DESC\n        \"\"\")\n        \n        analysis['calls'] = [\n            {\n                'contact': r[0],\n                'time': datetime.fromtimestamp(int(r[1]) / 1000) if r[1] else None,\n                'duration': r[2],\n                'result': r[3]\n            }\n            for r in cursor.fetchall()\n        ]\n        \n        conn.close()\n    \n    # Media files\n    media_path = os.path.join(whatsapp_path, 'Media')\n    if os.path.exists(media_path):\n        for root, dirs, files in os.walk(media_path):\n            for file in files:\n                file_path = os.path.join(root, file)\n                stat = os.stat(file_path)\n                analysis['media'].append({\n                    'path': file_path,\n                    'size': stat.st_size,\n                    'created': datetime.fromtimestamp(stat.st_ctime),\n                    'modified': datetime.fromtimestamp(stat.st_mtime)\n                })\n    \n    return analysis\n```\n\n#### Telegram Artifacts\n\n```python\ndef analyze_telegram(telegram_path):\n    \"\"\"Analyze Telegram application data\"\"\"\n    \n    analysis = {\n        'messages': [],\n        'chats': [],\n        'users': [],\n        'media': []\n    }\n    \n    # Telegram uses multiple databases\n    # cache4.db - Main database\n    cache_db = os.path.join(telegram_path, 'cache4.db')\n    \n    if os.path.exists(cache_db):\n        conn = sqlite3.connect(cache_db)\n        cursor = conn.cursor()\n        \n        # Get messages\n        try:\n            cursor.execute(\"\"\"\n                SELECT messages.mid, messages.uid, messages.date,\n                       messages.message, messages.media, messages.out,\n                       users.uid, users.first_name, users.last_name, users.phone\n                FROM messages\n                LEFT JOIN users ON messages.uid = users.uid\n                ORDER BY messages.date DESC\n            \"\"\")\n            \n            for row in cursor.fetchall():\n                analysis['messages'].append({\n                    'id': row[0],\n                    'chat_id': row[1],\n                    'date': datetime.fromtimestamp(row[2]) if row[2] else None,\n                    'text': row[3],\n                    'media': row[4],\n                    'outgoing': bool(row[5]),\n                    'sender_uid': row[6],\n                    'sender_name': f\"{row[7] or ''} {row[8] or ''}\".strip(),\n                    'sender_phone': row[9]\n                })\n        except:\n            pass\n        \n        conn.close()\n    \n    return analysis\n```\n\n#### Signal Artifacts\n\n```python\ndef analyze_signal(signal_path):\n    \"\"\"Analyze Signal application data\"\"\"\n    \n    analysis = {\n        'messages': [],\n        'contacts': [],\n        'groups': []\n    }\n    \n    # Signal database\n    signal_db = os.path.join(signal_path, 'signal.sqlite')\n    \n    if os.path.exists(signal_db):\n        conn = sqlite3.connect(signal_db)\n        cursor = conn.cursor()\n        \n        # Get messages\n        cursor.execute(\"\"\"\n            SELECT m.date, m.body, m.type, m.thread_id,\n                   r.display_name, r.phone\n            FROM mms m\n            LEFT JOIN recipient r ON m.address = r.recipient_id\n            ORDER BY m.date DESC\n        \"\"\")\n        \n        for row in cursor.fetchall():\n            # Signal dates are in milliseconds\n            date = datetime.fromtimestamp(int(row[0]) / 1000) if row[0] else None\n            \n            # Message type: 1=incoming, 2=outgoing, etc.\n            msg_type = 'incoming' if row[2] == 1 else 'outgoing' if row[2] == 2 else 'other'\n            \n            analysis['messages'].append({\n                'date': date,\n                'body': row[1],\n                'type': msg_type,\n                'thread': row[3],\n                'contact_name': row[4],\n                'contact_phone': row[5]\n            })\n        \n        conn.close()\n    \n    return analysis\n```\n\n---\n\n### 13.6 Location Data Forensics\n\nMobile devices store extensive location data from multiple sources.\n\n#### Location Sources\n\n| Source | Accuracy | Persistence |\n|--------|----------|-------------|\n| **GPS** | High (3-5m) | When app requests |\n| **WiFi** | Medium (20-50m) | Historical scans |\n| **Cell Towers** | Low (100m-1km) | Connection logs |\n| **Bluetooth** | High (1-10m) | Device discovery |\n| **IP Geolocation** | Very low | Network connections |\n\n#### Android Location Data\n\n```python\ndef analyze_android_location(location_db):\n    \"\"\"Analyze Android location history\"\"\"\n    \n    locations = []\n    \n    # Android stores location in multiple places\n    \n    # 1. Fused Location Provider\n    fused_db = os.path.join(location_db, 'fused_location.db')\n    if os.path.exists(fused_db):\n        conn = sqlite3.connect(fused_db)\n        cursor = conn.cursor()\n        \n        try:\n            cursor.execute(\"\"\"\n                SELECT timestamp, latitude, longitude, accuracy, provider\n                FROM locations\n                ORDER BY timestamp DESC\n            \"\"\")\n            \n            for row in cursor.fetchall():\n                locations.append({\n                    'timestamp': datetime.fromtimestamp(int(row[0]) / 1000) if row[0] else None,\n                    'latitude': row[1] / 1e7,  # Stored as microdegrees\n                    'longitude': row[2] / 1e7,\n                    'accuracy': row[3],\n                    'provider': row[4],\n                    'source': 'fused'\n                })\n        except:\n            pass\n        \n        conn.close()\n    \n    # 2. Google Location History (if enabled)\n    google_db = os.path.join(location_db, 'google_location_history.db')\n    if os.path.exists(google_db):\n        conn = sqlite3.connect(google_db)\n        cursor = conn.cursor()\n        \n        try:\n            cursor.execute(\"\"\"\n                SELECT timestamp, latitude, longitude, accuracy\n                FROM location_history\n                ORDER BY timestamp DESC\n            \"\"\")\n            \n            for row in cursor.fetchall():\n                locations.append({\n                    'timestamp': datetime.fromtimestamp(int(row[0]) / 1000) if row[0] else None,\n                    'latitude': row[1],\n                    'longitude': row[2],\n                    'accuracy': row[3],\n                    'provider': 'google',\n                    'source': 'google'\n                })\n        except:\n            pass\n        \n        conn.close()\n    \n    return locations\n\ndef analyze_wifi_history(wifi_config):\n    \"\"\"Analyze WiFi connection history\"\"\"\n    \n    # Android stores WiFi info in wpa_supplicant.conf\n    networks = []\n    \n    if os.path.exists(wifi_config):\n        with open(wifi_config, 'r') as f:\n            lines = f.readlines()\n        \n        current_network = {}\n        for line in lines:\n            line = line.strip()\n            \n            if line.startswith('network='):\n                if current_network:\n                    networks.append(current_network)\n                current_network = {}\n            elif '=' in line and current_network is not None:\n                key, value = line.split('=', 1)\n                current_network[key] = value.strip('\"')\n        \n        if current_network:\n            networks.append(current_network)\n    \n    return networks\n```\n\n#### iOS Location Data\n\n```python\ndef analyze_ios_location(backup_path):\n    \"\"\"Analyze iOS location data from backup\"\"\"\n    \n    locations = []\n    \n    # Cache files containing location data\n    location_files = [\n        'consolidated.db',  # Location cache\n        'cache_encryptedA.db',  # Encrypted cache\n        'Routines.mapsdata'  # Significant locations\n    ]\n    \n    for file_hash in location_files:\n        for root, dirs, files in os.walk(backup_path):\n            for file in files:\n                if file == file_hash:\n                    db_path = os.path.join(root, file)\n                    \n                    try:\n                        conn = sqlite3.connect(db_path)\n                        cursor = conn.cursor()\n                        \n                        # Try common location tables\n                        tables = ['WifiLocation', 'CellLocation', 'Location']\n                        \n                        for table in tables:\n                            try:\n                                cursor.execute(f\"SELECT * FROM {table}\")\n                                \n                                # Get column names\n                                cursor.execute(f\"PRAGMA table_info({table})\")\n                                columns = [col[1] for col in cursor.fetchall()]\n                                \n                                for row in cursor.fetchall():\n                                    loc = dict(zip(columns, row))\n                                    \n                                    # Convert timestamps\n                                    if 'timestamp' in loc:\n                                        try:\n                                            loc['timestamp'] = datetime(2001, 1, 1) + timedelta(seconds=float(loc['timestamp']))\n                                        except:\n                                            pass\n                                    \n                                    loc['source'] = table\n                                    locations.append(loc)\n                            except:\n                                continue\n                        \n                        conn.close()\n                    except:\n                        continue\n    \n    return locations\n```\n\n#### Location Timeline Creation\n\n```python\ndef create_location_timeline(android_locs, ios_locs, wifi_networks):\n    \"\"\"Create comprehensive location timeline\"\"\"\n    \n    timeline = []\n    \n    # Add Android locations\n    for loc in android_locs:\n        if loc['timestamp']:\n            timeline.append({\n                'timestamp': loc['timestamp'],\n                'type': 'gps',\n                'latitude': loc['latitude'],\n                'longitude': loc['longitude'],\n                'accuracy': loc.get('accuracy', 'Unknown'),\n                'source': loc.get('source', 'Android')\n            })\n    \n    # Add iOS locations\n    for loc in ios_locs:\n        if 'timestamp' in loc and loc['timestamp']:\n            timeline.append({\n                'timestamp': loc['timestamp'],\n                'type': 'location',\n                'latitude': loc.get('latitude', loc.get('Latitude', 'Unknown')),\n                'longitude': loc.get('longitude', loc.get('Longitude', 'Unknown')),\n                'source': loc.get('source', 'iOS'),\n                'raw': loc\n            })\n    \n    # Add WiFi connections as location approximations\n    for wifi in wifi_networks:\n        # Would need to geolocate BSSID\n        pass\n    \n    # Sort by timestamp\n    timeline.sort(key=lambda x: x['timestamp'])\n    \n    return timeline\n\ndef geolocate_wifi(bssid):\n    \"\"\"Approximate location from WiFi BSSID\"\"\"\n    \n    # In practice, use Wigle.net API or similar\n    # This is a simplified example\n    \n    import requests\n    \n    # Wigle.net API (would need credentials)\n    # api_url = f\"https://api.wigle.net/api/v2/network/detail?netid={bssid}\"\n    \n    # Mock response\n    return {\n        'bssid': bssid,\n        'latitude': 37.7749,  # Example\n        'longitude': -122.4194,\n        'accuracy': 'approximate'\n    }\n```\n\n---\n\n## Chapter 14 \u2013 IoT &amp; Embedded Forensics\n\n---\n\n### 14.1 Introduction to IoT Forensics\n\nInternet of Things (IoT) devices are increasingly common and can provide critical evidence in investigations.\n\n#### IoT Device Categories\n\n| Category | Examples | Forensic Value |\n|----------|----------|----------------|\n| **Smart Home** | Thermostats, lights, locks | Presence, activity |\n| **Wearables** | Smartwatches, fitness trackers | Health, location |\n| **Voice Assistants** | Alexa, Google Home | Conversations, commands |\n| **Cameras** | Security cameras, doorbells | Visual evidence |\n| **Vehicles** | Connected cars | Location, speed, events |\n| **Medical Devices** | Pacemakers, insulin pumps | Health data |\n\n#### IoT Forensic Challenges\n\n```\n1. DIVERSITY: Thousands of devices, no standards\n2. DATA FORMATS: Proprietary storage and protocols\n3. ENCRYPTION: Often encrypted or obfuscated\n4. VOLATILITY: Data may be overwritten quickly\n5. CLOUD DEPENDENCE: Data stored in manufacturer cloud\n6. PHYSICAL ACCESS: May require disassembly\n7. LEGAL: Ownership and privacy issues\n```\n\n---\n\n### 14.2 Firmware Extraction\n\nFirmware analysis is often the first step in IoT forensics.\n\n#### Extraction Methods\n\n| Method | Description | Tools |\n|--------|-------------|-------|\n| **Software** | Read from running device | SSH, ADB, custom exploits |\n| **SPI Flash** | Read flash chip via SPI | Bus Pirate, Flashrom |\n| **JTAG/SWD** | Debug interface access | OpenOCD, J-Link |\n| **Chip-off** | Remove and read chip | Hot air, programmer |\n| **Update Files** | Extract from manufacturer updates | Binwalk, firmware-mod-kit |\n\n#### SPI Flash Reading\n\n```python\nimport serial\nimport time\n\ndef read_spi_flash(port, baudrate=115200, size_mb=16):\n    \"\"\"Read SPI flash via serial connection\"\"\"\n    \n    ser = serial.Serial(port, baudrate, timeout=1)\n    \n    # Send read command (example - varies by device)\n    ser.write(b'read_flash\\r')\n    time.sleep(1)\n    \n    # Read data\n    data = b''\n    bytes_to_read = size_mb * 1024 * 1024\n    \n    while len(data) &lt; bytes_to_read:\n        chunk = ser.read(4096)\n        if not chunk:\n            break\n        data += chunk\n        print(f\"Read {len(data)} / {bytes_to_read} bytes\")\n    \n    ser.close()\n    return data\n\ndef parse_flash_data(data):\n    \"\"\"Parse raw flash dump\"\"\"\n    \n    import binwalk\n    \n    # Run binwalk to identify file systems\n    modules = binwalk.scan(data)\n    \n    results = []\n    for module in modules:\n        for result in module.results:\n            results.append({\n                'offset': result.offset,\n                'description': result.description,\n                'size': getattr(result, 'size', 'Unknown')\n            })\n    \n    return results\n```\n\n#### JTAG Debugging\n\n```python\ndef setup_jtag_connection(interface='jlink', device='cortex-m'):\n    \"\"\"Setup JTAG connection using OpenOCD\"\"\"\n    \n    import subprocess\n    \n    # OpenOCD configuration\n    config = f\"\"\"\n    interface {interface}\n    transport select swd\n    adapter speed 1000\n    source [find target/{device}.cfg]\n    \n    init\n    halt\n    \"\"\"\n    \n    with open('openocd.cfg', 'w') as f:\n        f.write(config)\n    \n    # Start OpenOCD\n    process = subprocess.Popen(\n        ['openocd', '-f', 'openocd.cfg'],\n        stdout=subprocess.PIPE,\n        stderr=subprocess.PIPE\n    )\n    \n    # Connect via telnet\n    import telnetlib\n    tn = telnetlib.Telnet('localhost', 4444)\n    \n    return tn, process\n\ndef read_memory_jtag(tn, address, size):\n    \"\"\"Read memory via JTAG\"\"\"\n    \n    tn.write(f\"mdw {address} {size}\\n\".encode())\n    result = tn.read_until(b'&gt;').decode()\n    \n    return result\n```\n\n#### Firmware Analysis\n\n```python\ndef analyze_firmware(firmware_file):\n    \"\"\"Comprehensive firmware analysis\"\"\"\n    \n    import hashlib\n    import subprocess\n    import tempfile\n    import os\n    \n    analysis = {\n        'hashes': {},\n        'strings': [],\n        'filesystems': [],\n        'binwalk_results': [],\n        'interesting_strings': []\n    }\n    \n    # Calculate hashes\n    with open(firmware_file, 'rb') as f:\n        data = f.read()\n        analysis['hashes']['md5'] = hashlib.md5(data).hexdigest()\n        analysis['hashes']['sha1'] = hashlib.sha1(data).hexdigest()\n        analysis['hashes']['sha256'] = hashlib.sha256(data).hexdigest()\n    \n    # Extract strings\n    result = subprocess.run(\n        ['strings', '-n', '8', firmware_file],\n        capture_output=True,\n        text=True\n    )\n    analysis['strings'] = result.stdout.split('\\n')\n    \n    # Find interesting strings\n    interesting = ['password', 'admin', 'root', 'key', 'token', 'secret',\n                   'http://', 'https://', '192.168.', '10.0.', 'api.',\n                   'firmware', 'update', 'debug', 'vulnerability']\n    \n    for s in analysis['strings']:\n        for i in interesting:\n            if i in s.lower():\n                analysis['interesting_strings'].append(s)\n                break\n    \n    # Run binwalk\n    with tempfile.TemporaryDirectory() as tmpdir:\n        result = subprocess.run(\n            ['binwalk', '-e', '--directory', tmpdir, firmware_file],\n            capture_output=True,\n            text=True\n        )\n        \n        analysis['binwalk_results'] = result.stdout.split('\\n')\n        \n        # List extracted files\n        for root, dirs, files in os.walk(tmpdir):\n            for file in files:\n                file_path = os.path.join(root, file)\n                analysis['filesystems'].append({\n                    'path': file_path,\n                    'size': os.path.getsize(file_path)\n                })\n    \n    return analysis\n```\n\n---\n\n### 14.3 Chip-Off Techniques\n\nChip-off forensics involves physically removing memory chips from devices for analysis.\n\n#### Chip-Off Process\n\n```\n1. IDENTIFICATION: Identify chip type and pinout\n2. REMOVAL: Heat and carefully remove chip\n3. CLEANING: Remove residual solder\n4. PROGRAMMING: Read chip with programmer\n5. ANALYSIS: Parse extracted data\n6. REBALLING: Optional, for reinstallation\n```\n\n#### Equipment Needed\n\n```\n- Hot air rework station (temperature controlled)\n- Soldering iron with fine tips\n- Flux and solder wick\n- Chip programmer (e.g., RT809H, TL866)\n- Adapters for different packages (TSOP, BGA, QFP)\n- Microscope\n- Anti-static workstation\n```\n\n#### Reading Memory Chips\n\n```python\ndef read_nor_flash(programmer, chip_type):\n    \"\"\"Read NOR flash chip\"\"\"\n    \n    # Example using flashrom\n    import subprocess\n    \n    # Identify chip\n    result = subprocess.run(\n        ['flashrom', '-p', programmer, '--identify'],\n        capture_output=True,\n        text=True\n    )\n    \n    # Read chip\n    result = subprocess.run(\n        ['flashrom', '-p', programmer, '-r', 'flash_dump.bin'],\n        capture_output=True,\n        text=True\n    )\n    \n    if result.returncode == 0:\n        with open('flash_dump.bin', 'rb') as f:\n            data = f.read()\n        return data\n    \n    return None\n\ndef parse_emmc(emmc_dump):\n    \"\"\"Parse eMMC chip dump\"\"\"\n    \n    # eMMC contains multiple partitions\n    # Boot1, Boot2, RPMB, User area, GP partitions\n    \n    import struct\n    \n    # Look for partition table\n    # GPT is common\n    gpt_signature = b'EFI PART'\n    \n    partitions = []\n    \n    # Search for GPT headers\n    for offset in range(0, len(emmc_dump) - 512, 512):\n        if emmc_dump[offset:offset+8] == gpt_signature:\n            # Found GPT header\n            partition_entry_lba = struct.unpack(' len(emmc_dump):\n                    break\n                \n                # Check if entry is in use\n                part_type = emmc_dump[entry_offset:entry_offset+16]\n                if any(part_type):\n                    # Extract partition name\n                    name_bytes = emmc_dump[entry_offset+56:entry_offset+72]\n                    name = name_bytes.decode('utf-16le').strip('\\x00')\n                    \n                    partitions.append({\n                        'name': name,\n                        'start': struct.unpack(' 2:\n            # Check time of day\n            hour = curr['timestamp'].hour if hasattr(curr['timestamp'], 'hour') else 0\n            \n            occupancy.append({\n                'time': curr['timestamp'],\n                'event': 'temperature_change',\n                'change': curr['temperature'] - prev['temperature'],\n                'likely_occupied': 7 &lt;= hour &lt;= 22  # Daytime hours\n            })\n    \n    return occupancy\n```\n\n#### Smart Lock Forensics\n\n```python\ndef analyze_smart_lock(lock_data):\n    \"\"\"Analyze smart lock access logs\"\"\"\n    \n    access_logs = []\n    \n    # Parse lock access logs\n    if 'events' in lock_data:\n        for event in lock_data['events']:\n            access_logs.append({\n                'timestamp': event.get('time'),\n                'user': event.get('user'),\n                'method': event.get('method'),  # key, code, app, etc.\n                'action': event.get('action'),  # lock, unlock\n                'status': event.get('status'),\n                'battery': event.get('battery')\n            })\n    \n    # Sort by time\n    access_logs.sort(key=lambda x: x.get('timestamp', ''))\n    \n    return access_logs\n\ndef identify_unauthorized_access(access_logs, authorized_users):\n    \"\"\"Identify potentially unauthorized access\"\"\"\n    \n    suspicious = []\n    \n    for log in access_logs:\n        # Check if user is authorized\n        if log['user'] not in authorized_users:\n            suspicious.append({\n                'reason': 'unauthorized_user',\n                'log': log\n            })\n        \n        # Check for unusual times\n        if log['timestamp']:\n            hour = log['timestamp'].hour if hasattr(log['timestamp'], 'hour') else 0\n            if 0 &lt;= hour &lt;= 5:  # Late night\n                suspicious.append({\n                    'reason': 'unusual_hours',\n                    'log': log\n                })\n        \n        # Check for repeated failures\n        if log['status'] == 'failed' and log['action'] == 'unlock':\n            # Track consecutive failures\n            pass\n    \n    return suspicious\n```\n\n#### Voice Assistant Forensics\n\n```python\ndef analyze_voice_assistant(assistant_data):\n    \"\"\"Analyze voice assistant data\"\"\"\n    \n    analysis = {\n        'commands': [],\n        'queries': [],\n        'devices_controlled': [],\n        'media_played': [],\n        'location_requests': [],\n        'shopping_list': []\n    }\n    \n    if 'history' in assistant_data:\n        for entry in assistant_data['history']:\n            timestamp = entry.get('timestamp')\n            text = entry.get('text', '').lower()\n            action = entry.get('action')\n            \n            # Categorize by content\n            if any(word in text for word in ['play', 'music', 'song', 'podcast']):\n                analysis['media_played'].append({\n                    'time': timestamp,\n                    'command': text\n                })\n            \n            elif any(word in text for word in ['weather', 'where', 'location']):\n                analysis['location_requests'].append({\n                    'time': timestamp,\n                    'query': text\n                })\n            \n            elif any(word in text for word in ['turn on', 'turn off', 'dim', 'brighten']):\n                analysis['devices_controlled'].append({\n                    'time': timestamp,\n                    'command': text\n                })\n            \n            elif any(word in text for word in ['add', 'shopping', 'list']):\n                analysis['shopping_list'].append({\n                    'time': timestamp,\n                    'item': text\n                })\n            \n            else:\n                analysis['queries'].append({\n                    'time': timestamp,\n                    'query': text\n                })\n    \n    return analysis\n```\n\n---\n\n### 14.5 Drone Forensics\n\nDrones contain navigation data, camera footage, and flight logs.\n\n#### Drone Data Sources\n\n| Source | Data | Forensic Value |\n|--------|------|----------------|\n| **Flight Controller** | GPS logs, IMU data | Flight path |\n| **SD Card** | Photos, videos | Visual evidence |\n| **Mobile App** | Flight plans, settings | Operator intent |\n| **Remote Controller** | Telemetry, control inputs | Operation details |\n| **Cloud Services** | Shared flights, media | Extended data |\n\n#### Parsing Drone Flight Logs\n\n```python\nimport csv\nimport json\nfrom math import radians, sin, cos, sqrt, atan2\n\ndef parse_dji_flightlog(log_file):\n    \"\"\"Parse DJI drone flight logs\"\"\"\n    \n    # DJI logs are often in CSV or DAT format\n    flight_data = {\n        'telemetry': [],\n        'events': [],\n        'battery': [],\n        'gps': []\n    }\n    \n    if log_file.endswith('.csv'):\n        with open(log_file, 'r') as f:\n            reader = csv.DictReader(f)\n            for row in reader:\n                entry = {\n                    'timestamp': float(row.get('timestamp', 0)),\n                    'latitude': float(row.get('latitude', 0)),\n                    'longitude': float(row.get('longitude', 0)),\n                    'altitude': float(row.get('altitude', 0)),\n                    'speed': float(row.get('speed', 0)),\n                    'battery': float(row.get('battery', 0)),\n                    'satellites': int(row.get('satellites', 0))\n                }\n                flight_data['telemetry'].append(entry)\n    \n    elif log_file.endswith('.dat'):\n        # Binary format - would need parsing\n        pass\n    \n    return flight_data\n\ndef calculate_flight_path(telemetry):\n    \"\"\"Calculate flight path from telemetry\"\"\"\n    \n    path = []\n    total_distance = 0\n    max_altitude = 0\n    max_speed = 0\n    \n    for i, point in enumerate(telemetry):\n        path.append({\n            'lat': point['latitude'],\n            'lon': point['longitude'],\n            'alt': point['altitude'],\n            'time': point['timestamp']\n        })\n        \n        # Update statistics\n        if point['altitude'] &gt; max_altitude:\n            max_altitude = point['altitude']\n        \n        if point['speed'] &gt; max_speed:\n            max_speed = point['speed']\n        \n        # Calculate distance from previous point\n        if i &gt; 0:\n            prev = telemetry[i-1]\n            distance = haversine_distance(\n                prev['latitude'], prev['longitude'],\n                point['latitude'], point['longitude']\n            )\n            total_distance += distance\n    \n    return {\n        'path': path,\n        'total_distance': total_distance,\n        'max_altitude': max_altitude,\n        'max_speed': max_speed,\n        'duration': telemetry[-1]['timestamp'] - telemetry[0]['timestamp'] if len(telemetry) &gt; 1 else 0\n    }\n\ndef haversine_distance(lat1, lon1, lat2, lon2):\n    \"\"\"Calculate distance between two GPS coordinates\"\"\"\n    \n    R = 6371000  # Earth radius in meters\n    \n    lat1_rad = radians(lat1)\n    lat2_rad = radians(lat2)\n    delta_lat = radians(lat2 - lat1)\n    delta_lon = radians(lon2 - lon1)\n    \n    a = sin(delta_lat/2)**2 + cos(lat1_rad) * cos(lat2_rad) * sin(delta_lon/2)**2\n    c = 2 * atan2(sqrt(a), sqrt(1-a))\n    \n    return R * c\n\ndef analyze_drone_media(media_files):\n    \"\"\"Analyze drone camera media\"\"\"\n    \n    from PIL import Image\n    from PIL.ExifTags import TAGS\n    \n    analysis = []\n    \n    for media_file in media_files:\n        if media_file.endswith(('.jpg', '.jpeg')):\n            try:\n                image = Image.open(media_file)\n                exif = image._getexif()\n                \n                if exif:\n                    exif_data = {}\n                    for tag_id, value in exif.items():\n                        tag = TAGS.get(tag_id, tag_id)\n                        exif_data[tag] = value\n                    \n                    # Extract GPS data if present\n                    if 'GPSInfo' in exif_data:\n                        gps = exif_data['GPSInfo']\n                        \n                        analysis.append({\n                            'file': media_file,\n                            'timestamp': exif_data.get('DateTime'),\n                            'gps': gps,\n                            'make': exif_data.get('Make'),\n                            'model': exif_data.get('Model')\n                        })\n            except:\n                continue\n    \n    return analysis\n```\n\n---\n\n### 14.6 Vehicle Forensics\n\nModern vehicles are complex computers on wheels.\n\n#### Vehicle Data Sources\n\n| System | Data | Access Method |\n|--------|------|---------------|\n| **ECU** | Engine parameters | OBD-II port |\n| **Infotainment** | Phone connections, navigation | USB, removal |\n| **Event Data Recorder** | Crash data | Proprietary tool |\n| **GPS/Navigation** | Destinations, routes | System access |\n| **Telematics** | Remote commands | Cellular network |\n\n#### OBD-II Data Extraction\n\n```python\nimport obd  # python-OBD library\n\ndef read_obd_data(port='COM3'):\n    \"\"\"Read data from OBD-II port\"\"\"\n    \n    connection = obd.OBD(port)\n    \n    data = {}\n    \n    # Read common parameters\n    commands = [\n        obd.commands.SPEED,\n        obd.commands.RPM,\n        obd.commands.COOLANT_TEMP,\n        obd.commands.THROTTLE_POS,\n        obd.commands.ENGINE_LOAD,\n        obd.commands.FUEL_LEVEL,\n        obd.commands.DTC  # Diagnostic Trouble Codes\n    ]\n    \n    for cmd in commands:\n        response = connection.query(cmd)\n        if response.is_null():\n            data[cmd.name] = None\n        else:\n            data[cmd.name] = response.value.magnitude\n    \n    connection.close()\n    return data\n\ndef parse_edr_data(edr_file):\n    \"\"\"Parse Event Data Recorder (Black Box) data\"\"\"\n    \n    # EDR data format is standardized (49 CFR Part 563)\n    # Typically XML or proprietary binary\n    \n    import xml.etree.ElementTree as ET\n    \n    if edr_file.endswith('.xml'):\n        tree = ET.parse(edr_file)\n        root = tree.getroot()\n        \n        crash_data = {}\n        \n        # Parse common EDR elements\n        for elem in root.iter():\n            if 'speed' in elem.tag.lower():\n                crash_data['speed'] = elem.text\n            elif 'brake' in elem.tag.lower():\n                crash_data['brake'] = elem.text\n            elif 'accelerator' in elem.tag.lower():\n                crash_data['throttle'] = elem.text\n            elif 'airbag' in elem.tag.lower():\n                crash_data['airbag_deployed'] = elem.text\n            elif 'seatbelt' in elem.tag.lower():\n                crash_data['seatbelt_status'] = elem.text\n        \n        return crash_data\n    \n    return None\n```\n\n#### Infotainment System Forensics\n\n```python\ndef analyze_infotainment(infotainment_image):\n    \"\"\"Analyze vehicle infotainment system image\"\"\"\n    \n    import sqlite3\n    import os\n    \n    analysis = {\n        'contacts': [],\n        'calls': [],\n        'messages': [],\n        'navigation': [],\n        'media': [],\n        'bluetooth': []\n    }\n    \n    # Mount image (simplified - would use proper mounting)\n    # For analysis, we'll look for common database files\n    \n    for root, dirs, files in os.walk(infotainment_image):\n        for file in files:\n            if file.endswith('.db') or file.endswith('.sqlite'):\n                db_path = os.path.join(root, file)\n                \n                try:\n                    conn = sqlite3.connect(db_path)\n                    cursor = conn.cursor()\n                    \n                    # Try to find contacts\n                    cursor.execute(\"SELECT name FROM sqlite_master WHERE type='table'\")\n                    tables = cursor.fetchall()\n                    \n                    for table in tables:\n                        table_name = table[0]\n                        \n                        # Check for contacts\n                        if any(word in table_name.lower() for word in ['contact', 'phonebook']):\n                            try:\n                                cursor.execute(f\"SELECT * FROM {table_name}\")\n                                rows = cursor.fetchall()\n                                \n                                for row in rows[:100]:  # Limit\n                                    analysis['contacts'].append({\n                                        'table': table_name,\n                                        'data': row\n                                    })\n                            except:\n                                pass\n                        \n                        # Check for navigation\n                        elif any(word in table_name.lower() for word in ['nav', 'destination', 'route']):\n                            try:\n                                cursor.execute(f\"SELECT * FROM {table_name}\")\n                                rows = cursor.fetchall()\n                                \n                                for row in rows:\n                                    analysis['navigation'].append({\n                                        'table': table_name,\n                                        'data': row\n                                    })\n                            except:\n                                pass\n                    \n                    conn.close()\n                except:\n                    continue\n    \n    return analysis\n```\n\n---\n\n# PART VII \u2013 ADVANCED TOPICS\n\n---\n\n## Chapter 15 \u2013 Anti-Forensics &amp; Evasion\n\n---\n\n### 15.1 Introduction to Anti-Forensics\n\nAnti-forensics refers to techniques used to hinder or prevent digital forensic analysis. Understanding these techniques is essential for forensic examiners to detect and counter them.\n\n#### Categories of Anti-Forensics\n\n```\n1. DATA HIDING\n   - Steganography\n   - Alternate data streams\n   - Hidden partitions\n   - Encrypted containers\n\n2. DATA DESTRUCTION\n   - Secure deletion\n   - Disk wiping\n   - Physical destruction\n   - Encryption (denial of access)\n\n3. TRAIL OBSCURATION\n   - Log tampering\n   - Timestomping\n   - IP spoofing\n   - Proxy chains\n\n4. TOOL ATTACKS\n   - Forensic tool exploits\n   - Anti-debugging\n   - VM detection\n   - Sandbox evasion\n```\n\n#### The Anti-Forensics Arms Race\n\n```\nAttacker develops technique\n    \u2193\nForensic community discovers\n    \u2193\nTools updated to detect\n    \u2193\nAttackers evolve technique\n    \u2193\nRepeat...\n```\n\n---\n\n### 15.2 Data Wiping Methods\n\nData wiping (sanitization) is the process of permanently removing data from storage media.\n\n#### Wiping Standards\n\n| Standard | Passes | Description |\n|----------|--------|-------------|\n| **DoD 5220.22-M** | 3 | 1st: zeros, 2nd: ones, 3rd: random |\n| **DoD 5220.22-M (ECE)** | 7 | Extended with verification |\n| **Gutmann** | 35 | 35 passes for magnetic media |\n| **NIST 800-88** | 1 | One pass for most media |\n| **Schneier** | 7 | 7 passes of alternating patterns |\n| **RCMP TSSIT OPS-II** | 3/7 | Canadian government standard |\n\n#### Software Wiping Tools\n\n```python\nimport os\nimport random\nimport struct\n\ndef create_wiping_patterns():\n    \"\"\"Create standard wiping patterns\"\"\"\n    \n    patterns = {\n        'zero': b'\\x00' * 512,\n        'one': b'\\xff' * 512,\n        'random': os.urandom(512),\n        'dod_first': b'\\x00' * 512,\n        'dod_second': b'\\xff' * 512,\n        'dod_third': os.urandom(512),\n        'gutmann': [bytes([i]) * 512 for i in range(256)]  # Simplified\n    }\n    \n    return patterns\n\ndef detect_wiped_space(disk_image, sector_size=512):\n    \"\"\"Detect if space has been wiped\"\"\"\n    \n    import numpy as np\n    from collections import Counter\n    \n    with open(disk_image, 'rb') as f:\n        # Sample sectors\n        f.seek(0, 2)\n        disk_size = f.tell()\n        \n        samples = []\n        for offset in range(0, disk_size, sector_size * 1000):  # Sample every 1000 sectors\n            f.seek(offset)\n            sector = f.read(sector_size)\n            if sector:\n                samples.append(sector)\n    \n    # Analyze patterns\n    patterns_found = []\n    \n    for sector in samples:\n        # Check for all zeros\n        if all(b == 0 for b in sector):\n            patterns_found.append('zero_filled')\n            continue\n        \n        # Check for all ones\n        if all(b == 255 for b in sector):\n            patterns_found.append('one_filled')\n            continue\n        \n        # Check for repeated patterns\n        if len(set(sector)) &lt; 10:\n            patterns_found.append('repeated_pattern')\n            continue\n        \n        # Check entropy\n        entropy = calculate_entropy(sector)\n        if entropy &gt; 7.9:  # Almost random\n            patterns_found.append('random_data')\n    \n    # Count occurrences\n    pattern_counts = Counter(patterns_found)\n    \n    return {\n        'patterns': pattern_counts,\n        'total_samples': len(samples),\n        'likely_wiped': len(patterns_found) &gt; len(samples) * 0.8\n    }\n```\n\n#### Detecting SSD TRIM\n\n```python\ndef detect_trim_effects(image_path, partition_offset):\n    \"\"\"Detect if TRIM has been issued on SSD\"\"\"\n    \n    from pytsk3 import Img_Info, FS_Info\n    \n    img = Img_Info(image_path)\n    fs = FS_Info(img, offset=partition_offset)\n    \n    # Check for patterns indicating TRIM\n    # TRIM typically leaves zeros or patterns in free space\n    \n    # Get unallocated space\n    # This is complex - would need to parse file system\n    \n    trim_indicators = {\n        'zeroed_free_space': False,\n        'uniform_patterns': False,\n        'missing_file_fragments': False\n    }\n    \n    return trim_indicators\n```\n\n---\n\n### 15.3 Encryption Bypass Concepts\n\nUnderstanding encryption is crucial for forensic examiners, even if bypass is not always possible.\n\n#### Types of Encryption\n\n| Type | Examples | Forensic Implications |\n|------|----------|----------------------|\n| **Full Disk** | BitLocker, FileVault, LUKS | Everything encrypted |\n| **File/Folder** | EFS, VeraCrypt | Selective protection |\n| **Container** | TrueCrypt, VeraCrypt | Encrypted volumes |\n| **Cloud** | iCloud, OneDrive | Data at rest encrypted |\n| **End-to-End** | Signal, WhatsApp | Inaccessible to provider |\n\n#### Key Discovery Locations\n\n```python\ndef search_for_encryption_keys(memory_dump):\n    \"\"\"Search for encryption keys in memory\"\"\"\n    \n    import re\n    \n    keys = []\n    \n    with open(memory_dump, 'rb') as f:\n        data = f.read()\n    \n    # Look for common key patterns\n    patterns = [\n        (b'[A-Za-z0-9+/]{32,}={0,2}', 'base64_32'),  # Base64 32-byte key\n        (b'[A-Fa-f0-9]{64}', 'hex_256'),             # Hex 256-bit key\n        (b'[A-Fa-f0-9]{128}', 'hex_512'),            # Hex 512-bit key\n        (b'-----BEGIN RSA PRIVATE KEY-----', 'rsa_private'),\n        (b'-----BEGIN PRIVATE KEY-----', 'private_key'),\n        (b'BitLocker', 'bitlocker_key'),\n        (b'\\\\x00\\\\x00\\\\x00\\\\x00.{32}', 'potential_key')  # Null-padded\n    ]\n    \n    for pattern, key_type in patterns:\n        matches = re.finditer(pattern, data)\n        for match in matches:\n            keys.append({\n                'type': key_type,\n                'offset': match.start(),\n                'value': match.group()[:50].decode('ascii', errors='ignore')  # Truncate\n            })\n    \n    return keys\n\ndef extract_bitlocker_keys(memory_dump):\n    \"\"\"Extract BitLocker keys from memory\"\"\"\n    \n    # BitLocker stores keys in memory when drive is unlocked\n    \n    import volatility3\n    \n    # Use volatility's bitlocker plugin\n    # This is simplified - would use actual volatility\n    \n    keys = []\n    \n    # Look for BitLocker FVEK (Full Volume Encryption Key)\n    # and VMK (Volume Master Key)\n    \n    return keys\n```\n\n#### Cold Boot Attack Concept\n\n```python\ndef simulate_cold_boot_attack(memory_file, decay_rate=0.1):\n    \"\"\"Simulate cold boot attack memory decay\"\"\"\n    \n    import numpy as np\n    \n    with open(memory_file, 'rb') as f:\n        data = np.frombuffer(f.read(), dtype=np.uint8)\n    \n    # Simulate bit decay\n    # Each bit has probability of flipping based on temperature/time\n    \n    # Random mask based on decay rate\n    flip_mask = np.random.random(len(data)) &lt; decay_rate\n    \n    # Flip bits\n    corrupted = data ^ flip_mask.astype(np.uint8)\n    \n    return corrupted.tobytes()\n\ndef reconstruct_decayed_memory(corrupted, original_patterns):\n    \"\"\"Attempt to reconstruct decayed memory\"\"\"\n    \n    # Use error correction techniques\n    # This is highly simplified\n    \n    reconstructed = bytearray()\n    \n    for i, byte in enumerate(corrupted):\n        # Check common patterns\n        if byte in original_patterns:\n            reconstructed.append(byte)\n        else:\n            # Find closest match\n            closest = min(original_patterns, key=lambda x: abs(x - byte))\n            reconstructed.append(closest)\n    \n    return bytes(reconstructed)\n```\n\n---\n\n### 15.4 Steganography Detection\n\nSteganography hides data within other data (images, audio, video, etc.).\n\n#### Types of Steganography\n\n| Method | Description | Detection |\n|--------|-------------|-----------|\n| **LSB** | Modify least significant bits | Statistical analysis |\n| **Spatial** | Modify pixel values | Visual inspection |\n| **Frequency** | Modify transform coefficients | Frequency analysis |\n| **Palette** | Modify color palette | Palette analysis |\n| **File Structure** | Hide in metadata | Structure parsing |\n\n#### LSB Detection\n\n```python\nfrom PIL import Image\nimport numpy as np\n\ndef detect_lsb_steganography(image_path):\n    \"\"\"Detect LSB steganography in images\"\"\"\n    \n    img = Image.open(image_path)\n    \n    # Convert to array\n    img_array = np.array(img)\n    \n    # Extract LSBs\n    lsbs = img_array &amp; 1\n    \n    # Calculate statistics\n    # Natural images have random LSB distribution\n    # Stego images may have patterns or non-random distribution\n    \n    # Count zeros and ones\n    zero_count = np.sum(lsbs == 0)\n    one_count = np.sum(lsbs == 1)\n    total = zero_count + one_count\n    \n    zero_ratio = zero_count / total\n    one_ratio = one_count / total\n    \n    # Chi-square test for randomness\n    expected = total / 2\n    chi_square = ((zero_count - expected)**2 / expected) + \\\n                 ((one_count - one_count)**2 / expected)\n    \n    # Analyze color pairs (Primary Sets)\n    # This detects LSB embedding in color images\n    \n    pairs = []\n    for channel in range(3):  # RGB\n        channel_data = img_array[:, :, channel]\n        # Group pixels into pairs (consecutive pixels)\n        flat = channel_data.flatten()\n        pixel_pairs = flat[::2], flat[1::2]\n        pairs.append(pixel_pairs)\n    \n    # RS Analysis (regular vs singular groups)\n    # This is complex - would implement full RS algorithm\n    \n    results = {\n        'lsb_balance': {\n            'zeros': int(zero_count),\n            'ones': int(one_count),\n            'ratio': zero_ratio / one_ratio if one_ratio &gt; 0 else float('inf')\n        },\n        'chi_square': chi_square,\n        'suspicious': abs(zero_ratio - 0.5) &lt; 0.01,  # Too balanced\n        'embedding_capacity': total / 8,  # Bytes that could be hidden\n    }\n    \n    return results\n\ndef extract_lsb_data(image_path, bytes_to_extract):\n    \"\"\"Extract LSB-encoded data from image\"\"\"\n    \n    img = Image.open(image_path)\n    img_array = np.array(img)\n    \n    # Flatten and extract LSBs\n    flat = img_array.flatten()\n    bits = flat &amp; 1\n    \n    # Convert bits to bytes\n    data = bytearray()\n    for i in range(0, min(len(bits), bytes_to_extract * 8), 8):\n        byte = 0\n        for j in range(8):\n            if i + j &lt; len(bits):\n                byte |= (bits[i + j] &lt;&lt; j)\n        data.append(byte)\n    \n    return bytes(data)\n```\n\n#### Audio Steganography Detection\n\n```python\nimport wave\nimport numpy as np\n\ndef analyze_audio_steganography(audio_path):\n    \"\"\"Detect steganography in WAV files\"\"\"\n    \n    with wave.open(audio_path, 'rb') as wav:\n        # Get audio parameters\n        n_channels = wav.getnchannels()\n        sample_width = wav.getsampwidth()\n        framerate = wav.getframerate()\n        n_frames = wav.getnframes()\n        \n        # Read audio data\n        frames = wav.readframes(n_frames)\n        \n        # Convert to samples based on sample width\n        if sample_width == 1:\n            samples = np.frombuffer(frames, dtype=np.uint8)\n            samples = samples - 128  # Convert to signed\n        elif sample_width == 2:\n            samples = np.frombuffer(frames, dtype=np.int16)\n        else:\n            samples = np.frombuffer(frames, dtype=np.int32)\n        \n        # Analyze LSBs of samples\n        if sample_width &gt; 1:\n            # For multi-byte samples, analyze LSB of each sample\n            lsbs = samples &amp; 1\n            \n            zero_count = np.sum(lsbs == 0)\n            one_count = np.sum(lsbs == 1)\n            total = zero_count + one_count\n            \n            zero_ratio = zero_count / total\n            one_ratio = one_count / total\n            \n            # Check for echo hiding (detect repeated patterns)\n            # Check for phase coding (analyze phase spectrum)\n            \n            return {\n                'lsb_analysis': {\n                    'zeros': int(zero_count),\n                    'ones': int(one_count),\n                    'ratio': zero_ratio / one_ratio if one_ratio &gt; 0 else float('inf')\n                },\n                'suspicious': abs(zero_ratio - 0.5) &lt; 0.01,\n                'duration': n_frames / framerate\n            }\n    \n    return None\n```\n\n---\n\n### 15.5 Log Tampering Detection\n\nAttackers often attempt to modify logs to cover their tracks.\n\n#### Types of Log Tampering\n\n| Technique | Description | Detection Method |\n|-----------|-------------|------------------|\n| **Deletion** | Remove specific entries | Gap analysis |\n| **Modification** | Change log contents | Hash verification |\n| **Injection** | Add false entries | Correlation |\n| **Truncation** | Delete entire logs | Size monitoring |\n| **Rotation bypass** | Prevent new logs | File monitoring |\n\n#### Detecting Log Gaps\n\n```python\ndef detect_log_gaps(log_file, expected_interval=60):\n    \"\"\"Detect gaps in timestamped logs\"\"\"\n    \n    import re\n    from datetime import datetime, timedelta\n    \n    timestamps = []\n    \n    with open(log_file, 'r') as f:\n        for line in f:\n            # Extract timestamp (format varies)\n            # Common formats: \"2023-06-15 14:23:45\" or \"Jun 15 14:23:45\"\n            timestamp_match = re.search(r'\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}', line)\n            if timestamp_match:\n                try:\n                    ts = datetime.strptime(timestamp_match.group(), '%Y-%m-%d %H:%M:%S')\n                    timestamps.append(ts)\n                except:\n                    pass\n    \n    if len(timestamps) &lt; 2:\n        return []\n    \n    # Find gaps\n    gaps = []\n    for i in range(1, len(timestamps)):\n        gap = (timestamps[i] - timestamps[i-1]).total_seconds()\n        if gap &gt; expected_interval * 2:  # More than double expected\n            gaps.append({\n                'start': timestamps[i-1],\n                'end': timestamps[i],\n                'duration': gap\n            })\n    \n    return gaps\n\ndef verify_log_integrity(log_file, hash_file=None):\n    \"\"\"Verify log file integrity using hashes\"\"\"\n    \n    import hashlib\n    \n    # Some systems store rolling hashes of logs\n    if hash_file and os.path.exists(hash_file):\n        with open(hash_file, 'r') as f:\n            stored_hash = f.read().strip()\n        \n        with open(log_file, 'rb') as f:\n            current_hash = hashlib.sha256(f.read()).hexdigest()\n        \n        return {\n            'matches': current_hash == stored_hash,\n            'stored': stored_hash,\n            'current': current_hash\n        }\n    \n    # Alternative: check for log rotation\n    log_dir = os.path.dirname(log_file)\n    log_base = os.path.basename(log_file)\n    \n    rotated = [f for f in os.listdir(log_dir) if f.startswith(log_base) and f != log_base]\n    \n    # Check if rotated logs are consistent\n    # (e.g., no missing numbers in sequence)\n    \n    return None\n```\n\n#### Detecting Timestomping\n\n```python\nimport os\nimport pytsk3\n\ndef detect_timestomping(file_path, mft_record=None):\n    \"\"\"Detect timestamp manipulation\"\"\"\n    \n    # Compare different timestamp sources\n    timestamps = {}\n    \n    # File system timestamps\n    stat = os.stat(file_path)\n    timestamps['fs'] = {\n        'created': datetime.fromtimestamp(stat.st_ctime),\n        'modified': datetime.fromtimestamp(stat.st_mtime),\n        'accessed': datetime.fromtimestamp(stat.st_atime)\n    }\n    \n    # NTFS timestamps from MFT\n    if mft_record:\n        # Parse $STANDARD_INFORMATION and $FILE_NAME attributes\n        # They may differ if timestomping occurred\n        pass\n    \n    # Check for impossible times\n    for source, ts in timestamps.items():\n        # Future dates\n        if any(t &gt; datetime.now() for t in ts.values()):\n            return {\n                'timestomped': True,\n                'reason': 'future_date',\n                'timestamps': ts\n            }\n        \n        # Creation after modification (impossible)\n        if ts['created'] &gt; ts['modified']:\n            return {\n                'timestomped': True,\n                'reason': 'creation_after_modification',\n                'timestamps': ts\n            }\n    \n    # Compare with other artifacts\n    # Check $UsnJrnl, $LogFile, prefetch, etc.\n    \n    return {'timestomped': False}\n\ndef analyze_mft_timestamps(mft_entry):\n    \"\"\"Analyze MFT entry for timestamp inconsistencies\"\"\"\n    \n    # Parse $STANDARD_INFORMATION (attribute 0x10)\n    # Parse $FILE_NAME (attribute 0x30)\n    \n    # Compare timestamps between the two\n    # If they differ significantly, file may have been timestomped\n    \n    standard_info = {}  # Extracted timestamps\n    file_name = {}  # Extracted timestamps\n    \n    differences = {}\n    for attr in ['created', 'modified', 'accessed', 'mft_modified']:\n        if attr in standard_info and attr in file_name:\n            diff = abs((standard_info[attr] - file_name[attr]).total_seconds())\n            if diff &gt; 10:  # More than 10 seconds difference\n                differences[attr] = diff\n    \n    return {\n        'inconsistent': len(differences) &gt; 0,\n        'differences': differences\n    }\n```\n\n---\n\n### 15.6 Anti-Forensics Detection Framework\n\n```python\nclass AntiForensicsDetector:\n    \"\"\"Comprehensive anti-forensics detection framework\"\"\"\n    \n    def __init__(self, evidence_path):\n        self.evidence_path = evidence_path\n        self.findings = []\n    \n    def run_all_checks(self):\n        \"\"\"Run all anti-forensics detection checks\"\"\"\n        \n        # Check for data wiping\n        self.check_data_wiping()\n        \n        # Check for encryption\n        self.check_encryption()\n        \n        # Check for steganography\n        self.check_steganography()\n        \n        # Check for log tampering\n        self.check_log_tampering()\n        \n        # Check for timestomping\n        self.check_timestomping()\n        \n        # Check for hidden data\n        self.check_hidden_data()\n        \n        # Check for forensic tool evasion\n        self.check_tool_evasion()\n        \n        return self.findings\n    \n    def check_data_wiping(self):\n        \"\"\"Check for evidence of data wiping\"\"\"\n        \n        # Look for disk sanitization tools\n        sanitization_tools = [\n            'CCleaner', 'BleachBit', 'Eraser', 'SDelete',\n            'DBAN', 'KillDisk', 'WipeFile', 'Secure Erase'\n        ]\n        \n        # Check prefetch, registry, etc.\n        \n        # Check for wiping patterns in free space\n        wiped = detect_wiped_space(self.evidence_path)\n        \n        if wiped['likely_wiped']:\n            self.findings.append({\n                'type': 'data_wiping',\n                'confidence': 'high',\n                'details': f\"Wiped patterns detected: {wiped['patterns']}\"\n            })\n    \n    def check_encryption(self):\n        \"\"\"Check for encryption artifacts\"\"\"\n        \n        # Look for encryption software\n        encryption_tools = [\n            'BitLocker', 'TrueCrypt', 'VeraCrypt', 'FileVault',\n            'LUKS', 'PGP', 'GnuPG', 'AxCrypt', '7-Zip'\n        ]\n        \n        # Look for encrypted containers\n        # Check file headers for known encrypted formats\n        \n        # Check for high entropy regions\n        # (would scan disk for high-entropy data)\n        \n        self.findings.append({\n            'type': 'encryption_check',\n            'confidence': 'medium',\n            'details': 'Encryption detection requires deeper analysis'\n        })\n    \n    def check_steganography(self):\n        \"\"\"Check for steganography in image files\"\"\"\n        \n        image_files = []\n        for root, dirs, files in os.walk(self.evidence_path):\n            for file in files:\n                if file.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp')):\n                    image_files.append(os.path.join(root, file))\n        \n        for img in image_files[:10]:  # Limit for demo\n            try:\n                result = detect_lsb_steganography(img)\n                if result['suspicious']:\n                    self.findings.append({\n                        'type': 'steganography',\n                        'confidence': 'medium',\n                        'details': f\"Suspicious LSB patterns in {img}\"\n                    })\n            except:\n                continue\n    \n    def check_log_tampering(self):\n        \"\"\"Check for log tampering\"\"\"\n        \n        log_files = []\n        log_dirs = ['Windows\\\\System32\\\\winevt\\\\Logs', 'var\\\\log']\n        \n        for log_dir in log_dirs:\n            full_path = os.path.join(self.evidence_path, log_dir)\n            if os.path.exists(full_path):\n                for file in os.listdir(full_path):\n                    if file.endswith(('.evtx', '.log', '.txt')):\n                        log_files.append(os.path.join(full_path, file))\n        \n        for log in log_files[:5]:  # Limit for demo\n            gaps = detect_log_gaps(log)\n            if gaps:\n                self.findings.append({\n                    'type': 'log_tampering',\n                    'confidence': 'high' if len(gaps) &gt; 1 else 'medium',\n                    'details': f\"Log gaps detected in {log}: {len(gaps)} gaps\"\n                })\n    \n    def check_timestomping(self):\n        \"\"\"Check for timestamp manipulation\"\"\"\n        \n        # Sample files and check for inconsistencies\n        suspicious = []\n        \n        for root, dirs, files in os.walk(self.evidence_path):\n            for file in files[:100]:  # Limit for demo\n                file_path = os.path.join(root, file)\n                try:\n                    result = detect_timestomping(file_path)\n                    if result.get('timestomped'):\n                        suspicious.append({\n                            'file': file_path,\n                            'reason': result['reason']\n                        })\n                except:\n                    continue\n        \n        if suspicious:\n            self.findings.append({\n                'type': 'timestomping',\n                'confidence': 'high' if len(suspicious) &gt; 1 else 'medium',\n                'details': f\"Timestomping detected in {len(suspicious)} files\",\n                'files': suspicious[:5]\n            })\n    \n    def check_hidden_data(self):\n        \"\"\"Check for hidden data (ADS, slack space, etc.)\"\"\"\n        \n        # Check for Alternate Data Streams (NTFS)\n        if os.name == 'nt':\n            import subprocess\n            result = subprocess.run(\n                ['dir', '/r', self.evidence_path],\n                capture_output=True,\n                text=True\n            )\n            \n            if ':$DATA' in result.stdout:\n                self.findings.append({\n                    'type': 'hidden_data',\n                    'confidence': 'high',\n                    'details': 'Alternate Data Streams detected'\n                })\n    \n    def check_tool_evasion(self):\n        \"\"\"Check for forensic tool evasion techniques\"\"\"\n        \n        # Look for anti-debugging/analysis techniques\n        evasion_indicators = [\n            'IsDebuggerPresent',\n            'CheckRemoteDebuggerPresent',\n            'NtQueryInformationProcess',\n            'vmware', 'vbox', 'virtual',\n            'sandbox', 'analysis',\n            'Sleep', 'time check', 'rdtsc'\n        ]\n        \n        # Scan executable files\n        exe_files = []\n        for root, dirs, files in os.walk(self.evidence_path):\n            for file in files:\n                if file.endswith(('.exe', '.dll', '.sys')):\n                    exe_files.append(os.path.join(root, file))\n        \n        for exe in exe_files[:10]:  # Limit for demo\n            with open(exe, 'rb') as f:\n                data = f.read(1024 * 1024)  # First 1MB\n                \n                for indicator in evasion_indicators:\n                    if indicator.encode() in data:\n                        self.findings.append({\n                            'type': 'tool_evasion',\n                            'confidence': 'medium',\n                            'details': f\"Evasion indicator '{indicator}' in {exe}\"\n                        })\n                        break\n```\n\n---\n\n## Chapter 16 \u2013 Cryptocurrency &amp; Dark Web Forensics\n\n---\n\n### 16.1 Introduction to Cryptocurrency Forensics\n\nCryptocurrencies like Bitcoin are increasingly used in cybercrime for ransom payments, money laundering, and illicit transactions.\n\n#### Blockchain Fundamentals\n\n```\nBlockchain = Distributed ledger of all transactions\n    \u2193\nBlocks contain:\n    - Previous block hash\n    - Timestamp\n    - Transaction data\n    - Nonce\n    \u2193\nEach block linked cryptographically\n    \u2193\nImmutable and public\n```\n\n#### Bitcoin Transaction Structure\n\n```\nInputs (sources of funds):\n    - Previous transaction hash\n    - Output index\n    - Signature (scriptSig)\n\nOutputs (destinations):\n    - Value (satoshis)\n    - Recipient address (scriptPubKey)\n```\n\n#### Forensic Opportunities\n\n| Data Source | Information | Forensic Value |\n|-------------|-------------|----------------|\n| **Public Blockchain** | All transactions | Tracing flow of funds |\n| **Wallet Files** | Addresses, keys | Identity attribution |\n| **Exchange Records** | KYC data | User identification |\n| **Node Logs** | IP addresses | Network attribution |\n| **Blockchain Analysis** | Clustering | Address grouping |\n\n---\n\n### 16.2 Bitcoin Transaction Tracing\n\n#### Parsing Blockchain Data\n\n```python\nimport requests\nfrom datetime import datetime\n\nclass BitcoinTracer:\n    \"\"\"Trace Bitcoin transactions\"\"\"\n    \n    def __init__(self, api_url=\"https://blockchain.info\"):\n        self.api_url = api_url\n    \n    def get_address_info(self, address):\n        \"\"\"Get information about a Bitcoin address\"\"\"\n        \n        response = requests.get(\n            f\"{self.api_url}/rawaddr/{address}\"\n        )\n        \n        if response.status_code == 200:\n            data = response.json()\n            \n            return {\n                'address': address,\n                'total_received': data.get('total_received', 0) / 100000000,  # Convert to BTC\n                'total_sent': data.get('total_sent', 0) / 100000000,\n                'balance': data.get('final_balance', 0) / 100000000,\n                'transaction_count': data.get('n_tx', 0),\n                'transactions': data.get('txs', [])\n            }\n        \n        return None\n    \n    def trace_transaction(self, tx_hash, depth=3):\n        \"\"\"Trace a transaction to its sources/sinks\"\"\"\n        \n        response = requests.get(\n            f\"{self.api_url}/rawtx/{tx_hash}\"\n        )\n        \n        if response.status_code != 200:\n            return None\n        \n        tx = response.json()\n        \n        trace = {\n            'hash': tx_hash,\n            'time': datetime.fromtimestamp(tx.get('time', 0)),\n            'inputs': [],\n            'outputs': [],\n            'value': sum(o.get('value', 0) for o in tx.get('out', [])) / 100000000\n        }\n        \n        # Process inputs (sources)\n        for inp in tx.get('inputs', []):\n            if 'prev_out' in inp:\n                input_info = {\n                    'address': inp['prev_out'].get('addr', 'Unknown'),\n                    'value': inp['prev_out'].get('value', 0) / 100000000,\n                    'tx_hash': inp['prev_out'].get('tx_index')\n                }\n                trace['inputs'].append(input_info)\n        \n        # Process outputs (destinations)\n        for out in tx.get('out', []):\n            output_info = {\n                'address': out.get('addr', 'Unknown'),\n                'value': out.get('value', 0) / 100000000,\n                'spent': out.get('spent', False)\n            }\n            trace['outputs'].append(output_info)\n        \n        # Recursively trace if depth &gt; 0\n        if depth &gt; 0:\n            for inp in trace['inputs']:\n                if inp['tx_hash']:\n                    inp['source_trace'] = self.trace_transaction(\n                        inp['tx_hash'], depth - 1\n                    )\n        \n        return trace\n    \n    def cluster_addresses(self, addresses):\n        \"\"\"Group addresses that likely belong to same entity\"\"\"\n        \n        # Common heuristics:\n        # 1. Multiple addresses in same transaction\n        # 2. Change addresses (one input, two outputs)\n        # 3. Peeling chains (systematic small transactions)\n        \n        clusters = {}\n        \n        # This is complex - would use graph analysis\n        # NetworkX can be used for this\n        \n        return clusters\n```\n\n#### Detecting Mixing/Tumbling\n\n```python\ndef detect_mixing_service(transactions):\n    \"\"\"Detect if transactions involve a mixing service\"\"\"\n    \n    mix_indicators = []\n    \n    # Characteristics of mixers:\n    # 1. Many inputs, many outputs\n    # 2. Similar output amounts\n    # 3. Time delays between transactions\n    # 4. Known mixer addresses\n    \n    for tx in transactions:\n        inputs = tx.get('inputs', [])\n        outputs = tx.get('outputs', [])\n        \n        # Many inputs and outputs\n        if len(inputs) &gt; 10 and len(outputs) &gt; 10:\n            mix_indicators.append('many_inputs_outputs')\n        \n        # Check output amounts\n        output_values = [o['value'] for o in outputs]\n        if len(set(output_values)) == 1 and len(output_values) &gt; 5:\n            mix_indicators.append('equal_outputs')\n        \n        # Check for change patterns\n        if len(inputs) == 1 and len(outputs) == 2:\n            # Could be change address\n            change_ratio = min(output_values) / max(output_values)\n            if change_ratio &lt; 0.1:  # Small change\n                # Not necessarily mixing, but note\n                pass\n    \n    return {\n        'is_mixer': len(mix_indicators) &gt;= 2,\n        'indicators': mix_indicators\n    }\n```\n\n---\n\n### 16.3 Wallet Artifact Analysis\n\nCryptocurrency wallets store keys, addresses, and transaction history.\n\n#### Wallet File Locations\n\n| Wallet | Location | File Format |\n|--------|----------|-------------|\n| **Bitcoin Core** | ~/.bitcoin/wallet.dat | Berkeley DB |\n| **Electrum** | ~/.electrum/wallets/ | JSON |\n| **Exodus** | Various | Encrypted |\n| **Blockchain.info** | Browser storage | JavaScript |\n| **Hardware Wallets** | Device storage | Proprietary |\n\n#### Parsing Bitcoin Core Wallet\n\n```python\nimport bsddb3  # Berkeley DB\nimport hashlib\nimport base58\n\ndef parse_bitcoin_wallet(wallet_path):\n    \"\"\"Parse Bitcoin Core wallet.dat file\"\"\"\n    \n    try:\n        db = bsddb3.db.DB()\n        db.open(wallet_path, None, bsddb3.db.DB_HASH, bsddb3.db.DB_RDONLY)\n        \n        wallet_data = {}\n        \n        # Common keys in wallet.dat\n        for key in db.keys():\n            try:\n                key_str = key.decode('utf-8', errors='ignore')\n                value = db.get(key)\n                \n                # Check for address keys\n                if key_str.startswith('name'):\n                    # Address label\n                    addr = key_str[4:]  # Remove 'name' prefix\n                    label = value.decode('utf-8', errors='ignore')\n                    wallet_data[f'label_{addr}'] = label\n                \n                elif key_str.startswith('key'):\n                    # Private key\n                    # This is encrypted - would need wallet password\n                    wallet_data[f'encrypted_key_{len(wallet_data)}'] = value.hex()[:50]\n                \n                elif key_str == 'defaultkey':\n                    wallet_data['default_key'] = value.hex()[:50]\n                \n                elif key_str == 'version':\n                    wallet_data['version'] = int.from_bytes(value, 'little')\n                \n            except:\n                continue\n        \n        db.close()\n        \n        return wallet_data\n        \n    except Exception as e:\n        return {'error': str(e)}\n\ndef extract_bitcoin_addresses(wallet_data):\n    \"\"\"Extract Bitcoin addresses from wallet data\"\"\"\n    \n    addresses = []\n    \n    # In Bitcoin, addresses are derived from public keys\n    # This is simplified - would need to process key material\n    \n    for key, value in wallet_data.items():\n        if key.startswith('label_'):\n            address = key[6:]  # Remove 'label_' prefix\n            addresses.append({\n                'address': address,\n                'label': value,\n                'type': 'address_with_label'\n            })\n    \n    return addresses\n```\n\n#### Analyzing Electrum Wallets\n\n```python\nimport json\nimport hashlib\nfrom Cryptodome.Cipher import AES\n\ndef parse_electrum_wallet(wallet_path):\n    \"\"\"Parse Electrum wallet file\"\"\"\n    \n    with open(wallet_path, 'r') as f:\n        data = json.load(f)\n    \n    wallet_info = {\n        'wallet_type': data.get('wallet_type', 'unknown'),\n        'seed_version': data.get('seed_version'),\n        'use_encryption': data.get('use_encryption', False),\n        'addresses': [],\n        'transactions': []\n    }\n    \n    # Extract addresses\n    if 'addresses' in data:\n        for addr_type, addr_list in data['addresses'].items():\n            for addr in addr_list:\n                wallet_info['addresses'].append({\n                    'address': addr,\n                    'type': addr_type\n                })\n    \n    # Check for encrypted seed\n    if 'seed' in data:\n        if isinstance(data['seed'], str) and data['seed'].startswith('encrypted'):\n            wallet_info['seed_encrypted'] = True\n    \n    # Get transaction history\n    if 'transactions' in data:\n        wallet_info['transactions'] = data['transactions']\n    \n    return wallet_info\n\ndef attempt_wallet_decryption(wallet_data, password):\n    \"\"\"Attempt to decrypt wallet seed\"\"\"\n    \n    if not wallet_data.get('seed_encrypted'):\n        return None\n    \n    # This is simplified - actual decryption is more complex\n    # Electrum uses AES-256-CBC\n    \n    try:\n        # Would need to derive key from password\n        # and decrypt the seed\n        return \"Decryption attempted - would return seed if successful\"\n    except:\n        return None\n```\n\n---\n\n### 16.4 Blockchain Analytics Tools\n\n#### Using Blockchain Explorers\n\n```python\nclass BlockchainAnalyzer:\n    \"\"\"Analyze blockchain data using public APIs\"\"\"\n    \n    def __init__(self):\n        self.apis = {\n            'blockchain.info': 'https://blockchain.info',\n            'blockchair.com': 'https://api.blockchair.com',\n            'chain.so': 'https://chain.so/api/v2'\n        }\n    \n    def get_transaction_graph(self, address, depth=2):\n        \"\"\"Build transaction graph around an address\"\"\"\n        \n        import networkx as nx\n        \n        G = nx.DiGraph()\n        \n        def add_transactions(addr, current_depth):\n            if current_depth &gt; depth:\n                return\n            \n            # Get address info\n            info = self.get_address_info(addr)\n            if not info:\n                return\n            \n            for tx in info.get('transactions', []):\n                tx_hash = tx['hash']\n                \n                # Add inputs\n                for inp in tx.get('inputs', []):\n                    if 'prev_out' in inp:\n                        src = inp['prev_out'].get('addr', 'Unknown')\n                        value = inp['prev_out'].get('value', 0)\n                        G.add_edge(src, addr, \n                                  transaction=tx_hash,\n                                  value=value,\n                                  type='input')\n                        \n                        if current_depth &lt; depth:\n                            add_transactions(src, current_depth + 1)\n                \n                # Add outputs\n                for out in tx.get('out', []):\n                    dst = out.get('addr', 'Unknown')\n                    value = out.get('value', 0)\n                    G.add_edge(addr, dst,\n                              transaction=tx_hash,\n                              value=value,\n                              type='output')\n        \n        add_transactions(address, 0)\n        \n        return G\n    \n    def analyze_transaction_patterns(self, G):\n        \"\"\"Analyze patterns in transaction graph\"\"\"\n        \n        patterns = {\n            'peeling_chains': [],\n            'fork_merge': [],\n            'circular': []\n        }\n        \n        # Detect peeling chains (systematic small transactions)\n        for node in G.nodes():\n            out_edges = list(G.out_edges(node, data=True))\n            if len(out_edges) &gt; 5:\n                # Check if one large output and many small ones\n                values = [e[2].get('value', 0) for e in out_edges]\n                if max(values) &gt; sum(values) * 0.5:\n                    patterns['peeling_chains'].append(node)\n        \n        return patterns\n```\n\n#### Clustering Heuristics\n\n```python\ndef cluster_addresses(transactions):\n    \"\"\"Cluster addresses using common heuristics\"\"\"\n    \n    import networkx as nx\n    \n    G = nx.Graph()\n    \n    # Heuristic 1: Multi-input transactions\n    # All inputs in a transaction likely belong to same entity\n    for tx in transactions:\n        inputs = tx.get('inputs', [])\n        if len(inputs) &gt; 1:\n            addrs = [i.get('address') for i in inputs if i.get('address')]\n            for i in range(len(addrs)):\n                for j in range(i+1, len(addrs)):\n                    G.add_edge(addrs[i], addrs[j], weight=1.0)\n    \n    # Heuristic 2: Change addresses\n    # The smaller output in a one-input, two-output transaction\n    # is likely change belonging to the sender\n    for tx in transactions:\n        inputs = tx.get('inputs', [])\n        outputs = tx.get('outputs', [])\n        \n        if len(inputs) == 1 and len(outputs) == 2:\n            sender = inputs[0].get('address')\n            if sender:\n                # The smaller output is likely change\n                if outputs[0]['value'] &lt; outputs[1]['value']:\n                    change = outputs[0]['address']\n                else:\n                    change = outputs[1]['address']\n                \n                if change:\n                    G.add_edge(sender, change, weight=0.8)\n    \n    # Find connected components (clusters)\n    clusters = list(nx.connected_components(G))\n    \n    return clusters\n```\n\n---\n\n### 16.5 Dark Web Marketplace Investigations\n\n#### Accessing Dark Web Content\n\n```python\nimport stem\nfrom stem.control import Controller\nimport socks\nimport socket\nimport requests\n\nclass DarkWebInvestigator:\n    \"\"\"Investigate dark web content\"\"\"\n    \n    def __init__(self, tor_password=None):\n        self.session = None\n        self.setup_tor(tor_password)\n    \n    def setup_tor(self, password):\n        \"\"\"Setup Tor connection\"\"\"\n        \n        # Configure SOCKS proxy\n        socks.set_default_proxy(socks.SOCKS5, \"127.0.0.1\", 9050)\n        socket.socket = socks.socksocket\n        \n        # Create session\n        self.session = requests.Session()\n        \n        # Optional: Control Tor for circuit management\n        if password:\n            try:\n                controller = Controller.from_port(port=9051)\n                controller.authenticate(password=password)\n                self.controller = controller\n            except:\n                print(\"Tor control connection failed\")\n    \n    def new_circuit(self):\n        \"\"\"Request new Tor circuit\"\"\"\n        \n        if hasattr(self, 'controller'):\n            self.controller.signal(stem.Signal.NEWNYM)\n            return True\n        return False\n    \n    def get_onion_content(self, onion_url):\n        \"\"\"Retrieve content from .onion site\"\"\"\n        \n        try:\n            response = self.session.get(\n                onion_url,\n                timeout=30,\n                headers={'User-Agent': 'Mozilla/5.0'}\n            )\n            \n            if response.status_code == 200:\n                return response.text\n            else:\n                return f\"Error: {response.status_code}\"\n                \n        except Exception as e:\n            return f\"Connection error: {str(e)}\"\n    \n    def search_marketplace(self, marketplace_url, product):\n        \"\"\"Search for products on marketplace\"\"\"\n        \n        # This would need to parse marketplace-specific HTML\n        # Each marketplace has different structure\n        \n        content = self.get_onion_content(marketplace_url)\n        \n        # Parse for product listings\n        # Would use BeautifulSoup or similar\n        \n        return content\n```\n\n#### Capturing Marketplace Evidence\n\n```python\nimport hashlib\nfrom datetime import datetime\nimport json\n\ndef capture_marketplace_evidence(investigator, urls):\n    \"\"\"Capture forensic evidence from dark web marketplaces\"\"\"\n    \n    evidence = {\n        'timestamp': datetime.now().isoformat(),\n        'urls_accessed': [],\n        'content_hashes': [],\n        'screenshots': [],\n        'transaction_records': []\n    }\n    \n    for url in urls:\n        print(f\"Accessing {url}\")\n        \n        # Get content\n        content = investigator.get_onion_content(url)\n        \n        # Calculate hash\n        content_hash = hashlib.sha256(content.encode()).hexdigest()\n        \n        evidence['urls_accessed'].append({\n            'url': url,\n            'timestamp': datetime.now().isoformat(),\n            'content_hash': content_hash\n        })\n        \n        evidence['content_hashes'].append(content_hash)\n        \n        # Save content\n        with open(f\"evidence_{hashlib.md5(url.encode()).hexdigest()}.html\", 'w') as f:\n            f.write(content)\n        \n        # Take screenshot (would need headless browser)\n        # ...\n        \n        # Look for Bitcoin addresses\n        import re\n        btc_pattern = r'[13][a-km-zA-HJ-NP-Z0-9]{26,33}'\n        btc_addresses = re.findall(btc_pattern, content)\n        \n        if btc_addresses:\n            evidence['transaction_records'].extend([\n                {\n                    'source': url,\n                    'address': addr,\n                    'found': datetime.now().isoformat()\n                }\n                for addr in set(btc_addresses)\n            ])\n        \n        # Rotate circuit occasionally\n        if len(evidence['urls_accessed']) % 3 == 0:\n            investigator.new_circuit()\n            print(\"New Tor circuit established\")\n    \n    # Save evidence manifest\n    with open('dark_web_evidence.json', 'w') as f:\n        json.dump(evidence, f, indent=2)\n    \n    return evidence\n```\n\n---\n\n### 16.6 OSINT Correlation\n\nCombining cryptocurrency data with open-source intelligence.\n\n#### Correlating Cryptocurrency with OSINT\n\n```python\nimport requests\nfrom datetime import datetime, timedelta\n\nclass OSINTCorrelator:\n    \"\"\"Correlate cryptocurrency data with OSINT\"\"\"\n    \n    def __init__(self):\n        self.osint_sources = {\n            'twitter': self.search_twitter,\n            'reddit': self.search_reddit,\n            'pastebin': self.search_pastebin,\n            'blockchain_forums': self.search_forums\n        }\n    \n    def search_twitter(self, query, days_back=30):\n        \"\"\"Search Twitter for cryptocurrency mentions\"\"\"\n        \n        # Would use Twitter API\n        # This is simplified\n        \n        return [\n            {\n                'platform': 'twitter',\n                'query': query,\n                'results': 'API would return tweets'\n            }\n        ]\n    \n    def search_reddit(self, address):\n        \"\"\"Search Reddit for address mentions\"\"\"\n        \n        # Reddit search API\n        url = f\"https://www.reddit.com/search.json?q={address}&amp;restrict_sr=off\"\n        \n        try:\n            response = requests.get(url, headers={'User-Agent': 'Forensic Tool'})\n            if response.status_code == 200:\n                data = response.json()\n                \n                results = []\n                for post in data.get('data', {}).get('children', []):\n                    post_data = post['data']\n                    results.append({\n                        'title': post_data.get('title'),\n                        'url': post_data.get('url'),\n                        'subreddit': post_data.get('subreddit'),\n                        'created': datetime.fromtimestamp(post_data.get('created_utc')),\n                        'score': post_data.get('score')\n                    })\n                \n                return results\n        except:\n            pass\n        \n        return []\n    \n    def search_pastebin(self, address):\n        \"\"\"Search Pastebin for address mentions\"\"\"\n        \n        # Pastebin scraping is more complex\n        # Would need to use their API or scrape recent pastes\n        \n        return []\n    \n    def search_forums(self, address):\n        \"\"\"Search cryptocurrency forums\"\"\"\n        \n        forums = [\n            'https://bitcointalk.org',\n            'https://forum.bitcoin.com',\n            'https://www.reddit.com/r/Bitcoin'\n        ]\n        \n        results = []\n        # Would need forum-specific scraping\n        \n        return results\n    \n    def correlate_address(self, bitcoin_address, timeframe_days=90):\n        \"\"\"Correlate Bitcoin address with OSINT\"\"\"\n        \n        correlation = {\n            'address': bitcoin_address,\n            'timeframe': f\"last_{timeframe_days}_days\",\n            'mentions': [],\n            'associated_identities': [],\n            'risk_score': 0\n        }\n        \n        # Search across all sources\n        for source_name, search_func in self.osint_sources.items():\n            try:\n                results = search_func(bitcoin_address)\n                if results:\n                    correlation['mentions'].extend(results)\n                    \n                    # Extract potential identities\n                    for result in results:\n                        # Look for usernames, emails, etc.\n                        pass\n            except Exception as e:\n                print(f\"Error searching {source_name}: {e}\")\n        \n        # Calculate risk score based on:\n        # - Number of mentions\n        # - Association with illegal markets\n        # - Forum reputation\n        # - Transaction patterns\n        \n        correlation['risk_score'] = len(correlation['mentions']) * 10\n        \n        return correlation\n```\n\n#### Building a Suspect Profile\n\n```python\ndef build_suspect_profile(bitcoin_address, transaction_trace, osint_data):\n    \"\"\"Build comprehensive suspect profile\"\"\"\n    \n    profile = {\n        'primary_address': bitcoin_address,\n        'transaction_analysis': {},\n        'osint_findings': [],\n        'timeline': [],\n        'confidence_score': 0,\n        'identified_identities': []\n    }\n    \n    # Analyze transaction patterns\n    if transaction_trace:\n        # Total volume\n        total_received = sum(\n            inp.get('value', 0) for inp in transaction_trace.get('inputs', [])\n        )\n        total_sent = sum(\n            out.get('value', 0) for out in transaction_trace.get('outputs', [])\n        )\n        \n        profile['transaction_analysis'] = {\n            'total_received_btc': total_received,\n            'total_sent_btc': total_sent,\n            'transaction_count': len(transaction_trace.get('transactions', [])),\n            'first_seen': min(\n                (t.get('time') for t in transaction_trace.get('transactions', [])),\n                default=None\n            ),\n            'last_seen': max(\n                (t.get('time') for t in transaction_trace.get('transactions', [])),\n                default=None\n            )\n        }\n    \n    # Process OSINT data\n    for mention in osint_data.get('mentions', []):\n        profile['osint_findings'].append({\n            'source': mention.get('platform', 'unknown'),\n            'content': mention.get('title', '')[:100],\n            'date': mention.get('created'),\n            'url': mention.get('url')\n        })\n        \n        # Extract usernames\n        if mention.get('platform') == 'twitter':\n            # Extract @username from text\n            pass\n        elif mention.get('platform') == 'reddit':\n            profile['identified_identities'].append({\n                'type': 'reddit_user',\n                'value': mention.get('subreddit'),\n                'confidence': 'medium'\n            })\n    \n    # Create timeline\n    all_events = []\n    \n    # Add transaction events\n    for tx in transaction_trace.get('transactions', []):\n        all_events.append({\n            'time': tx.get('time'),\n            'type': 'transaction',\n            'details': f\"Transaction {tx.get('hash')[:10]}...\",\n            'value': tx.get('value', 0)\n        })\n    \n    # Add OSINT events\n    for mention in profile['osint_findings']:\n        if mention.get('date'):\n            all_events.append({\n                'time': mention['date'],\n                'type': 'osint_mention',\n                'details': f\"Mentioned on {mention['source']}\",\n                'source': mention['source']\n            })\n    \n    # Sort timeline\n    all_events.sort(key=lambda x: x.get('time', datetime.min))\n    profile['timeline'] = all_events\n    \n    # Calculate confidence score\n    profile['confidence_score'] = min(\n        len(profile['identified_identities']) * 25 +\n        len(profile['osint_findings']) * 5 +\n        (profile['transaction_analysis'].get('transaction_count', 0) &gt; 0) * 10,\n        100\n    )\n    \n    return profile\n```\n\n---\n\n### 16.7 Cryptocurrency Tumbling Detection\n\n```python\ndef analyze_tumbling_patterns(transactions):\n    \"\"\"Analyze transactions for tumbling/mixing patterns\"\"\"\n    \n    tumbling_indicators = {\n        'peeling_chain': False,\n        'fork_merge': False,\n        'circular_flow': False,\n        'structured_delays': False\n    }\n    \n    # 1. Detect peeling chains\n    # One input, multiple outputs where amounts gradually decrease\n    \n    # 2. Detect fork-merge patterns\n    # Funds split then recombine later\n    \n    # 3. Detect circular flows\n    # Funds eventually return to original address\n    \n    # 4. Detect structured delays\n    # Transactions at regular intervals\n    \n    # Build transaction graph\n    import networkx as nx\n    G = nx.DiGraph()\n    \n    for tx in transactions:\n        tx_hash = tx.get('hash')\n        inputs = tx.get('inputs', [])\n        outputs = tx.get('outputs', [])\n        \n        for inp in inputs:\n            src = inp.get('address')\n            for out in outputs:\n                dst = out.get('address')\n                if src and dst:\n                    G.add_edge(src, dst, \n                              transaction=tx_hash,\n                              value=out.get('value', 0))\n    \n    # Look for cycles (circular flow)\n    try:\n        cycles = list(nx.simple_cycles(G))\n        if cycles:\n            tumbling_indicators['circular_flow'] = True\n    except:\n        pass\n    \n    # Look for nodes with high in/out degree (mixers)\n    for node in G.nodes():\n        in_degree = G.in_degree(node)\n        out_degree = G.out_degree(node)\n        \n        if in_degree &gt; 10 and out_degree &gt; 10:\n            tumbling_indicators['fork_merge'] = True\n    \n    # Score the likelihood of tumbling\n    indicator_count = sum(1 for v in tumbling_indicators.values() if v)\n    \n    return {\n        'indicators': tumbling_indicators,\n        'tumbling_score': indicator_count * 25,  # 0-100\n        'likely_tumbled': indicator_count &gt;= 2\n    }\n```\n\n---\n\n# PART VIII \u2013 LEGAL, REPORTING &amp; CAREER\n\n---\n\n## Chapter 17 \u2013 Writing Professional Forensic Reports\n\n---\n\n### 17.1 The Importance of Forensic Reporting\n\nA forensic report is the final product of your investigation and often the only thing the court, client, or stakeholders will see. A technically perfect investigation can be undermined by a poorly written report.\n\n#### Why Reports Matter\n\n```\nTechnical Investigation (100% effort)\n    \u2193\nReport Writing (50% effort)\n    \u2193\nReader Comprehension (25% retention)\n    \u2193\nLegal Proceedings (100% scrutiny)\n```\n\n**Key Principles:**\n- **Clarity:** Avoid jargon when possible, define when necessary\n- **Accuracy:** Every statement must be defensible\n- **Completeness:** Include all relevant findings, even negative ones\n- **Objectivity:** Present facts, not opinions (unless qualified as expert opinion)\n- **Reproducibility:** Another examiner should reach same conclusions\n\n---\n\n### 17.2 Report Structure\n\nA professional forensic report follows a standardized structure that guides the reader through your investigation.\n\n#### Standard Report Template\n\n```markdown\nFORENSIC EXAMINATION REPORT\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nCASE INFORMATION\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nCase Number: CF-2023-0042\nExaminer: Senior Forensic Analyst John Smith\nDate of Report: 2023-12-15\nRequesting Party: Legal Department, Acme Corporation\nClassification: Confidential\n\n1. EXECUTIVE SUMMARY\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nBrief overview (1-2 paragraphs) of:\n- What was examined\n- Key findings\n- Overall conclusions\n\n2. CASE BACKGROUND\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Incident description\n- Investigation scope\n- Legal authority (warrant, consent, etc.)\n- Chain of custody summary\n\n3. EVIDENCE LIST\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nItemized list of all evidence examined:\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Item ID \u2502 Description     \u2502 Source       \u2502 Hash Value  \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 EX-001  \u2502 Dell Laptop     \u2502 John Doe     \u2502 SHA256:...  \u2502\n\u2502 EX-002  \u2502 iPhone 12       \u2502 John Doe     \u2502 SHA256:...  \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n4. EXAMINATION METHODOLOGY\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Tools used (name, version, hash)\n- Procedures followed\n- Acquisition methods\n- Analysis techniques\n\n5. TECHNICAL FINDINGS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nDetailed findings organized by evidence item and finding type.\n\n   5.1 File System Analysis\n   5.2 User Activity Artifacts\n   5.3 Network Activity\n   5.4 Deleted Data Recovery\n   5.5 Timeline of Events\n\n6. ANALYSIS &amp; INTERPRETATION\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Correlation of findings\n- Significance of evidence\n- Alternative explanations considered\n- Expert opinions\n\n7. CONCLUSIONS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Summary of findings\n- Answers to specific questions\n- Recommendations\n\n8. LIMITATIONS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Constraints encountered\n- Unanswered questions\n- Additional analysis needed\n\n9. APPENDICES\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nA. Chain of Custody Documentation\nB. Tool Verification Hashes\nC. Raw Data Extracts\nD. Glossary of Terms\nE. Examiner Qualifications\n```\n\n---\n\n### 17.3 Writing the Executive Summary\n\nThe executive summary is often the only section read by busy executives, lawyers, and judges.\n\n#### Executive Summary Examples\n\n**Poor Example:**\n```\n\"We analyzed the suspect's computer and found incriminating evidence including \ndeleted files and browser history showing they visited illegal websites.\"\n```\n\n**Good Example:**\n```\n\"On December 10, 2023, at the request of the Legal Department, this examiner \nconducted a forensic analysis of a Dell Latitude laptop (EX-001) belonging to \nJohn Doe.\n\nThe examination revealed that between November 1-15, 2023, the user downloaded \n47 files containing proprietary company information from the internal server \nto an external USB drive (connected on November 15 at 2:30 PM). These files \nincluded customer lists, pricing strategies, and product specifications.\n\nAdditionally, 23 of these files were emailed to a personal Gmail account \n(johndoe.personal@gmail.com) on November 16, approximately 4 hours before \nthe user's resignation was submitted.\n\nNo evidence of external compromise or unauthorized access was found, \nindicating these actions were performed by the authorized user.\n\nDetailed findings and supporting evidence are provided in Section 5.\"\n```\n\n#### Key Elements of Executive Summary\n\n```\nWHO:    John Doe (employee)\nWHAT:   Downloaded 47 proprietary files\nWHEN:   November 1-15, 2023\nWHERE:  From company server to personal USB\nWHY:    Appears related to resignation (submitted Nov 16)\nHOW:    Direct access using valid credentials\n```\n\n---\n\n### 17.4 Technical Findings Documentation\n\nTechnical findings must be detailed enough for peer review but organized for readability.\n\n#### File System Findings Template\n\n```markdown\n5.1 File System Analysis - EX-001 (Dell Laptop)\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n5.1.1 File System Overview\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- File System: NTFS\n- Volume Size: 476 GB\n- Allocation Unit Size: 4096 bytes\n- Total Files Examined: 127,453\n- Deleted Files Recovered: 3,847\n\n5.1.2 Key Files Identified\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Filename     \u2502 Full Path          \u2502 Created       \u2502 Modified     \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 customers.xlsx\u2502 C:\\Users\\John\\Docs \u2502 2023-11-10    \u2502 2023-11-15   \u2502\n\u2502              \u2502                     \u2502 09:15:22      \u2502 14:30:45     \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 pricing.pdf  \u2502 C:\\Users\\John\\Docs \u2502 2023-11-12    \u2502 2023-11-15   \u2502\n\u2502              \u2502                     \u2502 11:20:33      \u2502 14:32:18     \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n5.1.3 File Content Analysis\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nFile: customers.xlsx (EX-001/Extracts/001)\nSHA256: 1a2b3c4d5e6f7g8h9i0j...\n\nThe file contains 15,247 customer records including:\n- Names, addresses, phone numbers\n- Purchase history and preferences\n- Payment methods (credit card last 4 digits)\n- Contract expiration dates\n\nNotable: This file was last accessed 4 hours before resignation.\n\n[SCREENSHOT: File content showing key columns]\n\n5.1.4 Deleted File Recovery\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nThe following deleted files were recovered from unallocated space:\n\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Filename     \u2502 Original Path       \u2502 Deleted       \u2502 Recovery     \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 secret.docx  \u2502 C:\\Users\\John\\Docs  \u2502 2023-11-15    \u2502 92%          \u2502\n\u2502              \u2502                     \u2502 14:35:22      \u2502 recovered    \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\nContent of secret.docx (excerpt):\n\"This document discusses the upcoming merger with XYZ Corp, \nscheduled to close December 2023...\"\n```\n\n#### Timeline Presentation\n\n```markdown\n5.5 Timeline of Events\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nKey events reconstructed from multiple artifacts:\n\n2023-11-01\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n09:00    \u2500 Employee logs into system (Event Log 4624)\n09:15    \u2500 Accesses customers.xlsx (USN Journal)\n09:30-16:30 \u2500 Normal work activity\n\n2023-11-10\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n11:20    \u2500 Creates pricing.pdf (MFT record created)\n11:22    \u2500 Modifies document (File metadata)\n\n2023-11-15\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n14:30    \u2500 Last access of customers.xlsx (Prefetch)\n14:32    \u2500 Last access of pricing.pdf (Prefetch)\n14:35    \u2500 secret.docx deleted (Recycle Bin)\n14:40    \u2500 USB drive \"SanDisk Ultra\" connected (USBSTOR)\n14:41-14:55 \u2500 Mass file copy to USB (USN Journal)\n15:00    \u2500 Employee leaves early\n\n2023-11-16\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n09:00    \u2500 Employee logs in\n09:15    \u2500 Email to johndoe.personal@gmail.com\n          Attachments: customers.xlsx, pricing.pdf (Email logs)\n09:30    \u2500 Email to HR: resignation letter\n10:00    \u2500 System shutdown (Event Log 6006)\n\nTimeline Visualization:\nNov 01 [===== Normal Work =====]\nNov 10 [== Document Creation ==]\nNov 15 [== Copy to USB ==][== Delete ==]\nNov 16 [== Email ==][== Resign ==]\n```\n\n---\n\n### 17.5 Including Visual Evidence\n\nVisual aids significantly improve comprehension.\n\n#### Screenshot Documentation\n\n```markdown\n5.2.3 Suspicious Email Evidence\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nFigure 1: Email sent to personal account on 2023-11-16\n\n[SCREENSHOT: Email client showing:\nFrom: john.doe@company.com\nTo: johndoe.personal@gmail.com\nSubject: Files\nDate: Nov 16, 2023 09:15:22\nAttachments: customers.xlsx (2.4 MB), pricing.pdf (1.8 MB)\n\nDear self,\nHere are the files we discussed.\n- John]\n\nExaminer Note: The email was recovered from the Sent Items folder\nand verified by matching attachment hashes to the original files.\n```\n\n#### Data Visualization\n\n```markdown\n5.5.2 Data Exfiltration Volume\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nFigure 2: Data transfer to USB drive over time\n\n[CHART: Line graph showing]\nBytes Transferred\n    ^\n5MB |        *\n4MB |      *   *\n3MB |    *       *\n2MB |  *           *\n1MB |*               *\n    +-------------------\u2192 Time\n    14:40 14:45 14:50 14:55\n\nThis pattern shows continuous file transfer rather than\nintermittent access, consistent with bulk copying.\n```\n\n#### File Structure Diagrams\n\n```markdown\n5.1.5 MFT Entry Analysis\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nFigure 3: MFT Entry for secret.docx (before deletion)\n\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 MFT HEADER                          \u2502\n\u2502 Record: 12345   In Use: Yes         \u2502\n\u2502 Sequence: 3     Links: 1             \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 $STANDARD_INFORMATION                \u2502\n\u2502 Created: 2023-11-10 11:20:33        \u2502\n\u2502 Modified: 2023-11-15 14:30:45       \u2502\n\u2502 Accessed: 2023-11-15 14:30:45       \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 $FILE_NAME                           \u2502\n\u2502 Name: secret.docx                    \u2502\n\u2502 Parent: 12340 (Documents)            \u2502\n\u2502 Created: 2023-11-10 11:20:33        \u2502\n\u2502 Modified: 2023-11-15 14:30:45       \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 $DATA (Non-resident)                 \u2502\n\u2502 Data Runs: [0x31 02 3A 01 34 12...] \u2502\n\u2502 Size: 245,760 bytes                  \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n---\n\n### 17.6 Tool Documentation\n\nProper tool documentation ensures reproducibility and admissibility.\n\n#### Tool Verification Table\n\n```markdown\n4.2 Forensic Tools Used\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nAll tools were verified using published hashes from official sources.\n\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Tool            \u2502 Version    \u2502 SHA256 Hash      \u2502 Verification  \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 FTK Imager      \u2502 4.7.1      \u2502 1a2b3c4d5e...    \u2502 Matched       \u2502\n\u2502 Autopsy         \u2502 4.20.0     \u2502 2b3c4d5e6f...    \u2502 Matched       \u2502\n\u2502 Volatility      \u2502 2.6.1      \u2502 3c4d5e6f7g...    \u2502 Matched       \u2502\n\u2502 Plaso           \u2502 20230715   \u2502 4d5e6f7g8h...    \u2502 Matched       \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\nTool Configuration:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nFTK Imager: Default settings, evidence file format E01,\n           compression level 6, verification enabled\n\nAutopsy: Ingest modules enabled:\n        - File Ingestion (default)\n        - Hash Lookup (NSRL)\n        - Keyword Search (custom list attached)\n        - Email Parser\n        - Extension Mismatch Detector\n```\n\n#### Command Documentation\n\n```markdown\n4.3 Key Commands Executed\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nMemory Acquisition:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nCommand: DumpIt.exe /quiet /output memory.raw\nOutput: memory.raw (16,384 MB)\nHash: SHA256: 5e6f7g8h9i0j...\n\nVerification:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nCommand: sha256sum memory.raw\nResult: 5e6f7g8h9i0j... (matches acquisition)\n\nMFT Extraction:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nCommand: fls -o 2048 -r evidence.E01 &gt; mft_listing.txt\nOutput: 127,453 files listed\nDate: 2023-12-10 14:30:00\n\nTimeline Creation:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nCommand: log2timeline.py --storage-file case.plaso evidence.E01\nCommand: psort.py -o l2tcsv -w timeline.csv case.plaso\nOutput: timeline.csv (234,567 events)\n```\n\n---\n\n### 17.7 Addressing Limitations and Alternative Explanations\n\nA credible report acknowledges limitations and considers alternatives.\n\n#### Limitations Section\n\n```markdown\n8. LIMITATIONS\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n8.1 Technical Limitations\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- The subject laptop (EX-001) was powered off at seizure, so volatile\n  memory (RAM) could not be acquired.\n- The USB drive referenced in findings was not recovered, so direct\n  examination of copied files was not possible.\n- Encrypted files (3 found) could not be examined without passwords.\n- System time was 3 minutes 22 seconds ahead of UTC; all timestamps\n  in this report have been adjusted accordingly.\n\n8.2 Scope Limitations\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Examination was limited to the laptop; cloud storage and personal\n  devices were not included in scope.\n- Network logs were available only for the previous 30 days.\n- Email attachments larger than 10MB were not preserved by the mail\n  server.\n\n8.3 Unanswered Questions\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- The recipient of the emailed files has not been identified.\n- It's unknown if additional files were deleted before imaging.\n- The ultimate destination of files copied to USB is unknown.\n\n8.4 Potential Alternative Explanations\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nThe following alternative explanations were considered and rejected:\n\nAlternative 1: System compromise\n- Considered: Could an attacker have performed these actions?\n- Rejected because: No evidence of remote access; actions align with\n  user's normal working hours; files were accessed with valid credentials;\n  no malware or unusual network connections detected.\n\nAlternative 2: Authorized business purpose\n- Considered: Could this be normal work activity?\n- Rejected because: Personal email recipient, timing with resignation,\n  deletion of files, and nature of files (customer data) inconsistent\n  with normal business practices.\n\nAlternative 3: Coerced actions\n- Considered: Could the user have been forced to perform these actions?\n- Rejected because: No evidence of coercion; actions were spread over\n  multiple days; user accessed files during normal work hours without\n  unusual behavior.\n```\n\n---\n\n### 17.8 Expert Witness Preparation\n\nYour report may lead to testimony in court or depositions.\n\n#### Preparing for Testimony\n\n```markdown\nEXPERT WITNESS PREPARATION CHECKLIST\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nBefore Testimony:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\u2610 Review entire case file (not just your report)\n\u2610 Refresh memory on technical details\n\u2610 Verify all dates, times, and findings\n\u2610 Prepare visual aids for complex concepts\n\u2610 Anticipate defense questions\n\u2610 Understand opposing expert's report (if any)\n\u2610 Confirm schedule and logistics\n\nCommon Defense Questions:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n1. \"Could the timestamps have been modified?\"\n   - Answer: Explain MFT vs file system timestamps\n   - Be honest about possibilities\n   - Reference corroborating evidence\n\n2. \"Could someone else have used the computer?\"\n   - Review login evidence\n   - Check for remote access\n   - Consider physical access\n\n3. \"Did you examine everything?\"\n   - Explain scope limitations\n   - Justify examination priorities\n   - Note what wasn't examined and why\n\n4. \"Are you being paid for your testimony?\"\n   - Yes (transparently)\n   - Explain fee structure (hourly, not outcome-based)\n\n5. \"Isn't it possible that [alternative explanation]?\"\n   - Address each alternative\n   - Explain why evidence supports your conclusion\n   - Acknowledge possibilities while showing probabilities\n\nDuring Testimony:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Speak clearly and slowly\n- Answer only what is asked\n- If you don't know, say so\n- Use plain language, define technical terms\n- Refer to notes when needed\n- Stay calm and professional\n```\n\n#### Expert Qualification Section\n\n```markdown\nEXAMINER QUALIFICATIONS\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nName: John Smith\nTitle: Senior Forensic Analyst\nCompany: Cyber Forensics Inc.\nExperience: 12 years\n\nEducation:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Master of Science in Digital Forensics, University X, 2014\n- Bachelor of Science in Computer Science, University Y, 2011\n\nCertifications:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- GIAC Certified Forensic Examiner (GCFE) - 2015\n- GIAC Certified Forensic Analyst (GCFA) - 2017\n- GIAC Reverse Engineering Malware (GREM) - 2019\n- Certified Computer Examiner (CCE) - 2016\n- EnCase Certified Examiner (EnCE) - 2015\n\nProfessional Experience:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n2020-Present: Senior Forensic Analyst, Cyber Forensics Inc.\n  - Lead examiner on 150+ cases\n  - Specializing in intellectual property theft and insider threats\n  - Testified as expert witness in 25 federal and state cases\n\n2015-2020: Digital Forensic Examiner, State Police\n  - Processed 500+ digital evidence items\n  - Trained 50+ officers in digital evidence handling\n  - Developed standard operating procedures\n\n2011-2015: IT Security Analyst, Private Sector\n  - Network security monitoring\n  - Incident response\n  - System administration\n\nPublications and Presentations:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- \"Advanced NTFS Forensics,\" DFIR Conference 2022\n- \"Timeline Analysis Techniques,\" Journal of Digital Forensics, 2021\n- \"Insider Threat Detection,\" Security Summit 2020\n\nPrevious Testimony:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- State v. Anderson (2023) - Qualified as expert, testified on file system analysis\n- Company v. Former Employee (2022) - Qualified, testified on data exfiltration\n- Federal v. Doe (2021) - Qualified, testified on timeline reconstruction\n\n(Full CV attached in Appendix E)\n```\n\n---\n\n### 17.9 Sample Forensic Report\n\nHere's a complete sample report demonstrating all principles.\n\n```markdown\nFORENSIC EXAMINATION REPORT\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nCASE INFORMATION\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nCase Number: CF-2023-0042\nExaminer: Senior Forensic Analyst John Smith\nDate of Report: 2023-12-15\nRequesting Party: Legal Department, Acme Corporation\nClassification: CONFIDENTIAL - ATTORNEY WORK PRODUCT\n\n1. EXECUTIVE SUMMARY\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nOn December 10, 2023, at the request of the Legal Department, this examiner \nconducted a forensic analysis of a Dell Latitude laptop (EX-001) belonging to \nJohn Doe, a former employee who resigned on November 16, 2023.\n\nThe examination revealed that between November 1-15, 2023, the user downloaded \n47 files containing proprietary company information totaling 45.7 MB to an \nexternal USB drive. These files included customer databases, pricing strategies, \nand confidential product specifications.\n\nOn November 16, 2023, at 9:15 AM, 23 of these files (totaling 23.4 MB) were \nemailed to the personal Gmail account johndoe.personal@gmail.com. The user \nsubmitted their resignation via email at 9:30 AM the same day.\n\nThe timing, method of access, and pattern of activity strongly indicate \ndeliberate data exfiltration rather than normal work activity or system \ncompromise. Detailed findings supporting these conclusions are provided below.\n\n2. CASE BACKGROUND\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nOn November 16, 2023, at 10:00 AM, John Doe submitted his resignation via email \nto Human Resources. Later that day, IT staff discovered that the employee had \naccessed an unusually large number of files in the days prior to resignation.\n\nOn December 10, 2023, the company's Legal Department requested a forensic \nexamination of the employee's company-issued laptop to determine if company \ndata had been exfiltrated.\n\nThe laptop was seized on December 10, 2023, at 2:30 PM, with the employee's \nconsent (consent form attached). The device was powered off at seizure.\n\n3. EVIDENCE LIST\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Item ID \u2502 Description     \u2502 Source       \u2502 SHA256 Hash                      \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 EX-001  \u2502 Dell Latitude   \u2502 John Doe     \u2502 Not applicable (physical item)   \u2502\n\u2502         \u2502 7420 Laptop      \u2502              \u2502                                  \u2502\n\u2502         \u2502 SN: 1A2B3C4D     \u2502              \u2502                                  \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 EX-001A \u2502 Forensic Image   \u2502 EX-001       \u2502 a1b2c3d4e5f67890a1b2c3d4e5f67890 \u2502\n\u2502         \u2502 of 500GB SSD     \u2502              \u2502                                  \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 EX-002  \u2502 Email Server     \u2502 IT Dept.     \u2502 Not applicable (log files)       \u2502\n\u2502         \u2502 Logs (30 days)   \u2502              \u2502                                  \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n4. EXAMINATION METHODOLOGY\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n4.1 Acquisition\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- EX-001 was imaged using Tableau TD3 write blocker\n- FTK Imager 4.7.1 created E01 image (EX-001A)\n- Verification hash calculated before and after imaging\n- Image verified (hash match)\n\n4.2 Analysis Tools\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Tool            \u2502 Version    \u2502 SHA256 Hash      \u2502 Verification  \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Autopsy         \u2502 4.20.0     \u2502 2b3c4d5e6f7g8h9i \u2502 Matched       \u2502\n\u2502 Plaso           \u2502 20230715   \u2502 3c4d5e6f7g8h9i0j \u2502 Matched       \u2502\n\u2502 RegRipper       \u2502 3.0        \u2502 4d5e6f7g8h9i0j1k \u2502 Matched       \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n4.3 Analysis Performed\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- File system analysis (NTFS)\n- MFT parsing and timeline creation\n- Registry analysis (USB history, user activity)\n- Email artifact extraction\n- Browser history analysis\n- Deleted file recovery\n- Timeline correlation\n\n5. TECHNICAL FINDINGS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n5.1 File System Analysis\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nThe 500GB SSD contained a single NTFS volume with Windows 10 Pro installed.\n\nTotal files examined: 127,453\nDeleted files recovered: 3,847\nEncrypted files identified: 3 (could not be examined without passwords)\n\n5.2 Key Files Identified\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Filename     \u2502 Full Path          \u2502 Created       \u2502 Modified     \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 customers.xlsx\u2502 C:\\Users\\John\\Docs \u2502 2023-11-10    \u2502 2023-11-15   \u2502\n\u2502              \u2502                     \u2502 09:15:22      \u2502 14:30:45     \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 pricing.pdf  \u2502 C:\\Users\\John\\Docs \u2502 2023-11-12    \u2502 2023-11-15   \u2502\n\u2502              \u2502                     \u2502 11:20:33      \u2502 14:32:18     \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 merger.docx  \u2502 C:\\Users\\John\\Docs \u2502 2023-11-14    \u2502 2023-11-15   \u2502\n\u2502              \u2502                     \u2502 13:45:12      \u2502 14:34:05     \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n[SCREENSHOT: customers.xlsx showing customer records]\n\n5.3 USB Device History\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nRegistry analysis revealed the following USB device connections:\n\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Device       \u2502 Serial Number      \u2502 First Seen    \u2502 Last Seen    \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 SanDisk Ultra\u2502 123456789ABC       \u2502 2023-11-15    \u2502 2023-11-15   \u2502\n\u2502 32GB         \u2502                     \u2502 14:40:22      \u2502 15:00:15     \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\nThe device was connected for approximately 20 minutes on November 15,\ncoinciding with the last access times of the key files identified above.\n\n5.4 File Copy Analysis (USN Journal)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nThe USN Journal recorded the following file copy operations on 2023-11-15:\n\n14:41:22 - customers.xlsx copied (FILE_CREATE)\n14:42:15 - customers.xlsx modified (DATA_OVERWRITE)\n14:45:33 - pricing.pdf copied (FILE_CREATE)\n14:46:12 - pricing.pdf modified (DATA_OVERWRITE)\n14:48:45 - merger.docx copied (FILE_CREATE)\n14:49:22 - merger.docx modified (DATA_OVERWRITE)\n[Additional entries for 44 more files...]\n\nThis pattern is consistent with bulk copying to external media.\n\n5.5 Email Evidence\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nEmail server logs (EX-002) show the following outgoing message:\n\nTimestamp: 2023-11-16 09:15:22\nFrom: john.doe@company.com\nTo: johndoe.personal@gmail.com\nSubject: Files\nSize: 24.6 MB\nAttachments: \n  - customers.xlsx (2.4 MB)\n  - pricing.pdf (1.8 MB)\n  - merger.docx (0.5 MB)\n  - [20 additional files...]\n\nThe email was sent from the company's internal network using\nthe employee's authenticated session.\n\n5.6 Resignation Email\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nTimestamp: 2023-11-16 09:30:45\nFrom: john.doe@company.com\nTo: hr@company.com\nSubject: Resignation - John Doe\n\nContent: \"Please accept this email as formal notification of my resignation...\"\n\n5.7 Deleted Files\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nThe following files were deleted on November 15, 2023, at approximately 14:35:\n\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Filename     \u2502 Original Path       \u2502 Deleted       \u2502 Recovery     \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 secret.docx  \u2502 C:\\Users\\John\\Docs  \u2502 2023-11-15    \u2502 92%          \u2502\n\u2502              \u2502                     \u2502 14:35:22      \u2502 recovered    \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\nRecovered content includes discussion of \"merger negotiations with XYZ Corp\"\nand \"final pricing strategy for Q1 2024.\"\n\n6. TIMELINE OF EVENTS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n2023-11-15\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n14:30    Last access of customers.xlsx\n14:32    Last access of pricing.pdf\n14:34    Last access of merger.docx\n14:35    secret.docx deleted\n14:40    SanDisk Ultra USB drive connected\n14:41-14:55 Mass file copy to USB (47 files, 45.7 MB)\n15:00    USB drive disconnected\n15:05    System shutdown (user leaves early)\n\n2023-11-16\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n09:00    User logs in\n09:15    Email to personal account with 23 attachments (23.4 MB)\n09:30    Resignation email to HR\n09:45    Browser searches for \"how to remove company data from personal email\"\n09:50    System shutdown\n\n7. ANALYSIS &amp; INTERPRETATION\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n7.1 Pattern Analysis\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nThe sequence of events shows a clear pattern:\n1. Identification of valuable files (Nov 10-14)\n2. Copy to external media (Nov 15)\n3. Email of subset to personal account (Nov 16)\n4. Deletion of sensitive document (Nov 15)\n5. Resignation submission (Nov 16)\n\nThis pattern is consistent with data exfiltration prior to departure.\n\n7.2 Alternative Explanations Considered\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nAlternative 1: Normal work backup\n- Inconsistent with: Personal email recipient, timing with resignation,\n  deletion of files, search for removal methods\n\nAlternative 2: System compromise\n- No evidence of unauthorized access; actions performed with user's\n  credentials during normal hours; no malware detected\n\nAlternative 3: Accidental email\n- Multiple attachments (23 files) inconsistent with accident;\n  files were specifically selected from documents folder\n\n7.3 Expert Opinion\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nBased on over 12 years of digital forensic experience and having\nexamined hundreds of similar cases, it is my expert opinion that:\n\n1. John Doe deliberately copied 47 proprietary files to external media\n2. John Doe deliberately emailed 23 of those files to his personal account\n3. These actions were performed in preparation for resignation\n4. The deletion of secret.docx was an attempt to conceal evidence\n5. No evidence suggests these actions were authorized or accidental\n\n8. LIMITATIONS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- The USB drive was not recovered; exact destination of all files unknown\n- Three encrypted files could not be examined\n- Personal email account content not accessible\n- System time was 3 minutes 22 seconds ahead of UTC (timestamps adjusted)\n\n9. CONCLUSIONS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nThe forensic examination of EX-001 has determined that John Doe\nexfiltrated 47 proprietary company files totaling 45.7 MB to external\nmedia and additionally emailed 23 of those files to a personal email\naccount immediately before resigning from the company.\n\nThe evidence strongly supports a finding of intentional data theft\nrather than normal work activity or system compromise.\n\n10. RECOMMENDATIONS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n1. Preserve all evidence for potential legal proceedings\n2. Consider legal action for theft of intellectual property\n3. Review access controls and monitoring for sensitive data\n4. Implement DLP (Data Loss Prevention) solutions\n5. Conduct exit interviews with immediate data access revocation\n\nAPPENDICES\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\nA. Chain of Custody Documentation\nB. Tool Verification Hashes\nC. Complete File Listing\nD. Email Server Logs\nE. Examiner CV and Qualifications\nF. Glossary of Technical Terms\n\nI declare under penalty of perjury that the foregoing is true and correct.\n\nSigned:\n\n_________________________\nJohn Smith, Senior Forensic Analyst\nCyber Forensics Inc.\nDate: December 15, 2023\n```\n\n---\n\n## Chapter 18 \u2013 Real-World Case Studies\n\n---\n\n### 18.1 Case Study 1: Ransomware Investigation\n\n#### Incident Overview\n\n```\nINCIDENT: Conti Ransomware Attack\nDATE: March 15, 2023\nVICTIM: Mid-sized manufacturing company (500 employees)\nIMPACT: 200 servers encrypted, production halted for 5 days\nRANSOM DEMAND: 50 Bitcoin (~$1.5M at time)\n```\n\n#### Initial Response\n\n```markdown\nINITIAL RESPONSE TIMELINE\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nDay 1 - 08:00\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nIT staff notice files with .conti extension\nSystems becoming unresponsive\nRansom note displayed on 50+ workstations\n\nDay 1 - 08:30\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nIncident response team activated\nSystems isolated from network\nContainment begun\n\nDay 1 - 10:00\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nForensic team arrives on site\nPreservation of affected systems begins\nNetwork isolation verified\n\nDay 1 - 12:00\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nCritical servers identified for priority recovery\nBackup systems checked (70% intact)\nLaw enforcement notified\n```\n\n#### Forensic Analysis\n\n```python\n# Ransomware investigation workflow\n\ndef analyze_ransomware_infection(evidence_path):\n    \"\"\"Analyze ransomware infection artifacts\"\"\"\n    \n    findings = {\n        'entry_point': None,\n        'execution_time': None,\n        'files_encrypted': [],\n        'ransom_note': None,\n        'indicators': [],\n        'timeline': []\n    }\n    \n    # 1. Identify entry point\n    # Look for phishing emails, RDP brute force, vulnerability exploit\n    \n    # Check email logs\n    email_logs = parse_email_logs(f\"{evidence_path}/mail.log\")\n    suspicious_emails = [e for e in email_logs if 'invoice' in e['subject'].lower() \n                         and e['attachment'] and e['attachment'].endswith('.doc')]\n    \n    if suspicious_emails:\n        findings['entry_point'] = {\n            'type': 'phishing',\n            'email': suspicious_emails[-1],\n            'time': suspicious_emails[-1]['timestamp']\n        }\n    \n    # 2. Track execution\n    # Look for process creation events\n    \n    # Windows Event Log 4688 (process creation)\n    process_events = parse_windows_events(f\"{evidence_path}/Security.evtx\")\n    \n    suspicious_processes = [\n        'powershell.exe -enc', 'rundll32.exe', 'mshta.exe',\n        'wscript.exe', 'cscript.exe', 'regsvr32.exe'\n    ]\n    \n    for event in process_events:\n        if event.get('event_id') == 4688:\n            cmdline = event.get('command_line', '').lower()\n            if any(p in cmdline for p in suspicious_processes):\n                findings['indicators'].append({\n                    'type': 'suspicious_process',\n                    'time': event['timestamp'],\n                    'process': event.get('new_process_name'),\n                    'command': cmdline\n                })\n    \n    # 3. Identify encrypted files\n    # Look for files with .conti extension\n    for root, dirs, files in os.walk(evidence_path):\n        for file in files:\n            if file.endswith('.conti'):\n                findings['files_encrypted'].append({\n                    'path': os.path.join(root, file),\n                    'original': file[:-6],  # Remove .conti\n                    'size': os.path.getsize(os.path.join(root, file))\n                })\n    \n    # 4. Find ransom note\n    ransom_notes = []\n    for root, dirs, files in os.walk(evidence_path):\n        for file in files:\n            if 'readme' in file.lower() or 'ransom' in file.lower():\n                note_path = os.path.join(root, file)\n                with open(note_path, 'r', errors='ignore') as f:\n                    content = f.read()\n                    if 'bitcoin' in content.lower() or 'conti' in content.lower():\n                        ransom_notes.append({\n                            'path': note_path,\n                            'content': content[:500]\n                        })\n    \n    if ransom_notes:\n        findings['ransom_note'] = ransom_notes[0]\n    \n    # 5. Extract IOCs\n    # Look for C2 connections\n    network_logs = parse_network_logs(f\"{evidence_path}/firewall.log\")\n    \n    suspicious_ips = []\n    for log in network_logs:\n        if log.get('destination_ip'):\n            # Check against threat intel (simplified)\n            if log['destination_ip'].startswith(('185.', '94.', '91.')):\n                suspicious_ips.append(log['destination_ip'])\n    \n    findings['indicators'].append({\n        'type': 'c2_ips',\n        'ips': list(set(suspicious_ips))\n    })\n    \n    return findings\n```\n\n#### Key Findings\n\n```markdown\nFORENSIC FINDINGS\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n1. ENTRY POINT\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nInitial compromise occurred via phishing email sent March 14, 2023, 14:23\nEmail purported to be from \"Accounts Payable\" with subject \"Overdue Invoice\"\nAttachment: invoice_74382.doc (contained malicious macro)\n\n2. EXECUTION TIMELINE\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nMarch 14, 14:25 - User opens attachment, enables macros\nMarch 14, 14:26 - PowerShell downloads Cobalt Strike beacon\nMarch 14, 14:30-16:00 - Attacker establishes persistence, enumerates network\nMarch 14, 16:00-20:00 - Lateral movement to file servers and domain controllers\nMarch 14, 20:00-23:00 - Data exfiltration (approx. 50GB to 185.130.5.23)\nMarch 15, 02:00 - Ransomware deployment begins\nMarch 15, 02:30 - First systems show encrypted files\nMarch 15, 08:00 - Users report issues, incident discovered\n\n3. SCOPE OF IMPACT\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Total systems encrypted: 1,247 (workstations and servers)\n- Total files encrypted: Approximately 2.3 million\n- Data exfiltrated: 50GB (customer data, financial records, IP)\n- Backup integrity: 70% recoverable (some backups also encrypted)\n\n4. ATTRIBUTION INDICATORS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Ransom note language and formatting matches known Conti samples\n- Encryption routine uses RSA-2048 + AES-256 (Conti signature)\n- C2 infrastructure overlaps with known Conti infrastructure\n- Bitcoin wallet address: 1ContiV3rS1oNxxxxxx (previously seen in Conti attacks)\n\n5. RECOVERED EVIDENCE\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Phishing email with attachment (preserved)\n- PowerShell script from temporary directory\n- Cobalt Strike beacon configuration\n- Partial network traffic containing exfiltration\n- Ransom note with payment instructions\n- Encrypted files with .conti extension\n```\n\n#### Lessons Learned\n\n```markdown\nLESSONS LEARNED &amp; RECOMMENDATIONS\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nTechnical Controls:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n1. Email Filtering\n   - Implement advanced phishing detection\n   - Block macros in Office documents from external sources\n   - Sandbox all email attachments\n\n2. Endpoint Protection\n   - Deploy EDR on all endpoints\n   - Restrict PowerShell execution\n   - Application whitelisting for critical systems\n\n3. Network Security\n   - Segment networks (IT vs OT)\n   - Implement 802.1x authentication\n   - Monitor for anomalous outbound traffic\n\n4. Backup Strategy\n   - Maintain offline/immutable backups\n   - Test restoration procedures regularly\n   - 3-2-1 backup rule (3 copies, 2 media, 1 offsite)\n\nProcedural Controls:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n1. User Training\n   - Phishing awareness (monthly simulated campaigns)\n   - Reporting procedures for suspicious emails\n   - Password hygiene and MFA\n\n2. Incident Response\n   - Regular tabletop exercises\n   - Updated IR plan with ransomware playbook\n   - Pre-established relationship with law enforcement\n\n3. Access Control\n   - Least privilege principle\n   - Regular access reviews\n   - Privileged Access Management (PAM)\n\nResponse Effectiveness:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nWhat worked well:\n- Rapid isolation of affected systems\n- Communication plan with stakeholders\n- Backup restoration (70% recovered)\n\nWhat needed improvement:\n- Detection time (12 hours from infection to discovery)\n- Offline backup availability\n- Third-party communication\n```\n\n---\n\n### 18.2 Case Study 2: Insider Data Theft\n\n#### Incident Overview\n\n```markdown\nINCIDENT: Intellectual Property Theft\nDATE: June 2023\nVICTIM: Technology startup (50 employees)\nIMPACT: Source code and product roadmap stolen\nSUSPECT: Senior developer (resigned to join competitor)\n```\n\n#### Investigation Process\n\n```markdown\nINVESTIGATION WORKFLOW\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nPhase 1: Initial Triage (Day 1)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Interviewed manager and IT staff\n- Identified key data at risk (source code repositories)\n- Preserved laptop, email, and cloud access logs\n- Documented resignation timeline\n\nPhase 2: Evidence Acquisition (Day 1-2)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Created forensic images of company laptop (EX-001)\n- Acquired email server logs for 90 days (EX-002)\n- Exported GitHub access logs (EX-003)\n- Preserved Slack/Discord communications (EX-004)\n\nPhase 3: Analysis (Day 2-5)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- File system timeline reconstruction\n- USB device history analysis\n- Cloud storage activity review\n- Communication pattern analysis\n- Code repository access review\n\nPhase 4: Findings &amp; Reporting (Day 5-7)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Correlated activities with resignation timeline\n- Identified exfiltrated data\n- Documented chain of events\n- Prepared expert report\n```\n\n#### Evidence Analysis\n\n```python\ndef analyze_insider_theft(case_path):\n    \"\"\"Analyze insider data theft case\"\"\"\n    \n    findings = {\n        'data_accessed': [],\n        'exfiltration_methods': [],\n        'timeline': [],\n        'communications': [],\n        'technical_indicators': []\n    }\n    \n    # 1. File access patterns\n    file_logs = parse_file_access_logs(f\"{case_path}/file_server.log\")\n    \n    # Look for unusual access patterns\n    from collections import Counter\n    user_files = [f for f in file_logs if f['user'] == 'suspect']\n    \n    # Group by day\n    by_day = Counter()\n    for entry in user_files:\n        day = entry['timestamp'].date()\n        by_day[day] += 1\n    \n    # Identify spike days\n    avg_access = sum(by_day.values()) / len(by_day)\n    for day, count in by_day.items():\n        if count &gt; avg_access * 3:  # 3x normal\n            findings['technical_indicators'].append({\n                'type': 'access_spike',\n                'date': day,\n                'files': count,\n                'normal_avg': avg_access\n            })\n    \n    # 2. USB activity\n    usb_logs = parse_usb_logs(f\"{case_path}/usb_history.csv\")\n    \n    for log in usb_logs:\n        if log['user'] == 'suspect':\n            findings['exfiltration_methods'].append({\n                'type': 'usb',\n                'device': log['device'],\n                'serial': log['serial'],\n                'connected': log['connected'],\n                'disconnected': log['disconnected']\n            })\n    \n    # 3. Cloud storage\n    cloud_logs = parse_cloud_logs(f\"{case_path}/cloud_access.log\")\n    \n    for log in cloud_logs:\n        if log['user'] == 'suspect' and log['action'] == 'download':\n            if log['file_size'] &gt; 10 * 1024 * 1024:  # &gt;10MB\n                findings['data_accessed'].append({\n                    'type': 'cloud_download',\n                    'file': log['file'],\n                    'size': log['file_size'],\n                    'time': log['timestamp']\n                })\n    \n    # 4. Email exfiltration\n    email_logs = parse_email_logs(f\"{case_path}/email.log\")\n    \n    for log in email_logs:\n        if log['from'] == 'suspect@company.com':\n            if log['to'] not in ['@company.com']:\n                # External recipient\n                if log['attachments']:\n                    findings['exfiltration_methods'].append({\n                        'type': 'email',\n                        'to': log['to'],\n                        'attachments': log['attachments'],\n                        'time': log['timestamp']\n                    })\n    \n    # 5. Create timeline\n    all_events = []\n    \n    # Add file access events\n    for entry in user_files:\n        all_events.append({\n            'time': entry['timestamp'],\n            'type': 'file_access',\n            'details': f\"Accessed {entry['file']}\"\n        })\n    \n    # Add USB events\n    for usb in findings['exfiltration_methods']:\n        if usb['type'] == 'usb':\n            all_events.append({\n                'time': usb['connected'],\n                'type': 'usb_connect',\n                'details': f\"Connected {usb['device']}\"\n            })\n    \n    # Add email events\n    for email in findings['exfiltration_methods']:\n        if email['type'] == 'email':\n            all_events.append({\n                'time': email['time'],\n                'type': 'email_exfil',\n                'details': f\"Sent {len(email['attachments'])} attachments to {email['to']}\"\n            })\n    \n    # Sort timeline\n    all_events.sort(key=lambda x: x['time'])\n    findings['timeline'] = all_events\n    \n    return findings\n```\n\n#### Findings Summary\n\n```markdown\nKEY FINDINGS\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n1. UNAUTHORIZED DATA ACCESS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Between June 1-15, 2023, suspect accessed 2,347 files (vs. normal 150/week)\n- Spike days: June 10 (487 files), June 14 (512 files), June 15 (498 files)\n- Accessed files included: source code (72%), design documents (15%), \n  product roadmap (8%), customer lists (5%)\n\n2. EXFILTRATION METHODS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nA. USB Device (June 14-15)\n   - Device: Samsung T7 Portable SSD (SN: S3Z1NS0M123456)\n   - Connected: June 14, 16:30 - 18:45 (2h 15m)\n   - Connected: June 15, 15:20 - 16:10 (50m)\n   - Total data transfer: ~45GB (calculated from USN Journal)\n\nB. Cloud Storage (June 1-10)\n   - Personal Google Drive accessed via browser\n   - 12 files uploaded (total 85MB)\n   - Files included: architecture diagrams, API specifications\n\nC. Email (June 14)\n   - Sent to personal email (suspect.personal@gmail.com)\n   - 3 attachments totaling 15MB\n   - Subject: \"Personal files - please archive\"\n\n3. COMMUNICATIONS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nSlack messages revealed (recovered from cache):\n\nJune 5, 14:30:\nSuspect to Friend (external): \"Interview went well, likely offer next week\"\n\nJune 10, 09:15:\nSuspect to Colleague: \"Can you show me how to clone all repos at once?\"\n\nJune 13, 11:20:\nSuspect to Friend: \"Got the offer, giving notice Thursday\"\n\n4. TIMELINE\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nJune 1-5: Initial job interviews (external comms)\nJune 1-10: Gradual access to sensitive files\nJune 10: Asked about cloning repositories\nJune 14: USB connection (evening), email exfiltration\nJune 15: Final USB connection, copied remaining files\nJune 16: Resignation submitted (9:30 AM)\n\n5. DATA CLASSIFICATION\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nData exfiltrated by category:\n- Source code: 35GB (core product, 80% of repository)\n- Architecture docs: 5GB (system design, AWS infrastructure)\n- Product roadmap: 500MB (next 18 months)\n- Customer data: 2GB (PII of enterprise clients)\n- Financial projections: 300MB (5-year forecast)\n\nEstimated value: $2-5M (replacement cost + competitive advantage)\n```\n\n#### Legal Outcome\n\n```markdown\nLEGAL PROCEEDINGS\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nCriminal Case:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Charged with: Theft of trade secrets (18 U.S.C. \u00a7 1832)\n- Evidence: Forensic report, email logs, USB history, Slack messages\n- Plea: Guilty to lesser charge (misdemeanor data theft)\n- Sentence: 6 months probation, $50,000 fine\n\nCivil Case:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Lawsuit: Breach of contract, misappropriation of trade secrets\n- Defendant: Former employee + competitor (hiring company)\n- Settlement: $1.2 million (confidential)\n- Injunction: Barred from using stolen technology\n\nLessons for Organization:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Implemented DLP (Data Loss Prevention) software\n- Restricted USB access (whitelisted devices only)\n- Developer workstations in VDI environment\n- Source code access logging and alerting\n- Exit procedures include immediate access revocation\n- Background checks for new hires\n- Non-compete agreements enforced\n```\n\n---\n\n### 18.3 Case Study 3: Financial Fraud Investigation\n\n#### Incident Overview\n\n```markdown\nINCIDENT: Business Email Compromise (BEC) + Wire Fraud\nDATE: August 2023\nVICTIM: Real estate investment firm\nLOSS: $1.2 million (wired to fraudulent account)\nMETHOD: Compromised CEO email, fraudulent wire instructions\n```\n\n#### Investigation Process\n\n```markdown\nINVESTIGATION WORKFLOW\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nPhase 1: Emergency Response (Day 1)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Identified fraudulent wire ($1.2M to Hong Kong bank)\n- Contacted bank (funds frozen in transit - recovered $800K)\n- Preserved email servers and workstations\n- Contacted FBI (cyber task force)\n\nPhase 2: Technical Analysis (Day 1-3)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Email server forensics\n- Compromised workstation analysis\n- Network traffic review\n- Bank account tracing\n\nPhase 3: Financial Tracing (Day 2-7)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Wire transfer records\n- Cryptocurrency conversion (partial)\n- Money trail documentation\n- International cooperation (MLAT)\n\nPhase 4: Attribution (Week 2-4)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Infrastructure analysis\n- Threat actor profiling\n- Intelligence sharing\n```\n\n#### Technical Findings\n\n```python\ndef analyze_bec_attack(email_logs, workstation_image):\n    \"\"\"Analyze Business Email Compromise attack\"\"\"\n    \n    findings = {\n        'compromise_method': None,\n        'timeline': [],\n        'fraudulent_emails': [],\n        'indicators': []\n    }\n    \n    # 1. Identify compromise method\n    # Check for phishing email that led to compromise\n    phishing_indicators = ['password', 'verify', 'account', 'urgent', \n                          'security alert', 'microsoft', 'office365']\n    \n    for email in email_logs:\n        if email['folder'] == 'inbox':\n            subject = email['subject'].lower()\n            body = email['body'].lower()\n            \n            if any(ind in subject or ind in body for ind in phishing_indicators):\n                if email.get('has_attachment'):\n                    findings['compromise_method'] = {\n                        'type': 'phishing',\n                        'email': email,\n                        'time': email['timestamp']\n                    }\n                    break\n    \n    # 2. Check for mailbox rule creation (common in BEC)\n    mailbox_rules = parse_outlook_rules(workstation_image)\n    \n    for rule in mailbox_rules:\n        if 'forward' in rule['action'].lower() and 'external' in rule['action'].lower():\n            findings['indicators'].append({\n                'type': 'mail_forwarding_rule',\n                'rule': rule,\n                'created': rule['created']\n            })\n    \n    # 3. Identify fraudulent emails\n    for email in email_logs:\n        if email['folder'] == 'sent':\n            # Look for wire transfer emails\n            if any(word in email['body'].lower() for word in ['wire', 'transfer', 'ach', 'payment']):\n                \n                # Check if recipient is external and not in normal contacts\n                if '@' in email['to'] and not email['to'].endswith('@company.com'):\n                    findings['fraudulent_emails'].append({\n                        'time': email['timestamp'],\n                        'to': email['to'],\n                        'subject': email['subject'],\n                        'body_preview': email['body'][:200]\n                    })\n    \n    # 4. Create timeline\n    for email in findings['fraudulent_emails']:\n        findings['timeline'].append({\n            'time': email['time'],\n            'event': 'fraudulent_email_sent',\n            'details': f\"To {email['to']}: {email['subject']}\"\n        })\n    \n    return findings\n```\n\n#### Financial Tracing\n\n```python\ndef trace_fraudulent_funds(bank_records, blockchain_data):\n    \"\"\"Trace funds from wire fraud\"\"\"\n    \n    trace = {\n        'initial_transfer': None,\n        'intermediate_accounts': [],\n        'final_destination': None,\n        'recovered': 0,\n        'timeline': []\n    }\n    \n    # 1. Initial wire transfer\n    initial = bank_records[0]  # Wire from victim to first account\n    trace['initial_transfer'] = {\n        'from': initial['source_account'],\n        'to': initial['destination_account'],\n        'amount': initial['amount'],\n        'date': initial['date'],\n        'bank': initial['destination_bank']\n    }\n    \n    trace['timeline'].append({\n        'date': initial['date'],\n        'event': 'initial_wire',\n        'details': f\"${initial['amount']:,} to {initial['destination_bank']}\"\n    })\n    \n    # 2. Follow money through accounts\n    current_account = initial['destination_account']\n    \n    for record in bank_records[1:]:\n        if record['source_account'] == current_account:\n            trace['intermediate_accounts'].append({\n                'from': current_account,\n                'to': record['destination_account'],\n                'amount': record['amount'],\n                'date': record['date'],\n                'bank': record['destination_bank']\n            })\n            \n            trace['timeline'].append({\n                'date': record['date'],\n                'event': 'funds_transferred',\n                'details': f\"${record['amount']:,} to {record['destination_bank']}\"\n            })\n            \n            current_account = record['destination_account']\n            \n            # Check if converted to crypto\n            if 'exchange' in record['destination_bank'].lower():\n                trace['timeline'].append({\n                    'date': record['date'],\n                    'event': 'crypto_conversion',\n                    'details': \"Funds converted to Bitcoin\"\n                })\n    \n    # 3. Trace Bitcoin if applicable\n    if blockchain_data:\n        btc_trace = trace_bitcoin(blockchain_data['address'], blockchain_data['transactions'])\n        trace['crypto_trace'] = btc_trace\n    \n    # 4. Calculate recovered amount\n    # Funds frozen at various points\n    trace['recovered'] = 800000  # $800K recovered\n    trace['lost'] = 400000  # $400K lost\n    \n    return trace\n\ndef trace_bitcoin(address, transactions):\n    \"\"\"Trace Bitcoin transactions\"\"\"\n    \n    trace = {\n        'address': address,\n        'received': 0,\n        'sent': 0,\n        'exchanges': [],\n        'mixers': []\n    }\n    \n    for tx in transactions:\n        if tx['type'] == 'received':\n            trace['received'] += tx['amount']\n            \n            # Check if from known exchange\n            if tx.get('source_exchange'):\n                trace['exchanges'].append({\n                    'name': tx['source_exchange'],\n                    'amount': tx['amount'],\n                    'date': tx['date']\n                })\n        \n        elif tx['type'] == 'sent':\n            trace['sent'] += tx['amount']\n            \n            # Check if to exchange (cashing out)\n            if tx.get('destination_exchange'):\n                trace['exchanges'].append({\n                    'name': tx['destination_exchange'],\n                    'amount': tx['amount'],\n                    'date': tx['date'],\n                    'type': 'cash_out'\n                })\n            \n            # Check if to mixer\n            if detect_mixing_service(tx['destination']):\n                trace['mixers'].append({\n                    'address': tx['destination'],\n                    'amount': tx['amount'],\n                    'date': tx['date']\n                })\n    \n    return trace\n```\n\n#### Investigation Outcomes\n\n```markdown\nINVESTIGATION RESULTS\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n1. COMPROMISE METHOD\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Initial compromise: Phishing email received August 1, 2023\n- Email subject: \"Action Required: Office 365 Password Expiration\"\n- Attachment: \"password_update.html\" (credential harvesting page)\n- CEO credentials stolen at 14:23 (2-factor bypassed via session cookie)\n\n2. ATTACKER ACTIVITY\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nAugust 1, 14:30 - Attacker logs into CEO email\nAugust 1, 14:35 - Mail forwarding rule created (to attacker@protonmail.com)\nAugust 1-7 - Attacker monitors email traffic, learns payment processes\nAugust 8, 10:15 - Attacker sends fraudulent wire instructions to CFO\nAugust 8, 11:30 - CFO initiates $1.2M wire to \"new vendor account\"\nAugust 8, 14:00 - Funds arrive at Hong Kong bank (HSBC)\nAugust 8, 15:00 - Funds split: $800K to three additional accounts\nAugust 8, 16:30 - $400K converted to Bitcoin via Binance\nAugust 9, 08:00 - Fraud discovered\n\n3. FUNDS TRACING\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Destination     \u2502 Amount       \u2502 Status       \u2502 Notes            \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 HSBC Hong Kong  \u2502 $1,200,000   \u2502 Frozen       \u2502 Initial deposit  \u2502\n\u2502 DBS Singapore   \u2502 $400,000     \u2502 Frozen       \u2502 First split      \u2502\n\u2502 Maybank Malaysia\u2502 $250,000     \u2502 Frozen       \u2502 Second split     \u2502\n\u2502 Bank of Thailand\u2502 $150,000     \u2502 Frozen       \u2502 Third split      \u2502\n\u2502 Binance (BTC)   \u2502 $400,000     \u2502 Traced       \u2502 Converted to BTC \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n4. ATTRIBUTION\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Tactics, techniques, and procedures (TTPs) match known Nigerian BEC group\n- \"Silver Terrier\" threat actor cluster\n- Infrastructure: Bulletproof hosting in Russia, ProtonMail accounts\n- Bitcoin wallet previously associated with romance scams\n\n5. RECOVERY\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Frozen funds: $800,000 (recovered)\n- Cryptocurrency: $150,000 traced to exchange (frozen)\n- Final loss: $250,000 (likely unrecoverable)\n\n6. RECOMMENDATIONS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Implement hardware tokens for 2FA (not SMS/app-based)\n- Train staff on BEC red flags (urgent requests, vendor changes)\n- Verify wire changes via secondary channel (phone call)\n- Implement positive pay and dual approval for wires\n- Monitor for mail forwarding rules (alerting)\n- Cyber insurance with wire fraud coverage\n```\n\n---\n\n### 18.4 Case Study 4: APT Intrusion Analysis\n\n#### Incident Overview\n\n```markdown\nINCIDENT: Advanced Persistent Threat (APT) Intrusion\nDATE: January-March 2023\nVICTIM: Defense contractor\nATTRIBUTION: APT10 (China-based)\nOBJECTIVE: Intellectual property theft (aerospace technology)\nIMPACT: 5TB data exfiltrated over 3 months\n```\n\n#### Attack Timeline\n\n```markdown\nATTACK LIFECYCLE\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nPhase 1: Initial Compromise (January 15-20)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Spear phishing to engineering department\n- Malicious Word document: \"F-35_specifications.docx\"\n- Exploit CVE-2017-11882 (Equation Editor)\n- Dropper installed Cobalt Strike beacon\n\nPhase 2: Establishment (January 20-25)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Beacon calling home to 45.77.xxx.xxx (Singapore)\n- PowerShell download of additional tools\n- Registry persistence (Run key)\n- Scheduled task: \"WindowsUpdateTask\"\n\nPhase 3: Privilege Escalation (January 25-30)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Credential dumping (Mimikatz)\n- Pass-the-hash to domain controller\n- Golden ticket creation\n- Domain admin access achieved\n\nPhase 4: Lateral Movement (February 1-15)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Deployed to 47 workstations and 12 servers\n- WMI and PSExec for remote execution\n- Created admin accounts: \"sysadmin\", \"backupuser\"\n- Disabled security tools (AV, EDR)\n\nPhase 5: Data Collection (February 15-March 15)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Identified file servers with technical data\n- RAR archives of sensitive directories\n- Staged in \"C:\\Windows\\Temp\\\"\n- Compressed with password protection\n\nPhase 6: Exfiltration (March 15-30)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- RDP to staging server\n- FTP to external server (45.77.xxx.xxx)\n- 5TB data exfiltrated over 2 weeks\n- Clean-up scripts executed\n\nPhase 7: Discovery (April 1)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- Anomalous outbound traffic detected\n- IR team activated\n- Forensics began\n```\n\n#### Forensic Analysis\n\n```python\ndef analyze_apt_intrusion(evidence_path):\n    \"\"\"Analyze APT intrusion\"\"\"\n    \n    findings = {\n        'initial_access': [],\n        'persistence': [],\n        'credential_access': [],\n        'lateral_movement': [],\n        'exfiltration': [],\n        'timeline': [],\n        'iocs': []\n    }\n    \n    # 1. Identify initial access\n    # Check for phishing email\n    email_logs = parse_email_logs(f\"{evidence_path}/mail.log\")\n    \n    suspicious_emails = []\n    for email in email_logs:\n        if email['attachment'] and email['attachment'].endswith('.doc'):\n            if 'spec' in email['subject'].lower() or 'f-35' in email['subject'].lower():\n                suspicious_emails.append(email)\n    \n    if suspicious_emails:\n        findings['initial_access'] = suspicious_emails\n    \n    # 2. Find persistence mechanisms\n    # Registry Run keys\n    registry = parse_registry_hive(f\"{evidence_path}/NTUSER.DAT\")\n    run_keys = registry.get_run_keys()\n    \n    for key in run_keys:\n        if key['value'] not in ['OneDrive', 'Teams', 'SecurityHealth']:\n            findings['persistence'].append({\n                'type': 'registry_run',\n                'key': key['path'],\n                'value': key['value'],\n                'data': key['data']\n            })\n    \n    # Scheduled tasks\n    tasks = parse_scheduled_tasks(f\"{evidence_path}/Tasks\")\n    \n    for task in tasks:\n        if 'Microsoft' not in task['name'] and 'Windows' not in task['name']:\n            findings['persistence'].append({\n                'type': 'scheduled_task',\n                'name': task['name'],\n                'trigger': task['trigger'],\n                'action': task['action']\n            })\n    \n    # 3. Credential access\n    # Look for Mimikatz usage\n    security_logs = parse_windows_events(f\"{evidence_path}/Security.evtx\")\n    \n    for log in security_logs:\n        if log['event_id'] == 4672:  # Special privileges assigned\n            if 'sedebug' in log['message'].lower():\n                findings['credential_access'].append({\n                    'type': 'mimikatz',\n                    'time': log['timestamp'],\n                    'process': log.get('process_name'),\n                    'user': log.get('user')\n                })\n    \n    # 4. Lateral movement\n    # Check for WMI and PSExec\n    for log in security_logs:\n        if log['event_id'] == 4688:  # Process creation\n            cmd = log.get('command_line', '').lower()\n            if 'wmic' in cmd or 'psexec' in cmd or 'winrm' in cmd:\n                findings['lateral_movement'].append({\n                    'type': 'remote_execution',\n                    'time': log['timestamp'],\n                    'command': cmd,\n                    'user': log.get('user')\n                })\n    \n    # 5. Exfiltration\n    # Look for large file creations and transfers\n    file_logs = parse_file_creation_logs(f\"{evidence_path}/USNJournal\")\n    \n    for log in file_logs:\n        if log['path'].endswith('.rar') or log['path'].endswith('.zip'):\n            if log['size'] &gt; 100 * 1024 * 1024:  # &gt;100MB\n                findings['exfiltration'].append({\n                    'type': 'archive_created',\n                    'path': log['path'],\n                    'size': log['size'],\n                    'time': log['time']\n                })\n    \n    # Network connections\n    net_logs = parse_network_logs(f\"{evidence_path}/netstat.log\")\n    \n    for log in net_logs:\n        if log['remote_ip'] not in ['10.', '172.', '192.168.']:\n            if log['bytes_sent'] &gt; 10 * 1024 * 1024:  # &gt;10MB\n                findings['exfiltration'].append({\n                    'type': 'data_transfer',\n                    'remote_ip': log['remote_ip'],\n                    'bytes': log['bytes_sent'],\n                    'time': log['time']\n                })\n    \n    # 6. Create IOCs\n    findings['iocs'] = {\n        'ips': list(set([l['remote_ip'] for l in net_logs if 'remote_ip' in l])),\n        'domains': ['update.microsoft-dns.com', 'cdn.cloudflare-ssl.net'],\n        'hashes': ['e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'],\n        'registry_keys': [k['path'] for k in findings['persistence'] if k['type'] == 'registry_run'],\n        'file_paths': [f['path'] for f in findings['exfiltration']]\n    }\n    \n    return findings\n```\n\n#### Technical Findings\n\n```markdown\nTECHNICAL FINDINGS\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n1. MALWARE ANALYSIS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nCobalt Strike Beacon (MD5: 1a2b3c4d5e6f7g8h9i0j)\n- Configuration extracted:\n  - C2 Server: 45.77.xxx.xxx:443\n  - User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0)\n  - Beacon interval: 60 seconds\n  - Jitter: 20%\n  - Public key: [RSA 2048-bit]\n  - Tasks: file download, command execution, screenshots\n\nCustom Tools:\n- cred_dump.exe (Mimikatz variant)\n- scan_net.exe (network enumeration)\n- archive_util.exe (RAR compression)\n- clean_tracks.ps1 (PowerShell script)\n\n2. NETWORK INFRASTRUCTURE\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nC2 Infrastructure:\n- Primary: 45.77.xxx.xxx (Singapore, Vultr hosting)\n- Backup: 103.56.xxx.xxx (Hong Kong, Alibaba Cloud)\n- Fallback: Domain generation algorithm (DGA)\n\nData Exfiltration:\n- FTP server: 45.77.xxx.xxx (same as C2)\n- Protocol: FTP (port 21)\n- Credentials: uploader / P@ssw0rd123\n- Data stored in /incoming/[timestamp]/ directories\n\n3. DATA STOLEN\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nTotal: 5.2 TB (estimated 1.2 million files)\n\nCategories:\n- F-35 Lightning II specifications (450GB)\n- Hypersonic missile research (320GB)\n- Radar systems (280GB)\n- Satellite communications (210GB)\n- Supply chain information (190GB)\n- Personnel records (150GB)\n- Other technical data (3.6TB)\n\nClassification levels:\n- Top Secret: 1.2TB\n- Secret: 2.8TB\n- Confidential: 1.2TB\n\n4. DWELL TIME\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nInitial compromise: January 15, 2023\nFirst exfiltration: March 15, 2023\nDetection: April 1, 2023\nTotal dwell time: 76 days\n\n5. DETECTION GAPS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- No email sandboxing (macro allowed)\n- No application whitelisting\n- Delayed patch management (CVE-2017-11882)\n- Insufficient network monitoring\n- No EDR on engineering workstations\n- No data loss prevention (DLP)\n```\n\n#### Lessons Learned\n\n```markdown\nCRITICAL LESSONS\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nTechnical Improvements Implemented:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n1. Email Security\n   - Sandbox all attachments\n   - Block macros by default\n   - DMARC/DKIM/SPF enforcement\n\n2. Endpoint Protection\n   - EDR on all endpoints (CrowdStrike)\n   - Application whitelisting\n   - PowerShell constrained language mode\n   - Credential Guard enabled\n\n3. Network Security\n   - 24/7 SOC monitoring\n   - NetFlow analysis\n   - DNS sinkholing\n   - TLS inspection\n   - Network segmentation\n\n4. Access Control\n   - Privileged Access Workstations (PAW)\n   - Just-in-Time (JIT) administration\n   - Hardware tokens for 2FA\n   - Regular credential rotation\n\n5. Data Protection\n   - DLP implementation\n   - Data classification\n   - Rights management\n   - Database activity monitoring\n\nProcess Improvements:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n1. Incident Response\n   - 24/7 IR team on call\n   - Tabletop exercises quarterly\n   - Threat hunting program\n   - Intelligence sharing (ISAC)\n\n2. User Training\n   - Phishing simulations\n   - Security awareness training\n   - Reporting suspicious activity\n\n3. Third-Party Risk\n   - Vendor security assessments\n   - Supply chain monitoring\n   - NDA enforcement\n\nRegulatory Impact:\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n- DoD notification required (DFARS 252.204-7012)\n- CMMC Level 3 compliance accelerated\n- Congressional briefing\n- Export license reviews\n```\n\n---\n\n## Appendices\n\n---\n\n### Appendix A: Forensic Command Reference\n\n```markdown\nFORENSIC COMMAND QUICK REFERENCE\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nWindows Live Response\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n# System Information\nsysteminfo &gt; systeminfo.txt\nwmic os get /format:list\nwmic computersystem get /format:list\n\n# Processes\ntasklist /v &gt; processes.txt\nwmic process list full &gt; wmic_process.txt\n\n# Network\nnetstat -ano &gt; connections.txt\nnetstat -rn &gt; routing_table.txt\nipconfig /displaydns &gt; dns_cache.txt\narp -a &gt; arp_cache.txt\n\n# Services\nnet start &gt; services.txt\nsc query &gt; sc_query.txt\n\n# Users\nnet user &gt; users.txt\nnet localgroup administrators &gt; admins.txt\nwhoami /all &gt; user_privileges.txt\n\n# Registry\nreg export HKLM\\SAM sam.reg\nreg export HKLM\\SYSTEM system.reg\nreg export HKLM\\SOFTWARE software.reg\nreg export HKCU\\NTUSER.DAT ntuser.reg\n\nLinux Live Response\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n# System\nuname -a &gt; system.txt\ncat /etc/os-release\ndate &gt; date.txt\nuptime &gt; uptime.txt\n\n# Processes\nps auxf &gt; processes.txt\npstree &gt; process_tree.txt\nlsof &gt; open_files.txt\n\n# Network\nnetstat -tupan &gt; connections.txt\nss -tulpn &gt; sockets.txt\niptables-save &gt; firewall.txt\narp -a &gt; arp.txt\n\n# Users\nw &gt; who.txt\nlast &gt; logins.txt\ncat /etc/passwd &gt; users.txt\ncat /etc/shadow &gt; shadow.txt\n\n# Memory\n# LiME\ninsmod lime.ko \"path=memory.lime format=lime\"\n# fmem\ndd if=/dev/fmem of=memory.raw bs=1M\n\nImaging Commands\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n# dd (Linux)\ndd if=/dev/sda of=image.dd bs=4M conv=noerror,sync status=progress\n\n# dd with compression\ndd if=/dev/sda bs=4M | gzip -c &gt; image.dd.gz\n\n# dd over network (receiver)\nnc -l -p 9999 | dd of=image.dd bs=4M\n\n# dd over network (sender)\ndd if=/dev/sda bs=4M | nc 192.168.1.100 9999\n\n# dcfldd (with hash)\ndcfldd if=/dev/sda of=image.dd bs=4M hash=sha256 hashlog=hash.txt\n\n# EWF (EnCase) format\newfacquire /dev/sda -t image.E01 -u\n\nThe Sleuth Kit\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n# Partition table\nmmls image.dd\n\n# File system info\nfsstat -o 2048 image.dd\n\n# List files\nfls -o 2048 -r image.dd &gt; file_list.txt\n\n# List deleted files\nfls -o 2048 -d -r image.dd &gt; deleted_files.txt\n\n# Get file by inode\nicat -o 2048 image.dd 12345 &gt; file.bin\n\n# Timeline\nils -o 2048 -m / -i image.dd &gt; bodyfile.txt\nmactime -b bodyfile.txt -d &gt; timeline.csv\n\nVolatility (Memory Analysis)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n# Identify profile\nvol.py -f memory.raw imageinfo\n\n# Process listing\nvol.py -f memory.raw --profile=Win10x64 pslist\nvol.py -f memory.raw --profile=Win10x64 psscan\nvol.py -f memory.raw --profile=Win10x64 pstree\n\n# Network\nvol.py -f memory.raw --profile=Win10x64 netscan\nvol.py -f memory.raw --profile=Win10x64 connections\n\n# DLLs\nvol.py -f memory.raw --profile=Win10x64 dlllist\nvol.py -f memory.raw --profile=Win10x64 ldrmodules\n\n# Process memory\nvol.py -f memory.raw --profile=Win10x64 memdump -p 1234 -D dumps/\n\n# Registry\nvol.py -f memory.raw --profile=Win10x64 hivelist\nvol.py -f memory.raw --profile=Win10x64 printkey -K \"ControlSet001\\Control\"\n\n# Malware\nvol.py -f memory.raw --profile=Win10x64 malfind\nvol.py -f memory.raw --profile=Win10x64 apihooks\nvol.py -f memory.raw --profile=Win10x64 timers\n\nPlaso (Timeline)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n# Create timeline\nlog2timeline.py --storage-file case.plaso image.dd\n\n# Add additional sources\nlog2timeline.py --storage-file case.plaso --append event_logs.evtx\n\n# Generate output\npsort.py -o l2tcsv -w timeline.csv case.plaso\n\n# Filter\npsort.py -o l2tcsv -w filtered.csv \"date &gt; '2023-01-01'\"\n\nYARA\n\u2500\u2500\u2500\u2500\n# Compile rules\nyara -c rules.yar\n\n# Scan file\nyara rules.yar suspicious.exe\n\n# Scan directory\nyara -r rules.yar /path/to/dir/\n\n# Memory scan\nyara rules.yar /proc/1234/mem\n\nRegRipper (Registry)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n# Parse hive\nrip.pl -r NTUSER.DAT -p all &gt; ntuser.txt\n\n# Specific plugin\nrip.pl -r SYSTEM -p usbstor &gt; usb_history.txt\n\n# All plugins\nrip.pl -r SAM -p &gt; sam_analysis.txt\n\nForemost (Carving)\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n# Basic carving\nforemost -i image.dd -o output/\n\n# Specific file types\nforemost -t jpg,pdf,doc -i image.dd -o output/\n\n# Custom config\nforemost -c foremost.conf -i image.dd -o output/\n```\n\n---\n\n### Appendix B: Artifact Cheat Sheets\n\n```markdown\nWINDOWS ARTIFACTS CHEAT SHEET\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Artifact           \u2502 Location                         \u2502 Forensic Value      \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Prefetch           \u2502 C:\\Windows\\Prefetch\\*.pf        \u2502 Program execution   \u2502\n\u2502 Amcache            \u2502 C:\\Windows\\AppCompat\\Programs\\   \u2502 App installation    \u2502\n\u2502                    \u2502 Amcache.hve                       \u2502                     \u2502\n\u2502 Shimcache          \u2502 Registry: AppCompatCache         \u2502 Program execution   \u2502\n\u2502 USN Journal        \u2502 $UsnJrnl (on volume)             \u2502 File activity       \u2502\n\u2502 $LogFile           \u2502 $LogFile (on volume)             \u2502 NTFS journal        \u2502\n\u2502 MFT                \u2502 $MFT (on volume)                 \u2502 All files metadata  \u2502\n\u2502 Event Logs         \u2502 C:\\Windows\\System32\\winevt\\Logs\\ \u2502 System events       \u2502\n\u2502                    \u2502 *.evtx                            \u2502                     \u2502\n\u2502 Registry Hives     \u2502 C:\\Windows\\System32\\config\\      \u2502 System config       \u2502\n\u2502 NTUSER.DAT         \u2502 C:\\Users\\[user]\\NTUSER.DAT       \u2502 User config         \u2502\n\u2502 UsrClass.dat       \u2502 C:\\Users\\[user]\\AppData\\Local\\   \u2502 User config         \u2502\n\u2502                    \u2502 Microsoft\\Windows\\UsrClass.dat   \u2502                     \u2502\n\u2502 Recycle Bin        \u2502 C:\\$Recycle.Bin\\[SID]\\$I*        \u2502 Deleted files       \u2502\n\u2502 LNK Files          \u2502 C:\\Users\\[user]\\Recent\\*.lnk     \u2502 File access         \u2502\n\u2502 Jump Lists         \u2502 C:\\Users\\[user]\\AppData\\Roaming\\ \u2502 Application usage   \u2502\n\u2502                    \u2502 Microsoft\\Windows\\Recent\\         \u2502                     \u2502\n\u2502                    \u2502 AutomaticDestinations\\*.ms        \u2502                     \u2502\n\u2502 Shellbags          \u2502 Registry: BagMRU, Bags            \u2502 Folder views        \u2502\n\u2502 USBSTOR            \u2502 Registry: USBSTOR                \u2502 USB device history  \u2502\n\u2502 Setupapi.log       \u2502 C:\\Windows\\INF\\setupapi.dev.log  \u2502 Device installation \u2502\n\u2502 Browser History    \u2502 C:\\Users\\[user]\\AppData\\Local\\   \u2502 Web activity        \u2502\n\u2502                    \u2502 [Browser]\\User Data\\Default\\      \u2502                     \u2502\n\u2502                    \u2502 History                           \u2502                     \u2502\n\u2502 Browser Cache      \u2502 C:\\Users\\[user]\\AppData\\Local\\   \u2502 Cached content      \u2502\n\u2502                    \u2502 [Browser]\\User Data\\Default\\Cache\u2502                     \u2502\n\u2502 Browser Cookies    \u2502 C:\\Users\\[user]\\AppData\\Local\\   \u2502 Cookies             \u2502\n\u2502                    \u2502 [Browser]\\User Data\\Default\\      \u2502                     \u2502\n\u2502                    \u2502 Cookies                           \u2502                     \u2502\n\u2502 Downloads          \u2502 C:\\Users\\[user]\\Downloads\\*       \u2502 Downloaded files    \u2502\n\u2502 Recent Documents   \u2502 Registry: RecentDocs              \u2502 Recent files        \u2502\n\u2502 Typed URLs         \u2502 Registry: TypedURLs               \u2502 URLs typed          \u2502\n\u2502 Run MRU            \u2502 Registry: RunMRU                  \u2502 Run dialog commands \u2502\n\u2502 Windows Search     \u2502 C:\\ProgramData\\Microsoft\\Search\\  \u2502 File index          \u2502\n\u2502                    \u2502 Data\\Applications\\Windows\\        \u2502                     \u2502\n\u2502                    \u2502 Windows.edb                       \u2502                     \u2502\n\u2502 Thumbcache         \u2502 C:\\Users\\[user]\\AppData\\Local\\   \u2502 Image thumbnails    \u2502\n\u2502                    \u2502 Microsoft\\Windows\\Explorer\\       \u2502                     \u2502\n\u2502                    \u2502 thumbcache_*.db                   \u2502                     \u2502\n\u2502 Tasks              \u2502 C:\\Windows\\System32\\Tasks\\       \u2502 Scheduled tasks     \u2502\n\u2502                    \u2502 C:\\Windows\\Tasks\\                 \u2502                     \u2502\n\u2502 Print Spool        \u2502 C:\\Windows\\System32\\spool\\PRINTERS\u2502 Printed documents   \u2502\n\u2502 PowerShell History \u2502 C:\\Users\\[user]\\AppData\\Roaming\\  \u2502 PowerShell commands \u2502\n\u2502                    \u2502 Microsoft\\Windows\\PowerShell\\     \u2502                     \u2502\n\u2502                    \u2502 PSReadLine\\ConsoleHost_history.txt\u2502                     \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\nLINUX ARTIFACTS CHEAT SHEET\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Artifact           \u2502 Location                         \u2502 Forensic Value      \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Authentication     \u2502 /var/log/auth.log                \u2502 Logins, sudo        \u2502\n\u2502                    \u2502 /var/log/secure                  \u2502                     \u2502\n\u2502 System Logs        \u2502 /var/log/syslog                  \u2502 System events       \u2502\n\u2502                    \u2502 /var/log/messages                 \u2502                     \u2502\n\u2502 Kernel Logs        \u2502 /var/log/kern.log                \u2502 Kernel messages     \u2502\n\u2502 Boot Log           \u2502 /var/log/boot.log                 \u2502 Boot process        \u2502\n\u2502 Cron Log           \u2502 /var/log/cron.log                 \u2502 Scheduled tasks     \u2502\n\u2502 Mail Log           \u2502 /var/log/mail.log                 \u2502 Email activity      \u2502\n\u2502 Apache Logs        \u2502 /var/log/apache2/access.log      \u2502 Web server access   \u2502\n\u2502                    \u2502 /var/log/apache2/error.log        \u2502                     \u2502\n\u2502 MySQL Logs         \u2502 /var/log/mysql/error.log         \u2502 Database activity   \u2502\n\u2502 Bash History       \u2502 ~/.bash_history                   \u2502 Commands executed   \u2502\n\u2502                    \u2502 ~/.zsh_history                    \u2502                     \u2502\n\u2502                    \u2502 ~/.history                        \u2502                     \u2502\n\u2502 User Accounts      \u2502 /etc/passwd                       \u2502 User list           \u2502\n\u2502 Password Hashes    \u2502 /etc/shadow                       \u2502 Password info       \u2502\n\u2502 Group Info         \u2502 /etc/group                        \u2502 Group memberships   \u2502\n\u2502 Sudoers            \u2502 /etc/sudoers                      \u2502 Sudo permissions    \u2502\n\u2502                    \u2502 /etc/sudoers.d/*                  \u2502                     \u2502\n\u2502 SSH Keys           \u2502 ~/.ssh/id_rsa*                    \u2502 Authentication keys \u2502\n\u2502                    \u2502 ~/.ssh/authorized_keys             \u2502                     \u2502\n\u2502 SSH Known Hosts    \u2502 ~/.ssh/known_hosts                 \u2502 Connected systems   \u2502\n\u2502 Systemd Journal    \u2502 /var/log/journal/                 \u2502 Systemd logs        \u2502\n\u2502 Last Logins        \u2502 /var/log/wtmp                      \u2502 Login history       \u2502\n\u2502 Failed Logins      \u2502 /var/log/btmp                      \u2502 Failed attempts     \u2502\n\u2502 Current Logins     \u2502 /var/run/utmp                      \u2502 Currently logged in \u2502\n\u2502 Process Info       \u2502 /proc/[pid]/                       \u2502 Process details     \u2502\n\u2502 Mounted FS         \u2502 /etc/fstab                         \u2502 Filesystem mounts   \u2502\n\u2502                    \u2502 /proc/mounts                       \u2502                     \u2502\n\u2502 Network Config     \u2502 /etc/network/interfaces           \u2502 Network settings    \u2502\n\u2502                    \u2502 /etc/sysconfig/network-scripts/   \u2502                     \u2502\n\u2502 DNS Config         \u2502 /etc/resolv.conf                   \u2502 DNS servers         \u2502\n\u2502 Hosts File         \u2502 /etc/hosts                        \u2502 Host mappings       \u2502\n\u2502 Firewall Rules     \u2502 /etc/iptables/rules.v4            \u2502 Firewall config     \u2502\n\u2502                    \u2502 /etc/iptables/rules.v6            \u2502                     \u2502\n\u2502 Cron Jobs          \u2502 /etc/crontab                       \u2502 System cron         \u2502\n\u2502                    \u2502 /etc/cron.d/*                      \u2502                     \u2502\n\u2502                    \u2502 /var/spool/cron/crontabs/*        \u2502 User cron           \u2502\n\u2502 System Info        \u2502 /etc/os-release                    \u2502 OS version          \u2502\n\u2502                    \u2502 /etc/issue                         \u2502                     \u2502\n\u2502                    \u2502 /etc/redhat-release                \u2502                     \u2502\n\u2502 Installed Packages \u2502 /var/log/dpkg.log                  \u2502 Package history     \u2502\n\u2502                    \u2502 /var/log/yum.log                   \u2502                     \u2502\n\u2502                    \u2502 /var/log/apt/                      \u2502                     \u2502\n\u2502 Application Config \u2502 /etc/[app]/*                       \u2502 App configuration   \u2502\n\u2502                    \u2502 ~/.config/[app]/*                  \u2502                     \u2502\n\u2502 Environment        \u2502 /etc/profile                       \u2502 Global environment  \u2502\n\u2502                    \u2502 ~/.bashrc                          \u2502 User environment    \u2502\n\u2502                    \u2502 ~/.profile                         \u2502                     \u2502\n\u2502 System Services    \u2502 /etc/init.d/                       \u2502 Init scripts        \u2502\n\u2502                    \u2502 /etc/systemd/system/               \u2502 Systemd units       \u2502\n\u2502                    \u2502 /lib/systemd/system/               \u2502                     \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\nMACOS ARTIFACTS CHEAT SHEET\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Artifact           \u2502 Location                         \u2502 Forensic Value      \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 Unified Logs       \u2502 /private/var/log/                \u2502 System logs         \u2502\n\u2502                    \u2502 (use 'log show' command)         \u2502                     \u2502\n\u2502 System Log         \u2502 /var/log/system.log              \u2502 Legacy syslog       \u2502\n\u2502 Install History    \u2502 /Library/Receipts/               \u2502 Software installed  \u2502\n\u2502                    \u2502 /var/db/receipts/                \u2502                     \u2502\n\u2502 User Data          \u2502 /Users/[user]/                   \u2502 User files          \u2502\n\u2502 Keychains          \u2502 ~/Library/Keychains/             \u2502 Passwords, keys     \u2502\n\u2502 Safari History     \u2502 ~/Library/Safari/History.db      \u2502 Web history         \u2502\n\u2502 Safari Downloads   \u2502 ~/Library/Safari/Downloads.plist \u2502 Downloaded files    \u2502\n\u2502 Safari Extensions  \u2502 ~/Library/Safari/Extensions/     \u2502 Browser extensions  \u2502\n\u2502 Mail Data          \u2502 ~/Library/Mail/                  \u2502 Emails              \u2502\n\u2502 Messages           \u2502 ~/Library/Messages/chat.db       \u2502 iMessage history    \u2502\n\u2502 Contacts           \u2502 ~/Library/Application Support/   \u2502 Contact list        \u2502\n\u2502                    \u2502 AddressBook/                      \u2502                     \u2502\n\u2502 Calendar           \u2502 ~/Library/Calendars/             \u2502 Calendar events     \u2502\n\u2502 Notes              \u2502 ~/Library/Group Containers/      \u2502 Notes               \u2502\n\u2502                    \u2502 group.com.apple.notes/            \u2502                     \u2502\n\u2502 Reminders          \u2502 ~/Library/Reminders/             \u2502 Reminders           \u2502\n\u2502 Spotlight Index    \u2502 /.Spotlight-V100/                 \u2502 File index          \u2502\n\u2502 Time Machine       \u2502 /Volumes/[Backup]/Backups.backupdb\u2502 Backups             \u2502\n\u2502                    \u2502 /[Computer]/                      \u2502                     \u2502\n\u2502 Application Data   \u2502 ~/Library/Application Support/   \u2502 App data            \u2502\n\u2502 Preferences        \u2502 ~/Library/Preferences/           \u2502 App settings        \u2502\n\u2502 Caches             \u2502 ~/Library/Caches/                 \u2502 Cached data         \u2502\n\u2502 Cookies            \u2502 ~/Library/Cookies/                \u2502 Browser cookies     \u2502\n\u2502 Recent Items       \u2502 ~/Library/Preferences/           \u2502 Recent files        \u2502\n\u2502                    \u2502 com.apple.recentitems.plist       \u2502                     \u2502\n\u2502 Quick Look         \u2502 ~/Library/QuickLook/              \u2502 Quick Look plugins  \u2502\n\u2502 Screen Savers      \u2502 ~/Library/Screen Savers/          \u2502 Screensaver files   \u2502\n\u2502 Fonts              \u2502 ~/Library/Fonts/                  \u2502 Installed fonts     \u2502\n\u2502 Spotlight Comments \u2502 File metadata                      \u2502 User tags           |\n\u2502 Trash              \u2502 ~/.Trash/                          \u2502 Deleted files       \u2502\n\u2502 Sleep Images      \u2502 /private/var/vm/sleepimage        \u2502 Memory on sleep     \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n---\n\n### Appendix C: Sample Forensic Report Template\n\n```markdown\nFORENSIC EXAMINATION REPORT\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nCASE INFORMATION\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nCase Number: [CASE-YYYY-NNNN]\nExaminer: [Name]\nDate of Report: [YYYY-MM-DD]\nRequesting Party: [Organization]\nClassification: [Confidential/Privileged/etc.]\n\n1. EXECUTIVE SUMMARY\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n[Brief overview - 2-3 paragraphs maximum]\n\n2. CASE BACKGROUND\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n[Incident description, investigation scope, legal authority]\n\n3. EVIDENCE LIST\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Item ID \u2502 Description     \u2502 Source       \u2502 Hash Value          \u2502\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524\n\u2502 EX-001  \u2502                 \u2502              \u2502                     \u2502\n\u2502 EX-002  \u2502                 \u2502              \u2502                     \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n4. EXAMINATION METHODOLOGY\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n[Tools used, procedures followed, acquisition methods]\n\n5. TECHNICAL FINDINGS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n[Detailed findings organized by evidence item]\n\n   5.1 [Finding Category 1]\n   5.2 [Finding Category 2]\n   5.3 Timeline of Events\n\n6. ANALYSIS &amp; INTERPRETATION\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n[Correlation of findings, significance, alternative explanations]\n\n7. CONCLUSIONS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n[Summary of findings, answers to specific questions, recommendations]\n\n8. LIMITATIONS\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n[Constraints, unanswered questions, additional analysis needed]\n\n9. APPENDICES\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nA. Chain of Custody\nB. Tool Verification\nC. Raw Data Extracts\nD. Glossary\nE. Examiner Qualifications\n\n_________________________\n[Examiner Name], [Credentials]\n[Organization]\nDate: [YYYY-MM-DD]\n```\n\n---\n\n### Appendix D: Glossary of Terms\n\n```markdown\nGLOSSARY OF FORENSIC TERMS\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nA\n\u2500\nAccess Time: Timestamp indicating when a file was last accessed\nAlternate Data Stream (ADS): NTFS feature allowing multiple data streams in one file\nAmcache: Windows artifact tracking program execution and installation\nAnti-Forensics: Techniques used to hinder forensic analysis\nAPT (Advanced Persistent Threat): Sophisticated, long-term cyber attack\nArtifact: Digital object of forensic interest\nAutopsy: Open source digital forensics platform\n\nB\n\u2500\nBash History: File recording commands executed in Linux/Unix shell\nBitLocker: Windows full disk encryption\nBitmap: Data structure tracking used/free space in file systems\nBlockchain: Distributed ledger technology underlying cryptocurrencies\nBootkit: Malware infecting master boot record\nBrowser History: Record of websites visited\nBrute Force: Attack trying all possible combinations\n\nC\n\u2500\nC2 (Command and Control): Server controlling compromised systems\nCache: Temporary storage for frequently accessed data\nCarving: Recovering files without file system metadata\nChain of Custody: Documentation of evidence handling\nCheckm8: Hardware exploit for iOS devices\nChip-off: Physical removal of memory chip for analysis\nCloud Forensics: Investigation of cloud computing environments\nCluster: Basic unit of file storage (group of sectors)\nCobalt Strike: Penetration testing tool, often abused by attackers\nCold Boot Attack: Memory recovery from chilled RAM modules\nContainer: Isolated environment (Docker, etc.)\nCookie: Small file storing web browsing data\nCron: Linux task scheduler\nCryptocurrency: Digital currency using cryptography\n\nD\n\u2500\nData Breach: Unauthorized data access or exfiltration\nData Exfiltration: Unauthorized data transfer\nData Remanence: Residual data after deletion\ndd: Unix command for bit-for-bit copying\nDead Analysis: Forensic analysis of powered-off system\nDeleted File: File removed from file system index\nDisk Image: Bit-for-bit copy of storage media\nDLL (Dynamic Link Library): Windows shared library\nDLL Injection: Malware technique inserting code into processes\nDNS Tunneling: Data exfiltration via DNS queries\nDwell Time: Time between compromise and detection\n\nE\n\u2500\nE01: EnCase evidence file format\nECU (Engine Control Unit): Vehicle computer\nEDR (Endpoint Detection and Response): Security monitoring tool\nEncryption: Data scrambling requiring key for access\nEnCase: Commercial forensic platform\nEntropy: Measure of randomness in data\nEvent Log: System record of significant occurrences\nEvent ID: Numeric identifier for Windows events\nExecutive Summary: Brief report overview for decision-makers\nExpert Witness: Qualified professional testifying in court\nEXT: Linux file system (ext2, ext3, ext4)\n\nF\n\u2500\nFaraday Bag: Container blocking electromagnetic signals\nFAT (File Allocation Table): Legacy file system\nFile Header: Identifying bytes at file beginning\nFile Signature: Unique pattern identifying file type\nFile System: Method of organizing files on storage\nFirmware: Software embedded in hardware\nFirst Responder: Initial person at digital crime scene\nForensic Copy: Bit-for-bit duplicate of evidence\nForensic Image: Complete copy of storage media\nForemost: File carving tool\nFTK (Forensic Toolkit): Commercial forensic platform\n\nG\n\u2500\nGPT (GUID Partition Table): Modern partition scheme\nGPS (Global Positioning System): Satellite-based location\nGutmann Method: 35-pass data wiping technique\n\nH\n\u2500\nHardware Write Blocker: Device preventing writes to evidence\nHash: Cryptographic checksum verifying data integrity\nHDD (Hard Disk Drive): Magnetic storage device\nHex Editor: Tool for viewing/editing raw data\nHibernation File: Memory saved to disk during hibernation\nHidden Partition: Partition not visible to OS\nHive: Windows registry file\n\nI\n\u2500\nIaaS (Infrastructure as a Service): Cloud computing model\nICMP: Internet Control Message Protocol (ping)\nIOC (Indicator of Compromise): Evidence of intrusion\nIoT (Internet of Things): Networked smart devices\nIP Address: Internet Protocol address\nIP Spoofing: Falsifying IP address\nImage: Forensic copy of storage media\nInode: Linux data structure describing file\nInsider Threat: Threat from within organization\n\nJ\n\u2500\nJournal: File system feature tracking changes\nJTAG: Debug interface for embedded devices\nJump List: Windows feature showing recent items\n\nK\n\u2500\nKernel: Core of operating system\nKeychain: macOS password storage\nKubernetes: Container orchestration platform\n\nL\n\u2500\nLateral Movement: Attacker moving through network\nLiME: Linux Memory Extractor\nLive Analysis: Forensic analysis of running system\nLNK File: Windows shortcut file\nLog File: File recording events\nLog Tampering: Modifying logs to hide activity\nLogical Acquisition: Copying only active files\nLSB (Least Significant Bit): Steganography technique\n\nM\n\u2500\nMAC Times: File timestamps (Modified, Accessed, Created)\nMalware: Malicious software\nMaster File Table (MFT): NTFS file index\nMBR (Master Boot Record): Legacy partition scheme\nMemory Dump: Contents of RAM saved to file\nMemory Forensics: Analysis of RAM contents\nMFT: See Master File Table\nMFT Entry: Record in Master File Table\nMFT Record: See MFT Entry\nMFT Sequence Number: Counter for MFT entry reuse\nMLAT (Mutual Legal Assistance Treaty): International evidence sharing\nMobile Forensics: Investigation of mobile devices\nMutex: Malware artifact for preventing multiple instances\n\nN\n\u2500\nNAND Flash: Storage used in SSDs and mobile devices\nNetFlow: Network traffic summary protocol\nNetwork Forensics: Analysis of network traffic\nNon-Resident Attribute: File data stored outside MFT\nNTFS (New Technology File System): Windows file system\n\nO\n\u2500\nOBD-II: Vehicle diagnostic port\nObfuscation: Making code difficult to understand\nOpenIOC: Open format for sharing IOCs\nOSINT (Open Source Intelligence): Intelligence from public sources\n\nP\n\u2500\nPaaS (Platform as a Service): Cloud computing model\nPacket: Unit of network data\nPartition: Logical division of storage\nPCAP: Packet capture file format\nPE File: Windows Portable Executable format\nPhishing: Fraudulent attempt to obtain credentials\nPhysical Acquisition: Bit-for-bit copy of storage\nPlaso: Timeline creation tool (log2timeline)\nPrefetch: Windows artifact tracking program execution\nProcess Hollowing: Malware injection technique\n\nR\n\u2500\nRAID (Redundant Array of Independent Disks): Multiple drives as one\nRAM (Random Access Memory): Volatile system memory\nRansomware: Malware encrypting files for ransom\nRegistry: Windows configuration database\nRegistry Hive: Individual registry file\nResident Attribute: File data stored in MFT\nRootkit: Malware hiding its presence\n\nS\n\u2500\nSaaS (Software as a Service): Cloud computing model\nSandbox: Isolated environment for malware analysis\nSector: Smallest addressable storage unit (usually 512 bytes)\nSHA (Secure Hash Algorithm): Hash function family\nShellbags: Windows folder view settings\nShimcache: Windows program execution artifact\nSignature: Unique pattern identifying file type\nSlack Space: Unused space between file end and cluster end\nSnapshot: Point-in-time copy of system state\nSSD (Solid State Drive): Flash-based storage\nSteganography: Hiding data within other data\nStrings: Printable text extracted from binary files\nSuper Timeline: Combined timeline from multiple sources\n\nT\n\u2500\nTCP/IP: Internet protocol suite\nThreat Intelligence: Information about threats\nTime Machine: macOS backup feature\nTimeline: Chronological sequence of events\nTimestamp: Time value attached to events\nTimestomping: Modifying timestamps to hide activity\nTRIM: SSD command marking blocks as unused\nTSK (The Sleuth Kit): Open source forensic tools\n\nU\n\u2500\nUEFI (Unified Extensible Firmware Interface): Modern firmware\nUnallocated Space: Storage not assigned to files\nUnified Logs: macOS comprehensive logging system\nUSB Device History: Record of connected USB devices\nUSN Journal: NTFS change journal\n\nV\n\u2500\nVMDK: VMware virtual disk format\nVHDX: Hyper-V virtual disk format\nVM (Virtual Machine): Software-emulated computer\nVolatility: Memory forensics framework\nVolume: Storage unit with file system\n\nW\n\u2500\nWAL (Write-Ahead Logging): SQLite journal\nWallet: Cryptocurrency key storage\nWear Leveling: SSD technique distributing writes\nWindows Event Log: Windows logging system\nWrite Blocker: Device preventing writes to evidence\n\nY\n\u2500\nYARA: Pattern matching tool for malware detection\n```\n\n---\n\n### Appendix E: Lab Exercises\n\n```markdown\nFORENSIC LAB EXERCISES\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nExercise 1: Creating a Forensic Image\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nObjective: Create a forensic image of a USB drive\nTools: dd (Linux), FTK Imager (Windows)\n\nSteps:\n1. Connect USB drive (non-evidence, practice only)\n2. Identify device name (Linux: lsblk, Windows: disk management)\n3. Calculate SHA256 hash of original\n4. Create image using dd or FTK Imager\n5. Verify image hash matches original\n6. Mount image read-only and verify contents\n\nExercise 2: File Carving\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nObjective: Recover deleted files from disk image\nTools: foremost, scalpel, photorec\n\nSteps:\n1. Download practice disk image with deleted files\n2. Run foremost with default configuration\n3. Review recovered files\n4. Try different file types (jpg, pdf, doc)\n5. Compare recovery rates with different tools\n\nExercise 3: Windows Registry Analysis\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nObjective: Extract user activity from registry hives\nTools: RegRipper, Registry Explorer\n\nFiles needed: NTUSER.DAT, SAM, SYSTEM (from practice VM)\n\nTasks:\n1. Extract USB device history\n2. Find recently accessed documents\n3. List installed programs\n4. Identify user accounts\n5. Find typed URLs\n\nExercise 4: Memory Analysis\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nObjective: Analyze memory dump for malware indicators\nTools: Volatility\n\nFiles needed: Practice memory dump (from malware.iaik.tugraz.at)\n\nTasks:\n1. Identify correct profile\n2. List running processes\n3. Find hidden processes (pslist vs psscan)\n4. Extract network connections\n5. Run malfind to detect injected code\n6. Dump suspicious processes\n\nExercise 5: Timeline Creation\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nObjective: Create super timeline from disk image\nTools: Plaso (log2timeline)\n\nSteps:\n1. Run log2timeline on practice image\n2. Generate CSV timeline\n3. Filter for specific date range\n4. Identify file access patterns\n5. Correlate with registry artifacts\n6. Create visualization of timeline\n\nExercise 6: Network Traffic Analysis\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nObjective: Analyze PCAP for malicious activity\nTools: Wireshark, tcpdump, NetworkMiner\n\nFiles needed: Malicious PCAP (from malware-traffic-analysis.net)\n\nTasks:\n1. Identify top talkers\n2. Extract HTTP objects\n3. Find DNS queries\n4. Reconstruct TCP streams\n5. Identify malware C2 traffic\n6. Extract IOCs\n\nExercise 7: Malware Static Analysis\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nObjective: Perform static analysis of malware sample\nTools: PEview, Detect It Easy, strings, pestudio\n\nFiles needed: Malware sample (use safely in sandbox)\n\nTasks:\n1. Calculate hashes\n2. Identify compiler/packer\n3. Extract strings\n4. Analyze imports\n5. Check section entropy\n6. Identify suspicious APIs\n7. Create YARA rule\n\nExercise 8: Mobile Forensics\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nObjective: Extract data from Android backup\nTools: Android SDK, SQLite Browser, ABE (Android Backup Extractor)\n\nFiles needed: Android backup (.ab file)\n\nTasks:\n1. Convert backup to tar\n2. Extract SMS database\n3. Parse contacts\n4. Analyze call logs\n5. Extract WhatsApp messages\n6. Create timeline of activity\n\nExercise 9: Log Analysis\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nObjective: Identify security events in logs\nTools: grep, awk, Python, ELK stack (optional)\n\nFiles needed: Apache access logs, auth.log\n\nTasks:\n1. Identify failed SSH attempts\n2. Find successful logins\n3. Detect brute force patterns\n4. Analyze web server requests\n5. Identify SQL injection attempts\n6. Create timeline of attacks\n\nExercise 10: Report Writing\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nObjective: Write professional forensic report based on exercise findings\n\nRequirements:\n1. Executive summary\n2. Evidence list\n3. Methodology\n4. Technical findings\n5. Timeline\n6. Conclusions\n7. Limitations\n8. Appendices\n\nEvaluation criteria:\n- Clarity and organization\n- Technical accuracy\n- Appropriate detail level\n- Proper formatting\n- Objective tone\n```\n\n---\n\n### Appendix F: Practice Scenarios\n\n```markdown\nPRACTICE FORENSIC SCENARIOS\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nScenario 1: Insider Threat Investigation\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nBackground: Employee resigned unexpectedly. Company suspects data theft.\n\nEvidence Provided:\n- Company laptop image (Windows 10)\n- Email server logs (last 30 days)\n- USB device logs\n- Employee's Slack messages\n\nTask: Determine if data was exfiltrated before resignation\n\nKey Questions:\n1. What files were accessed in the last two weeks?\n2. Was any external storage connected?\n3. Were emails sent to personal accounts?\n4. What was the timeline of events?\n5. Is there evidence of intent?\n\nScenario 2: Ransomware Incident Response\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nBackground: Company reports files encrypted with .lockbit extension.\n\nEvidence Provided:\n- Memory dump from affected workstation\n- Network traffic capture\n- Windows event logs\n- Encrypted files (samples)\n\nTask: Determine entry point and scope of compromise\n\nKey Questions:\n1. How did the malware enter?\n2. What was the initial execution time?\n3. What systems were affected?\n4. What data was exfiltrated (if any)?\n5. Can we identify the ransomware variant?\n\nScenario 3: Phishing Investigation\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nBackground: CFO received suspicious email and clicked link.\n\nEvidence Provided:\n- Email (EML file)\n- Browser history\n- Network traffic\n- Memory dump\n\nTask: Determine if credentials were compromised\n\nKey Questions:\n1. Was the email malicious?\n2. What happened after clicking the link?\n3. Were credentials entered?\n4. Was malware downloaded?\n5. What is the IOC for this campaign?\n\nScenario 4: Mobile Device Investigation\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nBackground: Phone seized in criminal investigation.\n\nEvidence Provided:\n- Android phone backup\n- iTunes backup (iOS for comparison)\n\nTask: Extract location history and communications\n\nKey Questions:\n1. Where was the user on specific dates?\n2. Who were they communicating with?\n3. What apps were used?\n4. Can we recover deleted messages?\n5. What photos/videos are present?\n\nScenario 5: Network Intrusion\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nBackground: IDS alerted on suspicious outbound connections.\n\nEvidence Provided:\n- Full PCAP (24 hours)\n- Firewall logs\n- Proxy logs\n- DNS logs\n\nTask: Determine if compromise occurred and scope\n\nKey Questions:\n1. Is there evidence of C2 communication?\n2. What systems are affected?\n3. What data was exfiltrated?\n4. What was the attack vector?\n5. How long has the attacker been present?\n\nScenario 6: Cryptocurrency Tracing\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nBackground: Ransomware payment traced to Bitcoin address.\n\nEvidence Provided:\n- Bitcoin address\n- Transaction history (blockchain data)\n- Exchange records (limited)\n\nTask: Trace funds and identify potential owner\n\nKey Questions:\n1. Where did the funds originate?\n2. Were mixers used?\n3. Did funds go to exchanges?\n4. Can we cluster related addresses?\n5. What is the money flow pattern?\n\nScenario 7: Cloud Investigation\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nBackground: Data breach in AWS environment.\n\nEvidence Provided:\n- CloudTrail logs\n- S3 access logs\n- VPC Flow Logs\n- CloudWatch logs\n\nTask: Determine how breach occurred and what was accessed\n\nKey Questions:\n1. What API calls were made?\n2. Was there unauthorized access?\n3. What data was accessed/downloaded?\n4. Were credentials compromised?\n5. What is the timeline of events?\n\nScenario 8: Anti-Forensics Detection\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nBackground: Suspect may have attempted to hide evidence.\n\nEvidence Provided:\n- Disk image\n- Memory dump\n- Registry hives\n\nTask: Detect anti-forensic techniques\n\nKey Questions:\n1. Was data wiped? (look for wiping patterns)\n2. Were timestamps manipulated?\n3. Are there hidden partitions/streams?\n4. Was steganography used?\n5. Are there signs of log tampering?\n\nScenario 9: IoT Device Investigation\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nBackground: Smart home device may contain evidence.\n\nEvidence Provided:\n- Smart thermostat data\n- Smart lock logs\n- Voice assistant history\n- Router logs\n\nTask: Determine occupancy patterns and activities\n\nKey Questions:\n1. When was the residence occupied?\n2. Who accessed the home and when?\n3. What voice commands were given?\n4. Were there unusual network activities?\n5. Can we correlate with other evidence?\n\nScenario 10: APT Investigation\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nBackground: Defense contractor suspects nation-state intrusion.\n\nEvidence Provided:\n- Full disk images (multiple systems)\n- Network logs (6 months)\n- Email archives\n- Memory dumps\n\nTask: Determine scope, attribution, and data stolen\n\nKey Questions:\n1. What was the initial access vector?\n2. How long have they been present?\n3. What data was targeted?\n4. What tools were used?\n5. Can we attribute to known APT group?\n```\n\n---\n", "creation_timestamp": "2026-08-25T16:14:14.155169Z"}