Skip to content
Incident Response & Forensics — Complete Guide for Beginners

Incident Response & Forensics — Complete Guide for Beginners

DodaTech Updated Jun 7, 2026 12 min read

Incident response (IR) is the systematic approach to handling security breaches — detecting the attack, containing the damage, eradicating the threat, and recovering normal operations — while digital forensics preserves and analyzes evidence for legal action.

What You’ll Learn

By the end of this tutorial, you’ll understand the 7-step incident response lifecycle, how to collect and preserve digital evidence, perform basic malware analysis, maintain chain of custody, and write an incident response playbook for common scenarios.

Why IR & Forensics Matters

The average time to identify a breach is 207 days (IBM 2025). Every minute without a response plan increases damage. Organizations with an IR team save an average of $1.2 million per incident. At DodaTech, Durga Antivirus Pro includes an incident response module that automatically isolates infected endpoints and preserves forensic data.

IR Learning Path

    flowchart LR
  A[Security Basics] --> B[Network Security]
  B --> C[Web Security]
  C --> D[DevSecOps]
  D --> E[Incident Response]
  E --> F{You Are Here}
  style F fill:#f90,color:#fff
  
Prerequisites: Cyber Security basics. Familiarity with Linux command line and networking fundamentals is helpful.

What Is Incident Response? (The “Why” First)

Think of incident response like a hospital emergency room. When someone has a heart attack, the ER doesn’t start googling symptoms. They have a protocol: assess, stabilize, diagnose, treat, monitor. Incident response is the same protocol for security emergencies.

Without an IR plan, when a breach happens:

  • Panic and confusion
  • Evidence gets destroyed
  • Attackers remain in the network
  • Damage keeps growing

With an IR plan:

  • Clear roles and actions
  • Systematic containment
  • Evidence preserved for prosecution
  • Recovery in hours, not weeks

The 7-Step Incident Response Process

    flowchart LR
  A[1. Preparation] --> B[2. Identification]
  B --> C[3. Containment]
  C --> D[4. Eradication]
  D --> E[5. Recovery]
  E --> F[6. Lessons Learned]
  F --> A
  

Step 1: Preparation

The most critical phase. You can’t build a fire escape during a fire.

Preparation checklist:

  • Incident response policy and plan documented
  • IR team roles assigned (commander, analyst, comms, legal)
  • Contact lists (team, legal, PR, law enforcement, forensics vendors)
  • Tools ready: forensic workstations, imaging tools, analysis VMs
  • Logging enabled: SIEM, endpoint detection, network logs
  • Backups verified and offline copies available
  • Playbooks written for common scenarios

Essential IR tools:

ToolPurposeExample
SIEMLog aggregation and alertingSplunk, Elastic SIEM, Wazuh
EDREndpoint detection and responseCrowdStrike, SentinelOne, Wazuh
ForensicsDisk and memory analysisAutopsy, Volatility, FTK Imager
NetworkPacket capture and analysisWireshark, tcpdump, Zeek
Threat intelIOCs and threat dataMISP, OpenCTI, VirusTotal

Step 2: Identification

Detect that something is wrong. Common indicators:

# ir_detection.py — Simple log anomaly detector
import re
from collections import Counter
from datetime import datetime

class AnomalyDetector:
    """Detect common security anomalies in log data."""

    SUSPICIOUS_PATTERNS = {
        "multiple_auth_failures": r"Failed password.*ssh.*",
        "sql_injection_attempt": r"'.*OR.*'1'='1",
        "port_scan": r"Connection refused.*port",
        "suspicious_user_agent": r"(curl|wget|python-requests|masscan)",
        "large_file_download": r"GET.*\.(zip|tar|gz|sql|bak)\s+200\s+\d{7,}",
    }

    def __init__(self, log_file: str, threshold: int = 5):
        self.log_file = log_file
        self.threshold = threshold
        self.alerts = []

    def analyze(self) -> list[dict]:
        """Analyze a log file for anomalies."""
        try:
            with open(self.log_file, 'r') as f:
                lines = f.readlines()
        except FileNotFoundError:
            return [{"error": f"Log file {self.log_file} not found"}]

        for pattern_name, pattern in self.SUSPICIOUS_PATTERNS.items():
            matches = []
            for line in lines:
                if re.search(pattern, line, re.IGNORECASE):
                    matches.append(line.strip())

            if len(matches) >= self.threshold:
                self.alerts.append({
                    "alert": pattern_name,
                    "count": len(matches),
                    "severity": "HIGH" if len(matches) > 20 else "MEDIUM",
                    "timestamp": datetime.now().isoformat(),
                    "samples": matches[:3]  # First 3 matches
                })

        return self.alerts

# Example
# detector = AnomalyDetector("/var/log/auth.log", threshold=10)
# alerts = detector.analyze()
# for alert in alerts:
#     print(f"[{alert['severity']}] {alert['alert']} ({alert['count']} times)")

Step 3: Containment

Stop the bleeding. Short-term containment isolates the threat; long-term containment prepares for eradication.

Short-term actions:

  • Disconnect affected systems from the network
  • Block malicious IPs at the firewall
  • Disable compromised accounts
  • Take forensic images before shutting down
# Linux — Block an attacker IP with iptables
sudo iptables -A INPUT -s 192.168.1.100 -j DROP

# Windows — Disable a compromised user account
net user compromised_user /ACTIVE:NO

# Network — Capture live traffic before isolation
sudo tcpdump -i eth0 -w incident_capture.pcap

Forensic imaging — create a bit-for-bit copy before any changes:

# Create a forensic image of a disk (Linux)
# Using dd with a hardware write-blocker in production
sudo dd if=/dev/sda of=/mnt/evidence/disk_image.dd bs=4k conv=noerror,sync

# Verify the image with SHA-256
sudo sha256sum /dev/sda
sudo sha256sum /mnt/evidence/disk_image.dd
# Both hashes must match to prove evidence integrity

Step 4: Eradication

Remove the threat from the environment.

Actions:

  • Remove malware from affected systems
  • Patch the vulnerability that was exploited
  • Reset all passwords and rotate API keys
  • Rebuild compromised systems from clean images
  • Verify no backdoors or persistence mechanisms remain
# persistence_check.py — Check for common persistence mechanisms on Linux

def check_persistence() -> list[str]:
    """Check for common malware persistence mechanisms."""
    findings = []
    import os

    # Check cron jobs for all users
    cron_dirs = [
        "/etc/cron.hourly", "/etc/cron.daily",
        "/etc/cron.weekly", "/etc/cron.monthly",
        "/var/spool/cron/crontabs"
    ]
    for cron_dir in cron_dirs:
        if os.path.isdir(cron_dir):
            suspicious = [f for f in os.listdir(cron_dir)
                         if not f.startswith('.')]
            if suspicious:
                findings.append(f"Unexpected cron files in {cron_dir}: {suspicious}")

    # Check systemd services
    service_dirs = ["/etc/systemd/system", "/usr/lib/systemd/system"]
    for sd_dir in service_dirs:
        if os.path.isdir(sd_dir):
            services = os.listdir(sd_dir)
            # Flag recently added services
            for svc in services:
                path = os.path.join(sd_dir, svc)
                if os.path.getmtime(path) > 0:  # Check modification time
                    findings.append(f"Recently modified systemd service: {svc}")

    # Check SSH authorized_keys for unexpected keys
    ssh_dir = os.path.expanduser("~/.ssh/authorized_keys")
    if os.path.exists(ssh_dir):
        with open(ssh_dir) as f:
            keys = f.read().strip()
            if keys:
                findings.append(f"SSH authorized_keys found — verify each key")

    return findings

Step 5: Recovery

Restore normal operations safely.

Actions:

  • Restore systems from clean backups
  • Monitor for signs of re-infection
  • Gradually return systems to production
  • Communicate status to stakeholders

Step 6: Lessons Learned

The most frequently skipped step — and the one that prevents future incidents.

Post-mortem template:

# Incident Post-Mortem

**Date**: 2026-06-07
**Incident ID**: IR-2026-042
**Severity**: Critical / High / Medium / Low

## Timeline
- **Detection**: 2026-06-07 14:30 UTC
- **Containment**: 14:52 UTC (22 minutes)
- **Eradication**: 16:10 UTC
- **Recovery**: 18:30 UTC
- **Total duration**: 4 hours

## Root Cause
A phishing email delivered a trojan that established C2 via HTTPS
to a malicious domain. The trojan dumped LSASS credentials.

## What Went Well
- Detection within 15 minutes via EDR alert
- Team activated within 10 minutes via on-call rotation
- Forensic images taken before remediation

## What Could Be Better
- Phishing awareness training needs quarterly refresher
- LSASS should be disabled on non-domain controllers
- C2 domain was not blocked at proxy because HTTPS inspection was disabled

## Action Items
- [ ] Enable HTTPS inspection for all outbound traffic (Owner: Network Team, Due: 1 week)
- [ ] Disable LSASS on all servers (Owner: Security Team, Due: 2 weeks)
- [ ] Conduct phishing simulation this month (Owner: HR, Due: 2 weeks)
- [ ] Update IR playbook for phishing/Trojan scenarios (Owner: IR Lead, Due: 1 week)

Chain of Custody

For incidents that may lead to legal action, evidence must be tracked meticulously:

# chain_of_custody.py
# Track forensic evidence from collection to court
from datetime import datetime
import json

class ChainOfCustody:
    """Track evidence handling for legal admissibility."""

    def __init__(self, evidence_id: str, description: str):
        self.evidence_id = evidence_id
        self.description = description
        self.handlers = []
        self.add_entry("Evidence collected", "System")

    def add_entry(self, action: str, handler: str, notes: str = ""):
        """Record a custody transfer."""
        entry = {
            "timestamp": datetime.now().isoformat(),
            "action": action,
            "handler": handler,
            "notes": notes
        }
        self.handlers.append(entry)

    def verify_integrity(self, original_hash: str, current_hash: str) -> bool:
        """Verify evidence hasn't been tampered with."""
        match = original_hash == current_hash
        self.add_entry(
            "Hash verification",
            "Forensic Analyst",
            f"Hashes {'match' if match else 'DO NOT MATCH'}"
        )
        return match

    def report(self) -> str:
        """Generate chain of custody report."""
        report = f"=== Chain of Custody: {self.evidence_id} ===\n"
        report += f"Description: {self.description}\n"
        report += f"Total transfers: {len(self.handlers)}\n\n"
        for entry in self.handlers:
            report += f"{entry['timestamp']}{entry['action']} by {entry['handler']}\n"
            if entry['notes']:
                report += f"  Notes: {entry['notes']}\n"
        return report

# Example
evidence = ChainOfCustody(
    "EVD-2026-001",
    "Disk image — compromised web server #3"
)
evidence.add_entry("Imaged disk", "Analyst A", "SHA-256: a1b2c3...")
evidence.add_entry("Transferred to analysis VM", "Analyst A")
evidence.add_entry("Analyzed with Autopsy", "Analyst B")
evidence.add_entry("Returned to evidence locker", "Analyst C")
print(evidence.report())

Malware Analysis Basics

Static Analysis (Without Running)

# Check file type
file suspicious.exe

# Extract strings
strings suspicious.exe | head -50

# Check entropy (high entropy = packed/encrypted)
python3 -c "
import sys
with open(sys.argv[1], 'rb') as f:
    data = f.read()
    entropy = -sum((data.count(b)/len(data)) * (data.count(b)/len(data)).bit_length() for b in set(data))
    print(f'Entropy: {entropy:.2f}')
" suspicious.exe

Dynamic Analysis (In a Sandbox)

# sandbox_monitor.py — Monitor process behavior in a sandbox VM
import subprocess
import json

class SandboxMonitor:
    """Monitor system calls and network connections in a sandbox."""

    def __init__(self, sample_path: str):
        self.sample_path = sample_path

    def capture_network(self, duration: int = 30):
        """Capture network traffic during execution."""
        print(f"Capturing network for {duration}s...")
        # In a real sandbox, you'd use tcpdump or wireshark CLI
        # For this demo, we simulate the output
        return {
            "dns_queries": ["evil-malware.com", "192.168.1.100"],
            "connections": [{"dest": "185.220.101.1", "port": 443}],
            "protocols": ["HTTPS", "DNS"]
        }

    def check_process_creation(self) -> list[dict]:
        """Monitor child processes created."""
        # Simulate detection
        return [
            {"pid": 1234, "name": "explorer.exe", "parent": 567, "cmd": "C:\\Windows\\System32\\cmd.exe /c powershell -enc ..."},
            {"pid": 1235, "name": "powershell.exe", "parent": 1234, "cmd": "powershell -enc ZgByAG8AbQA..."}
        ]

    def check_registry_changes(self) -> list[dict]:
        """Monitor registry modifications."""
        return [
            {"key": "HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Run",
             "value": "MaliciousService",
             "action": "CREATE"}
        ]

    def generate_report(self) -> dict:
        """Generate a complete analysis report."""
        return {
            "sample": self.sample_path,
            "network": self.capture_network(),
            "processes": self.check_process_creation(),
            "registry": self.check_registry_changes(),
            "verdict": "MALICIOUS",
            "confidence": "HIGH"
        }

Common IR Mistakes

1. Not Having a Plan Until an Incident Occurs

You can’t think clearly during a crisis. Write your IR plan, test it with tabletop exercises, and update it quarterly.

2. Isolating Systems Prematurely

Before disconnecting a machine, take a forensic image. Once you disconnect, you lose volatile data (RAM contents, active network connections).

3. Not Preserving Evidence Properly

Without chain of custody and hash verification, evidence is inadmissible in court. Treat every incident as if it will go to trial.

4. Communicating Poorly

Stakeholders need updates. Silence creates rumors. Have a communication plan: internal, customers, press, law enforcement.

5. Skipping the Lessons Learned Phase

The biggest waste of an incident is not learning from it. Every incident should produce action items that make you stronger.

6. Relying Only on Automated Tools

SIEM and EDR tools are essential, but they generate noise and miss subtle attacks. Human analysis is irreplaceable.

7. Not Testing the IR Plan

A plan that’s never been tested will fail when it matters. Run tabletop exercises quarterly and full simulation exercises annually.

Practice Questions

1. What are the 6 phases of the incident response lifecycle?

Preparation, Identification, Containment, Eradication, Recovery, Lessons Learned. Preparation is the most important — you prepare before any incident.

2. Why is chain of custody important in digital forensics?

It proves evidence hasn’t been tampered with. Every transfer must be documented with timestamp, handler, and purpose. Without it, evidence is inadmissible in court.

3. What’s the difference between short-term and long-term containment?

Short-term containment immediately stops the bleeding (disconnect network, block IPs). Long-term containment prepares for eradication (take forensic images, identify all affected systems).

4. Why should you take a forensic image before disconnecting an infected machine?

Disconnecting loses volatile data: RAM contents, active network connections, running processes. A forensic image preserves the state at the time of detection.

5. Challenge: Write a one-page incident response playbook for ransomware.

Include: detection indicators (file renaming, ransom notes), containment (isolate network, identify patient zero), eradication (identify encryption key if available), recovery (restore from clean backups), communication (who to notify).

Mini Project: Incident Response Simulator

# ir_simulator.py
# Command-line incident response drill
import random
import time

class IRDrill:
    """Run a simulated incident response drill."""

    SCENARIOS = {
        "phishing": {
            "description": "User reports clicking a suspicious link and entering credentials",
            "steps": [
                "Identify affected user and machine",
                "Check email logs for phishing indicators",
                "Reset user credentials",
                "Check for other users who received the same email",
                "Scan affected machine for malware",
                "Block phishing domain at proxy"
            ]
        },
        "ransomware": {
            "description": "Files on file server being renamed with .locked extension",
            "steps": [
                "Isolate file server from network",
                "Identify patient zero (first infected machine)",
                "Take forensic image of affected server",
                "Check if decryption key exists",
                "Restore from clean backup",
                "Patch the vulnerability that allowed initial access"
            ]
        },
        "insider_threat": {
            "description": "Employee downloading large volumes of customer data before resignation",
            "steps": [
                "Disable user account immediately",
                "Escort employee from premises (if in-office)",
                "Take forensic image of workstation",
                "Check what data was accessed/downloaded",
                "Notify legal department",
                "Review access logs for all sensitive data"
            ]
        }
    }

    def run_drill(self, scenario_name: str = None):
        """Run a randomized IR drill."""
        if scenario_name:
            scenario = self.SCENARIOS.get(scenario_name)
            if not scenario:
                print(f"Unknown scenario: {scenario_name}")
                return
        else:
            scenario = random.choice(list(self.SCENARIOS.values()))

        print(f"\n=== INCIDENT RESPONSE DRILL ===")
        print(f"Scenario: {scenario['description']}\n")
        print("Correct steps (in order):")
        for i, step in enumerate(scenario['steps'], 1):
            print(f"  {i}. {step}")

        input("\nPress Enter to reveal the recommended order...")
        print("\n=== Recommended Response ===")
        for step in scenario['steps']:
            time.sleep(0.5)
            print(f"  ✓ {step}")

if __name__ == "__main__":
    drill = IRDrill()
    drill.run_drill("ransomware")

FAQ

How long should an incident response plan be?
Start with 5-10 pages covering: team roles, communication plan, response workflow, and playbooks for top 3 scenarios. Expand as you learn from incidents.
What’s the difference between EDR and SIEM?
EDR (Endpoint Detection and Response) monitors individual machines for suspicious behavior. SIEM aggregates logs from many sources (EDR, firewalls, servers) for correlation and alerting. You need both.
Do I need a dedicated forensic lab?
For professional forensics, yes — a clean environment with write-blockers, forensic workstations, and analysis VMs. For learning, a virtual machine with forensic tools installed is sufficient.
How do I get started in incident response?
Learn Linux command line and networking. Practice with free resources: Wazuh for EDR/SIEM, Autopsy for forensics, TryHackMe IR rooms. Consider GIAC certifications (GCIH, GCFE).
What’s the most important IR skill?
Remaining calm and methodical under pressure. Technical skills can be learned; composure during a crisis comes from practice and preparation.

Try It Yourself

Set up a home lab for IR practice:

  1. Install a SIEM (Wazuh or ELK stack) in a VM
  2. Generate security events: failed SSH logins, port scans, malware downloads
  3. Practice identifying incidents from the logs
  4. Create an IR playbook for one scenario

This is the same type of lab DodaTech uses to train its security operations team for Durga Antivirus Pro and Doda Browser incident response.

What’s Next

What’s Next

Congratulations on completing this Incident Response tutorial! Here’s where to go from here:

  • Practice daily — Consistency is more important than long study sessions
  • Build a project — Apply what you learned by building something real
  • Explore related topics — Check out other tutorials in the same category
  • Join the community — Discuss with other learners and share your progress

Remember: every expert was once a beginner. Keep coding!

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro