npx skills add mukul975/Anthropic-Cybersecurity-SkillsMITRE ATT&CK
When to Use
- When you need to create a forensic copy of a suspect drive for investigation
- During incident response when preserving volatile disk evidence before analysis
- When law enforcement or legal proceedings require a verified bit-for-bit copy
- Before performing any destructive analysis on a storage device
- When acquiring images from physical drives, USB devices, or memory cards
Prerequisites
- Linux-based forensic workstation (SIFT, Kali, or any Linux distro)
dd(pre-installed on all Linux systems) ordcfldd(enhanced forensic version)- Write-blocker hardware or software write-blocking configured
- Destination drive with sufficient storage (larger than source)
- Root/sudo privileges on the forensic workstation
- SHA-256 or MD5 hashing utilities (
sha256sum,md5sum)
Workflow
Step 1: Identify the Target Device and Enable Write Protection
# List all connected block devices to identify the target
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,MODEL
# Verify the device details
fdisk -l /dev/sdb
# Enable software write-blocking (if no hardware blocker)
blockdev --setro /dev/sdb
# Verify read-only status
blockdev --getro /dev/sdb
# Output: 1 (means read-only is enabled)
# Alternatively, use udev rules for persistent write-blocking
echo 'SUBSYSTEM=="block", ATTRS{serial}=="WD-WCAV5H861234", ATTR{ro}="1"' > /etc/udev/rules.d/99-writeblock.rules
udevadm control --reload-rulesStep 2: Prepare the Destination and Document the Source
# Create case directory structure
mkdir -p /cases/case-2024-001/{images,hashes,logs,notes}
# Document source drive information
hdparm -I /dev/sdb > /cases/case-2024-001/notes/source_drive_info.txt
# Record the serial number and model
smartctl -i /dev/sdb >> /cases/case-2024-001/notes/source_drive_info.txt
# Pre-hash the source device
sha256sum /dev/sdb | tee /cases/case-2024-001/hashes/source_hash_before.txtStep 3: Acquire the Image Using dd
# Basic dd acquisition with progress and error handling
dd if=/dev/sdb of=/cases/case-2024-001/images/evidence.dd \
bs=4096 \
conv=noerror,sync \
status=progress 2>&1 | tee /cases/case-2024-001/logs/dd_acquisition.log
# For compressed images to save space
dd if=/dev/sdb bs=4096 conv=noerror,sync status=progress | \
gzip -c > /cases/case-2024-001/images/evidence.dd.gz
# Using dd with a specific count for partial acquisition
dd if=/dev/sdb of=/cases/case-2024-001/images/first_1gb.dd \
bs=1M count=1024 status=progressStep 4: Acquire Using dcfldd (Preferred Forensic Method)
# Install dcfldd if not present
apt-get install dcfldd
# Acquire image with built-in hashing and split output
dcfldd if=/dev/sdb \
of=/cases/case-2024-001/images/evidence.dd \
hash=sha256,md5 \
hashwindow=1G \
hashlog=/cases/case-2024-001/hashes/acquisition_hashes.txt \
bs=4096 \
conv=noerror,sync \
errlog=/cases/case-2024-001/logs/dcfldd_errors.log
# Split large images into manageable segments
dcfldd if=/dev/sdb \
of=/cases/case-2024-001/images/evidence.dd \
hash=sha256 \
hashlog=/cases/case-2024-001/hashes/split_hashes.txt \
bs=4096 \
split=2G \
splitformat=aa
# Acquire with verification pass
dcfldd if=/dev/sdb \
of=/cases/case-2024-001/images/evidence.dd \
hash=sha256 \
hashlog=/cases/case-2024-001/hashes/verification.txt \
vf=/cases/case-2024-001/images/evidence.dd \
verifylog=/cases/case-2024-001/logs/verify.logStep 5: Verify Image Integrity
# Hash the acquired image
sha256sum /cases/case-2024-001/images/evidence.dd | \
tee /cases/case-2024-001/hashes/image_hash.txt
# Compare source and image hashes
diff <(sha256sum /dev/sdb | awk '{print $1}') \
<(sha256sum /cases/case-2024-001/images/evidence.dd | awk '{print $1}')
# If using split images, verify each segment
sha256sum /cases/case-2024-001/images/evidence.dd.* | \
tee /cases/case-2024-001/hashes/split_image_hashes.txt
# Re-hash source to confirm no changes occurred
sha256sum /dev/sdb | tee /cases/case-2024-001/hashes/source_hash_after.txt
diff /cases/case-2024-001/hashes/source_hash_before.txt \
/cases/case-2024-001/hashes/source_hash_after.txtStep 6: Document the Acquisition Process
# Generate acquisition report
cat << 'EOF' > /cases/case-2024-001/notes/acquisition_report.txt
DISK IMAGE ACQUISITION REPORT
==============================
Case Number: 2024-001
Date/Time: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
Examiner: [Name]
Source Device: /dev/sdb
Model: [from hdparm output]
Serial: [from hdparm output]
Size: [from fdisk output]
Acquisition Tool: dcfldd v1.9.1
Block Size: 4096
Write Blocker: [Hardware/Software model]
Image File: evidence.dd
Image Hash (SHA-256): [from hash file]
Source Hash (SHA-256): [from hash file]
Hash Match: YES/NO
Errors During Acquisition: [from error log]
EOF
# Compress logs for archival
tar -czf /cases/case-2024-001/acquisition_package.tar.gz \
/cases/case-2024-001/hashes/ \
/cases/case-2024-001/logs/ \
/cases/case-2024-001/notes/Key Concepts
| Concept | Description |
|---|---|
| Bit-for-bit copy | Exact replica of source including unallocated space and slack space |
| Write blocker | Hardware or software mechanism preventing writes to evidence media |
| Hash verification | Cryptographic hash comparing source and image to prove integrity |
| Block size (bs) | Transfer chunk size affecting speed; 4096 or 64K typical for forensics |
| conv=noerror,sync | Continue on read errors and pad with zeros to maintain offset alignment |
| Chain of custody | Documented trail proving evidence has not been tampered with |
| Split imaging | Breaking large images into smaller files for storage and transport |
| Raw/dd format | Bit-for-bit image format without metadata container overhead |
Tools & Systems
| Tool | Purpose |
|---|---|
| dd | Standard Unix disk duplication utility for raw imaging |
| dcfldd | DoD Computer Forensics Laboratory enhanced version of dd with hashing |
| dc3dd | Another forensic dd variant from the DoD Cyber Crime Center |
| sha256sum | SHA-256 hash calculation for integrity verification |
| blockdev | Linux command to set block device read-only mode |
| hdparm | Drive identification and parameter reporting |
| smartctl | S.M.A.R.T. data retrieval for drive health and identification |
| lsblk | Block device enumeration and identification |
Common Scenarios
Scenario 1: Acquiring a Suspect Laptop Hard Drive
Connect the drive via a Tableau T35u hardware write-blocker, identify as /dev/sdb, use dcfldd with SHA-256 hashing, split into 4GB segments for DVD archival, verify hashes match, document in case notes.
Scenario 2: Imaging a USB Flash Drive from a Compromised Workstation
Use software write-blocking with blockdev --setro, acquire with dcfldd including MD5 and SHA-256 dual hashing, image is small enough for single file, verify and store on encrypted case drive.
Scenario 3: Remote Acquisition Over Network
Use dd piped through netcat or ssh for remote acquisition: ssh root@remote "dd if=/dev/sda bs=4096" | dd of=remote_image.dd bs=4096, hash both ends independently to verify transfer integrity.
Scenario 4: Acquiring from a Failing Drive
Use ddrescue first to recover readable sectors, then use dd with conv=noerror,sync to fill gaps with zeros, document which sectors were unreadable in the error log.
Output Format
Acquisition Summary:
Source: /dev/sdb (500GB Western Digital WD5000AAKX)
Destination: /cases/case-2024-001/images/evidence.dd
Tool: dcfldd 1.9.1
Block Size: 4096 bytes
Duration: 2h 15m 32s
Bytes Copied: 500,107,862,016
Errors: 0 bad sectors
Source SHA-256: a3f2b8c9d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1
Image SHA-256: a3f2b8c9d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1
Verification: PASSED - Hashes matchReferences and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 1
api-reference.md2.5 KB
API Reference: dd and dcfldd Disk Imaging
dd - Standard Unix Disk Duplication
Basic Syntax
dd if=<source> of=<destination> [options]Key Options
| Flag | Description | Example |
|---|---|---|
if= |
Input file (source device) | if=/dev/sdb |
of= |
Output file (destination image) | of=evidence.dd |
bs= |
Block size for read/write | bs=4096 (forensic standard) |
count= |
Number of blocks to copy | count=1024 |
skip= |
Skip N blocks from input start | skip=2048 |
conv= |
Conversion options | conv=noerror,sync |
status= |
Transfer statistics level | status=progress |
conv= Values
noerror- Continue on read errors (do not abort)sync- Pad input blocks with zeros on error (preserves offset alignment)notrunc- Do not truncate output file
Output Format
500107862016 bytes (500 GB, 466 GiB) copied, 8132.45 s, 61.5 MB/s
976773168+0 records in
976773168+0 records outdcfldd - DoD Forensic dd
Basic Syntax
dcfldd if=<source> of=<destination> [options]Extended Options
| Flag | Description | Example |
|---|---|---|
hash= |
Hash algorithm(s) | hash=sha256,md5 |
hashlog= |
File for hash output | hashlog=hashes.txt |
hashwindow= |
Hash every N bytes | hashwindow=1G |
hashconv= |
Hash before or after conversion | hashconv=after |
errlog= |
Error log file | errlog=errors.log |
split= |
Split output into chunks | split=2G |
splitformat= |
Suffix format for split files | splitformat=aa |
vf= |
Verification file | vf=evidence.dd |
verifylog= |
Verification result log | verifylog=verify.log |
Output Format
Total (sha256): a3f2b8c9d4e5f6a7b8c9d0e1f2a3b4c5...
1024+0 records in
1024+0 records outsha256sum - Hash Verification
Syntax
sha256sum <file_or_device>
sha256sum -c <checksum_file>Output Format
a3f2b8c9d4e5f6... /dev/sdb
a3f2b8c9d4e5f6... evidence.ddblockdev - Write Protection
Syntax
blockdev --setro <device> # Set read-only
blockdev --setrw <device> # Set read-write
blockdev --getro <device> # Check: 1=RO, 0=RW
blockdev --getsize64 <device> # Size in byteslsblk - Block Device Enumeration
Syntax
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,MODEL,SERIAL,RO
lsblk -J # JSON output
lsblk -p # Full device pathshdparm - Drive Identification
Syntax
hdparm -I <device> # Detailed drive info
hdparm -i <device> # Summary identificationScripts 1
agent.py6.7 KB
#!/usr/bin/env python3
"""Forensic disk image acquisition agent using dd and dcfldd with hash verification."""
import shlex
import subprocess
import hashlib
import os
import datetime
import json
def run_cmd(cmd, capture=True):
"""Execute a command and return output."""
if isinstance(cmd, str):
cmd = shlex.split(cmd)
result = subprocess.run(cmd, capture_output=capture, text=True, timeout=120)
return result.stdout.strip(), result.stderr.strip(), result.returncode
def list_block_devices():
"""Enumerate connected block devices."""
stdout, _, rc = run_cmd("lsblk -J -o NAME,SIZE,TYPE,MOUNTPOINT,MODEL,SERIAL,RO")
if rc == 0 and stdout:
return json.loads(stdout)
return {"blockdevices": []}
def check_write_protection(device):
"""Verify a device is set to read-only mode."""
stdout, _, rc = run_cmd(f"blockdev --getro {device}")
if rc == 0:
return stdout.strip() == "1"
return False
def enable_write_protection(device):
"""Enable software write-blocking on the target device."""
_, _, rc = run_cmd(f"blockdev --setro {device}")
if rc != 0:
print(f"[ERROR] Failed to set {device} read-only. Run as root.")
return False
if check_write_protection(device):
print(f"[OK] Write protection enabled on {device}")
return True
print(f"[ERROR] Write protection verification failed for {device}")
return False
def compute_hash(path, algorithm="sha256", block_size=65536):
"""Compute the SHA-256 or MD5 hash of a file or device."""
h = hashlib.new(algorithm)
try:
with open(path, "rb") as f:
while True:
block = f.read(block_size)
if not block:
break
h.update(block)
except PermissionError:
print(f"[ERROR] Permission denied reading {path}. Run as root.")
return None
except FileNotFoundError:
print(f"[ERROR] Path not found: {path}")
return None
return h.hexdigest()
def acquire_with_dd(source, destination, block_size=4096, log_file=None):
"""Acquire a forensic image using dd with error handling."""
dd_cmd = [
"dd", f"if={source}", f"of={destination}",
f"bs={block_size}", "conv=noerror,sync", "status=progress"
]
print(f"[*] Starting dd acquisition: {source} -> {destination}")
print(f"[*] Block size: {block_size}")
start = datetime.datetime.utcnow()
if log_file:
dd_proc = subprocess.run(dd_cmd, capture_output=True, text=True, timeout=120)
combined = (dd_proc.stdout or "") + (dd_proc.stderr or "")
with open(log_file, "w") as lf:
lf.write(combined)
rc = dd_proc.returncode
else:
result = subprocess.run(dd_cmd, text=True, timeout=120)
rc = result.returncode
elapsed = (datetime.datetime.utcnow() - start).total_seconds()
print(f"[*] Acquisition completed in {elapsed:.1f} seconds (rc={rc})")
return rc == 0
def acquire_with_dcfldd(source, destination, hash_alg="sha256", hash_log=None,
error_log=None, block_size=4096, split_size=None):
"""Acquire a forensic image using dcfldd with built-in hashing."""
cmd = [
"dcfldd", f"if={source}", f"of={destination}",
f"bs={block_size}", "conv=noerror,sync",
f"hash={hash_alg}", "hashwindow=1G",
]
if hash_log:
cmd.append(f"hashlog={hash_log}")
if error_log:
cmd.append(f"errlog={error_log}")
if split_size:
cmd.extend([f"split={split_size}", "splitformat=aa"])
print(f"[*] Starting dcfldd acquisition: {source} -> {destination}")
start = datetime.datetime.utcnow()
result = subprocess.run(cmd, text=True, timeout=120)
rc = result.returncode
elapsed = (datetime.datetime.utcnow() - start).total_seconds()
print(f"[*] dcfldd completed in {elapsed:.1f} seconds (rc={rc})")
return rc == 0
def verify_image(source, image_path, algorithm="sha256"):
"""Verify image integrity by comparing hashes of source and acquired image."""
print(f"[*] Computing {algorithm} hash of source: {source}")
source_hash = compute_hash(source, algorithm)
print(f" Source hash: {source_hash}")
print(f"[*] Computing {algorithm} hash of image: {image_path}")
image_hash = compute_hash(image_path, algorithm)
print(f" Image hash: {image_hash}")
if source_hash and image_hash:
match = source_hash == image_hash
status = "PASSED" if match else "FAILED"
print(f"[{'OK' if match else 'FAIL'}] Verification: {status}")
return match, source_hash, image_hash
return False, source_hash, image_hash
def generate_report(case_dir, source_device, image_path, tool_used,
source_hash, image_hash, verified, elapsed_seconds=0):
"""Generate a forensic acquisition report."""
report = {
"report_type": "Disk Image Acquisition",
"timestamp": datetime.datetime.utcnow().isoformat() + "Z",
"case_directory": case_dir,
"source_device": source_device,
"image_file": image_path,
"acquisition_tool": tool_used,
"block_size": 4096,
"source_hash_sha256": source_hash,
"image_hash_sha256": image_hash,
"hash_verified": verified,
"duration_seconds": elapsed_seconds,
}
report_path = os.path.join(case_dir, "acquisition_report.json")
with open(report_path, "w") as f:
json.dump(report, f, indent=2)
print(f"[*] Report saved to {report_path}")
return report
if __name__ == "__main__":
print("=" * 60)
print("Forensic Disk Image Acquisition Agent")
print("Tools: dd / dcfldd with SHA-256 verification")
print("=" * 60)
# Demo: list block devices
print("\n[*] Enumerating block devices...")
devices = list_block_devices()
for dev in devices.get("blockdevices", []):
name = dev.get("name", "?")
size = dev.get("size", "?")
dtype = dev.get("type", "?")
model = dev.get("model", "N/A")
ro = "RO" if dev.get("ro") else "RW"
print(f" /dev/{name} {size} {dtype} {model} [{ro}]")
# Demo workflow (dry run)
demo_source = "/dev/sdb"
demo_case = "/cases/demo-case/images"
demo_image = os.path.join(demo_case, "evidence.dd")
print(f"\n[DEMO] Acquisition workflow for {demo_source}:")
print(f" 1. Enable write protection: blockdev --setro {demo_source}")
print(f" 2. Acquire with dcfldd: dcfldd if={demo_source} of={demo_image} "
f"hash=sha256 hashwindow=1G bs=4096 conv=noerror,sync")
print(f" 3. Verify: compare SHA-256 of {demo_source} and {demo_image}")
print(f" 4. Generate acquisition report with chain-of-custody metadata")
print("\n[*] Agent ready. Provide a source device and case directory to begin.")