Appearance
NetworkMiner Network Forensic Analysis Tool Cheat Sheet
Overview
NetworkMiner is a Network Forensic Analysis Tool (NFAT) for Windows that can detect operating systems, sessions, hostnames, open ports, and more by analyzing network traffic captured in PCAP files. It provides a user-friendly interface for network forensics and incident response, offering both free and professional versions with advanced features for deep packet analysis, file extraction, and network reconstruction.
⚠️ Note: NetworkMiner is primarily a Windows application. The free version has limitations on PCAP file size and features. Professional version offers advanced capabilities for enterprise use.
Installation
Windows Installation
powershell
# Download NetworkMiner Free from official website
# https://www.netresec.com/?page=NetworkMiner
# Extract to desired directory
Expand-Archive -Path NetworkMiner_2-8-1.zip -DestinationPath C:\Tools\NetworkMiner
# Run NetworkMiner
cd C:\Tools\NetworkMiner
.\NetworkMiner.exe
# For Professional version
# Purchase license from https://www.netresec.com/
# Install using provided installer
Linux Installation (Mono)
bash
# Install Mono runtime
sudo apt update
sudo apt install mono-complete
# Download NetworkMiner
wget https://www.netresec.com/files/NetworkMiner_2-8-1.zip
unzip NetworkMiner_2-8-1.zip
cd NetworkMiner_2-8-1
# Run with Mono
mono NetworkMiner.exe
# Install additional dependencies if needed
sudo apt install libmono-winforms2.0-cil
sudo apt install libmono-system-windows-forms4.0-cil
Docker Installation
bash
# Create Dockerfile for NetworkMiner
cat > Dockerfile << 'EOF'
FROM mono:latest
RUN apt-get update && apt-get install -y \
wget \
unzip \
libmono-winforms2.0-cil \
libmono-system-windows-forms4.0-cil
WORKDIR /app
RUN wget https://www.netresec.com/files/NetworkMiner_2-8-1.zip && \
unzip NetworkMiner_2-8-1.zip && \
rm NetworkMiner_2-8-1.zip
WORKDIR /app/NetworkMiner_2-8-1
ENTRYPOINT ["mono", "NetworkMiner.exe"]
EOF
# Build and run
docker build -t networkminer .
docker run -it --rm -v $(pwd)/pcaps:/pcaps networkminer
Portable Installation
bash
# Download portable version
wget https://www.netresec.com/files/NetworkMiner_2-8-1.zip
# Extract to USB drive or portable location
unzip NetworkMiner_2-8-1.zip -d /media/usb/NetworkMiner
# Create launcher script
cat > /media/usb/NetworkMiner/run_networkminer.sh << 'EOF'
#!/bin/bash
cd "$(dirname "$0")/NetworkMiner_2-8-1"
mono NetworkMiner.exe "$@"
EOF
chmod +x /media/usb/NetworkMiner/run_networkminer.sh
Basic Usage
Loading PCAP Files
powershell
# Command line usage
NetworkMiner.exe --help
# Load single PCAP file
NetworkMiner.exe capture.pcap
# Load multiple PCAP files
NetworkMiner.exe capture1.pcap capture2.pcap capture3.pcap
# Load PCAP with specific output directory
NetworkMiner.exe --output C:\Analysis\Output capture.pcap
# Load large PCAP files (Professional)
NetworkMiner.exe --maxframes 1000000 large_capture.pcap
GUI Operations
text
File Menu:
- Open File(s): Load PCAP/PCAPNG files
- Open Directory: Load all PCAP files from directory
- Receive from Sniffer: Capture live traffic (Professional)
- Clear GUI: Clear current analysis
- Export: Export analysis results
Tools Menu:
- Reassemble Files: Extract files from traffic
- Generate Report: Create analysis report
- Calculate Hash: Generate file hashes
- Decode Base64: Decode Base64 strings
- Convert PCAP: Convert between formats
Command Line Interface
bash
# Basic analysis
mono NetworkMiner.exe capture.pcap
# Specify output directory
mono NetworkMiner.exe --output /tmp/analysis capture.pcap
# Set maximum frames to process
mono NetworkMiner.exe --maxframes 100000 capture.pcap
# Enable verbose output
mono NetworkMiner.exe --verbose capture.pcap
# Process multiple files
mono NetworkMiner.exe *.pcap
# Generate report automatically
mono NetworkMiner.exe --report capture.pcap
Network Analysis Features
Host Discovery
text
Hosts Tab Analysis:
- IP addresses and MAC addresses
- Operating system detection
- Open ports and services
- Hostname resolution
- Network distance (TTL analysis)
- First and last seen timestamps
Host Information Extraction:
- DHCP hostnames
- NetBIOS names
- DNS queries and responses
- HTTP User-Agent strings
- SMB/CIFS hostnames
Session Analysis
text
Sessions Tab Features:
- TCP sessions reconstruction
- Client-server relationships
- Session duration and data volume
- Protocol identification
- Application layer protocols
Session Details:
- Source and destination hosts
- Port numbers and protocols
- Start and end timestamps
- Bytes transferred
- Frame count
File Extraction
text
Files Tab Capabilities:
- Automatic file extraction from traffic
- File type identification
- MD5/SHA1/SHA256 hash calculation
- File size and timestamps
- Source host identification
Supported Protocols for File Extraction:
- HTTP/HTTPS file downloads
- FTP file transfers
- SMB/CIFS file shares
- SMTP email attachments
- POP3/IMAP email content
- TFTP transfers
Credential Harvesting
text
Credentials Tab Features:
- Clear-text password extraction
- Authentication attempts
- Protocol-specific credentials
- Success/failure indicators
Supported Protocols:
- HTTP Basic/Digest authentication
- FTP login credentials
- Telnet authentication
- POP3/IMAP login
- SMB/NTLM authentication
- SNMP community strings
Advanced Analysis Techniques
Protocol Analysis
bash
#!/bin/bash
# networkminer-protocol-analysis.sh
PCAP_FILE="$1"
OUTPUT_DIR="/tmp/nm_analysis"
if [ $# -ne 1 ]; then
echo "Usage: $0 <pcap_file>"
exit 1
fi
mkdir -p "$OUTPUT_DIR"
echo "Starting NetworkMiner analysis of $PCAP_FILE"
# Run NetworkMiner analysis
mono NetworkMiner.exe --output "$OUTPUT_DIR" "$PCAP_FILE"
# Parse results
echo "=== Host Summary ==="
if [ -f "$OUTPUT_DIR/hosts.csv" ]; then
cat "$OUTPUT_DIR/hosts.csv" | head -20
fi
echo -e "\n=== Session Summary ==="
if [ -f "$OUTPUT_DIR/sessions.csv" ]; then
cat "$OUTPUT_DIR/sessions.csv" | head -20
fi
echo -e "\n=== Extracted Files ==="
if [ -d "$OUTPUT_DIR/AssembledFiles" ]; then
find "$OUTPUT_DIR/AssembledFiles" -type f | head -20
fi
echo -e "\n=== Credentials Found ==="
if [ -f "$OUTPUT_DIR/credentials.csv" ]; then
cat "$OUTPUT_DIR/credentials.csv"
fi
Automated File Analysis
python
#!/usr/bin/env python3
# networkminer-file-analyzer.py
import os
import sys
import hashlib
import subprocess
import csv
from pathlib import Path
class NetworkMinerAnalyzer:
def __init__(self, pcap_file, output_dir):
self.pcap_file = pcap_file
self.output_dir = Path(output_dir)
self.assembled_files_dir = self.output_dir / "AssembledFiles"
def run_networkminer(self):
"""Run NetworkMiner analysis"""
cmd = [
"mono", "NetworkMiner.exe",
"--output", str(self.output_dir),
self.pcap_file
]
try:
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
print(f"NetworkMiner error: {result.stderr}")
return False
return True
except Exception as e:
print(f"Error running NetworkMiner: {e}")
return False
def analyze_extracted_files(self):
"""Analyze extracted files"""
if not self.assembled_files_dir.exists():
print("No assembled files directory found")
return
print("=== Extracted Files Analysis ===")
for file_path in self.assembled_files_dir.rglob("*"):
if file_path.is_file():
self.analyze_file(file_path)
def analyze_file(self, file_path):
"""Analyze individual extracted file"""
try:
# Calculate file hash
with open(file_path, 'rb') as f:
file_hash = hashlib.sha256(f.read()).hexdigest()
# Get file info
file_size = file_path.stat().st_size
file_type = self.get_file_type(file_path)
print(f"File: {file_path.name}")
print(f" Size: {file_size} bytes")
print(f" Type: {file_type}")
print(f" SHA256: {file_hash}")
print(f" Path: {file_path}")
# Check for suspicious files
if self.is_suspicious_file(file_path, file_type):
print(f" ⚠️ SUSPICIOUS FILE DETECTED")
print()
except Exception as e:
print(f"Error analyzing {file_path}: {e}")
def get_file_type(self, file_path):
"""Determine file type"""
try:
result = subprocess.run(['file', str(file_path)],
capture_output=True, text=True)
return result.stdout.strip().split(':', 1)[1].strip()
except:
return "Unknown"
def is_suspicious_file(self, file_path, file_type):
"""Check if file is potentially suspicious"""
suspicious_extensions = ['.exe', '.scr', '.bat', '.cmd', '.com', '.pif']
suspicious_types = ['executable', 'script', 'batch']
# Check extension
if any(str(file_path).lower().endswith(ext) for ext in suspicious_extensions):
return True
# Check file type
if any(sus_type in file_type.lower() for sus_type in suspicious_types):
return True
return False
def parse_hosts_csv(self):
"""Parse hosts.csv file"""
hosts_file = self.output_dir / "hosts.csv"
if not hosts_file.exists():
return
print("=== Host Analysis ===")
try:
with open(hosts_file, 'r') as f:
reader = csv.DictReader(f)
for row in reader:
print(f"Host: {row.get('IP', 'Unknown')}")
print(f" MAC: {row.get('MAC', 'Unknown')}")
print(f" OS: {row.get('OS', 'Unknown')}")
print(f" Hostname: {row.get('Hostname', 'Unknown')}")
print()
except Exception as e:
print(f"Error parsing hosts.csv: {e}")
def parse_credentials_csv(self):
"""Parse credentials.csv file"""
creds_file = self.output_dir / "credentials.csv"
if not creds_file.exists():
return
print("=== Credentials Analysis ===")
try:
with open(creds_file, 'r') as f:
reader = csv.DictReader(f)
for row in reader:
print(f"Protocol: {row.get('Protocol', 'Unknown')}")
print(f" Username: {row.get('Username', 'Unknown')}")
print(f" Password: {row.get('Password', 'Unknown')}")
print(f" Host: {row.get('Host', 'Unknown')}")
print()
except Exception as e:
print(f"Error parsing credentials.csv: {e}")
def generate_report(self):
"""Generate comprehensive analysis report"""
report_file = self.output_dir / "analysis_report.txt"
with open(report_file, 'w') as f:
f.write(f"NetworkMiner Analysis Report\n")
f.write(f"PCAP File: {self.pcap_file}\n")
f.write(f"Analysis Date: {os.popen('date').read().strip()}\n")
f.write("=" * 50 + "\n\n")
# File statistics
if self.assembled_files_dir.exists():
file_count = len(list(self.assembled_files_dir.rglob("*")))
f.write(f"Extracted Files: {file_count}\n")
# Host statistics
hosts_file = self.output_dir / "hosts.csv"
if hosts_file.exists():
with open(hosts_file, 'r') as hosts_f:
host_count = len(hosts_f.readlines()) - 1 # Subtract header
f.write(f"Unique Hosts: {host_count}\n")
f.write("\nDetailed analysis available in CSV files and AssembledFiles directory.\n")
print(f"Report generated: {report_file}")
def main():
if len(sys.argv) != 3:
print("Usage: python3 networkminer-file-analyzer.py <pcap_file> <output_dir>")
sys.exit(1)
pcap_file = sys.argv[1]
output_dir = sys.argv[2]
analyzer = NetworkMinerAnalyzer(pcap_file, output_dir)
print("Running NetworkMiner analysis...")
if analyzer.run_networkminer():
print("Analysis complete. Processing results...")
analyzer.parse_hosts_csv()
analyzer.parse_credentials_csv()
analyzer.analyze_extracted_files()
analyzer.generate_report()
else:
print("NetworkMiner analysis failed")
if __name__ == "__main__":
main()
Batch Processing Script
bash
#!/bin/bash
# networkminer-batch-processor.sh
PCAP_DIR="$1"
OUTPUT_BASE_DIR="$2"
NETWORKMINER_PATH="/opt/NetworkMiner"
if [ $# -ne 2 ]; then
echo "Usage: $0 <pcap_directory> <output_base_directory>"
exit 1
fi
if [ ! -d "$PCAP_DIR" ]; then
echo "Error: PCAP directory does not exist"
exit 1
fi
mkdir -p "$OUTPUT_BASE_DIR"
# Process each PCAP file
find "$PCAP_DIR" -name "*.pcap" -o -name "*.pcapng" | while read pcap_file; do
echo "Processing: $pcap_file"
# Create output directory for this PCAP
pcap_basename=$(basename "$pcap_file" | sed 's/\.[^.]*$//')
output_dir="$OUTPUT_BASE_DIR/$pcap_basename"
mkdir -p "$output_dir"
# Run NetworkMiner
cd "$NETWORKMINER_PATH"
mono NetworkMiner.exe --output "$output_dir" "$pcap_file"
# Generate summary
echo "=== Analysis Summary for $pcap_file ===" > "$output_dir/summary.txt"
echo "Analysis Date: $(date)" >> "$output_dir/summary.txt"
echo "PCAP File: $pcap_file" >> "$output_dir/summary.txt"
echo "Output Directory: $output_dir" >> "$output_dir/summary.txt"
echo "" >> "$output_dir/summary.txt"
# Count extracted files
if [ -d "$output_dir/AssembledFiles" ]; then
file_count=$(find "$output_dir/AssembledFiles" -type f | wc -l)
echo "Extracted Files: $file_count" >> "$output_dir/summary.txt"
fi
# Count hosts
if [ -f "$output_dir/hosts.csv" ]; then
host_count=$(($(wc -l < "$output_dir/hosts.csv") - 1))
echo "Unique Hosts: $host_count" >> "$output_dir/summary.txt"
fi
# Count sessions
if [ -f "$output_dir/sessions.csv" ]; then
session_count=$(($(wc -l < "$output_dir/sessions.csv") - 1))
echo "Network Sessions: $session_count" >> "$output_dir/summary.txt"
fi
echo "Completed: $pcap_file"
echo "Output: $output_dir"
echo "---"
done
echo "Batch processing complete!"
echo "Results available in: $OUTPUT_BASE_DIR"
Integration and Automation
SIEM Integration
python
#!/usr/bin/env python3
# networkminer-siem-integration.py
import json
import csv
import requests
from pathlib import Path
import hashlib
class NetworkMinerSIEMIntegrator:
def __init__(self, output_dir, siem_endpoint, api_key):
self.output_dir = Path(output_dir)
self.siem_endpoint = siem_endpoint
self.api_key = api_key
def send_to_siem(self, event_data):
"""Send event to SIEM"""
try:
headers = {
'Content-Type': 'application/json',
'Authorization': f'Bearer {self.api_key}'
}
response = requests.post(
self.siem_endpoint,
json=event_data,
headers=headers,
timeout=10
)
response.raise_for_status()
return True
except requests.RequestException as e:
print(f"Error sending to SIEM: {e}")
return False
def process_hosts(self):
"""Process and send host information to SIEM"""
hosts_file = self.output_dir / "hosts.csv"
if not hosts_file.exists():
return
with open(hosts_file, 'r') as f:
reader = csv.DictReader(f)
for row in reader:
event = {
'event_type': 'host_discovery',
'source': 'networkminer',
'timestamp': row.get('First Seen', ''),
'ip_address': row.get('IP', ''),
'mac_address': row.get('MAC', ''),
'hostname': row.get('Hostname', ''),
'operating_system': row.get('OS', ''),
'open_ports': row.get('Open Ports', ''),
'last_seen': row.get('Last Seen', '')
}
self.send_to_siem(event)
def process_credentials(self):
"""Process and send credential information to SIEM"""
creds_file = self.output_dir / "credentials.csv"
if not creds_file.exists():
return
with open(creds_file, 'r') as f:
reader = csv.DictReader(f)
for row in reader:
event = {
'event_type': 'credential_exposure',
'source': 'networkminer',
'severity': 'HIGH',
'protocol': row.get('Protocol', ''),
'username': row.get('Username', ''),
'password': row.get('Password', ''),
'host': row.get('Host', ''),
'timestamp': row.get('Timestamp', '')
}
self.send_to_siem(event)
def process_files(self):
"""Process and send file information to SIEM"""
files_dir = self.output_dir / "AssembledFiles"
if not files_dir.exists():
return
for file_path in files_dir.rglob("*"):
if file_path.is_file():
try:
# Calculate file hash
with open(file_path, 'rb') as f:
file_hash = hashlib.sha256(f.read()).hexdigest()
event = {
'event_type': 'file_extraction',
'source': 'networkminer',
'filename': file_path.name,
'file_size': file_path.stat().st_size,
'file_hash': file_hash,
'extraction_path': str(file_path),
'timestamp': file_path.stat().st_mtime
}
self.send_to_siem(event)
except Exception as e:
print(f"Error processing file {file_path}: {e}")
def main():
output_dir = "/tmp/networkminer_output"
siem_endpoint = "https://your-siem.com/api/events"
api_key = "your-api-key"
integrator = NetworkMinerSIEMIntegrator(output_dir, siem_endpoint, api_key)
print("Sending NetworkMiner results to SIEM...")
integrator.process_hosts()
integrator.process_credentials()
integrator.process_files()
print("SIEM integration complete")
if __name__ == "__main__":
main()
Threat Intelligence Integration
python
#!/usr/bin/env python3
# networkminer-threat-intel.py
import csv
import requests
import json
from pathlib import Path
class ThreatIntelChecker:
def __init__(self, output_dir, virustotal_api_key):
self.output_dir = Path(output_dir)
self.vt_api_key = virustotal_api_key
self.vt_base_url = "https://www.virustotal.com/vtapi/v2"
def check_ip_reputation(self, ip_address):
"""Check IP reputation with VirusTotal"""
try:
url = f"{self.vt_base_url}/ip-address/report"
params = {
'apikey': self.vt_api_key,
'ip': ip_address
}
response = requests.get(url, params=params)
if response.status_code == 200:
return response.json()
except Exception as e:
print(f"Error checking IP {ip_address}: {e}")
return None
def check_file_hash(self, file_hash):
"""Check file hash with VirusTotal"""
try:
url = f"{self.vt_base_url}/file/report"
params = {
'apikey': self.vt_api_key,
'resource': file_hash
}
response = requests.get(url, params=params)
if response.status_code == 200:
return response.json()
except Exception as e:
print(f"Error checking hash {file_hash}: {e}")
return None
def analyze_hosts(self):
"""Analyze hosts for threat intelligence"""
hosts_file = self.output_dir / "hosts.csv"
if not hosts_file.exists():
return
print("=== Threat Intelligence Analysis - Hosts ===")
with open(hosts_file, 'r') as f:
reader = csv.DictReader(f)
for row in reader:
ip = row.get('IP', '')
if ip and self.is_external_ip(ip):
print(f"Checking IP: {ip}")
result = self.check_ip_reputation(ip)
if result and result.get('response_code') == 1:
detected_urls = result.get('detected_urls', [])
detected_samples = result.get('detected_communicating_samples', [])
if detected_urls or detected_samples:
print(f" ⚠️ THREAT DETECTED for {ip}")
print(f" Malicious URLs: {len(detected_urls)}")
print(f" Malicious Samples: {len(detected_samples)}")
else:
print(f" ✓ Clean reputation for {ip}")
def analyze_files(self):
"""Analyze extracted files for threats"""
files_dir = self.output_dir / "AssembledFiles"
if not files_dir.exists():
return
print("=== Threat Intelligence Analysis - Files ===")
for file_path in files_dir.rglob("*"):
if file_path.is_file() and file_path.stat().st_size > 0:
try:
import hashlib
with open(file_path, 'rb') as f:
file_hash = hashlib.sha256(f.read()).hexdigest()
print(f"Checking file: {file_path.name}")
result = self.check_file_hash(file_hash)
if result and result.get('response_code') == 1:
positives = result.get('positives', 0)
total = result.get('total', 0)
if positives > 0:
print(f" ⚠️ MALWARE DETECTED: {file_path.name}")
print(f" Detection: {positives}/{total} engines")
print(f" SHA256: {file_hash}")
else:
print(f" ✓ Clean file: {file_path.name}")
except Exception as e:
print(f"Error analyzing {file_path}: {e}")
def is_external_ip(self, ip):
"""Check if IP is external (not private)"""
import ipaddress
try:
ip_obj = ipaddress.ip_address(ip)
return not ip_obj.is_private
except:
return False
def main():
output_dir = "/tmp/networkminer_output"
virustotal_api_key = "your-virustotal-api-key"
checker = ThreatIntelChecker(output_dir, virustotal_api_key)
print("Starting threat intelligence analysis...")
checker.analyze_hosts()
checker.analyze_files()
print("Threat intelligence analysis complete")
if __name__ == "__main__":
main()
Reporting and Visualization
HTML Report Generator
python
#!/usr/bin/env python3
# networkminer-html-report.py
import csv
import json
from pathlib import Path
from datetime import datetime
class NetworkMinerHTMLReporter:
def __init__(self, output_dir, pcap_file):
self.output_dir = Path(output_dir)
self.pcap_file = pcap_file
self.report_data = {}
def collect_data(self):
"""Collect all analysis data"""
self.report_data = {
'pcap_file': self.pcap_file,
'analysis_date': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
'hosts': self.load_hosts(),
'sessions': self.load_sessions(),
'files': self.load_files(),
'credentials': self.load_credentials()
}
def load_hosts(self):
"""Load host data"""
hosts_file = self.output_dir / "hosts.csv"
hosts = []
if hosts_file.exists():
with open(hosts_file, 'r') as f:
reader = csv.DictReader(f)
hosts = list(reader)
return hosts
def load_sessions(self):
"""Load session data"""
sessions_file = self.output_dir / "sessions.csv"
sessions = []
if sessions_file.exists():
with open(sessions_file, 'r') as f:
reader = csv.DictReader(f)
sessions = list(reader)
return sessions
def load_files(self):
"""Load extracted files data"""
files_dir = self.output_dir / "AssembledFiles"
files = []
if files_dir.exists():
for file_path in files_dir.rglob("*"):
if file_path.is_file():
files.append({
'name': file_path.name,
'size': file_path.stat().st_size,
'path': str(file_path.relative_to(files_dir))
})
return files
def load_credentials(self):
"""Load credentials data"""
creds_file = self.output_dir / "credentials.csv"
credentials = []
if creds_file.exists():
with open(creds_file, 'r') as f:
reader = csv.DictReader(f)
credentials = list(reader)
return credentials
def generate_html_report(self):
"""Generate HTML report"""
html_template = """
<!DOCTYPE html>
<html>
<head>
<title>NetworkMiner Analysis Report</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.header { background-color: #f0f0f0; padding: 20px; border-radius: 5px; }
.section { margin: 20px 0; }
.section h2 { color: #333; border-bottom: 2px solid #ccc; }
table { border-collapse: collapse; width: 100%; margin: 10px 0; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
.stats { display: flex; gap: 20px; margin: 20px 0; }
.stat-box { background-color: #e9f4ff; padding: 15px; border-radius: 5px; text-align: center; }
.warning { background-color: #fff3cd; border: 1px solid #ffeaa7; padding: 10px; border-radius: 5px; }
</style>
</head>
<body>
<div class="header">
<h1>NetworkMiner Analysis Report</h1>
<p><strong>PCAP File:</strong> {pcap_file}</p>
<p><strong>Analysis Date:</strong> {analysis_date}</p>
</div>
<div class="stats">
<div class="stat-box">
<h3>{host_count}</h3>
<p>Unique Hosts</p>
</div>
<div class="stat-box">
<h3>{session_count}</h3>
<p>Network Sessions</p>
</div>
<div class="stat-box">
<h3>{file_count}</h3>
<p>Extracted Files</p>
</div>
<div class="stat-box">
<h3>{credential_count}</h3>
<p>Credentials Found</p>
</div>
</div>
{credentials_warning}
<div class="section">
<h2>Host Information</h2>
<table>
<tr>
<th>IP Address</th>
<th>MAC Address</th>
<th>Hostname</th>
<th>Operating System</th>
<th>Open Ports</th>
</tr>
{host_rows}
</table>
</div>
<div class="section">
<h2>Network Sessions</h2>
<table>
<tr>
<th>Client</th>
<th>Server</th>
<th>Protocol</th>
<th>Start Time</th>
<th>Duration</th>
</tr>
{session_rows}
</table>
</div>
<div class="section">
<h2>Extracted Files</h2>
<table>
<tr>
<th>Filename</th>
<th>Size (bytes)</th>
<th>Path</th>
</tr>
{file_rows}
</table>
</div>
{credentials_section}
</body>
</html>
"""
# Generate table rows
host_rows = ""
for host in self.report_data['hosts'][:20]: # Limit to first 20
host_rows += f"""
<tr>
<td>{host.get('IP', '')}</td>
<td>{host.get('MAC', '')}</td>
<td>{host.get('Hostname', '')}</td>
<td>{host.get('OS', '')}</td>
<td>{host.get('Open Ports', '')}</td>
</tr>
"""
session_rows = ""
for session in self.report_data['sessions'][:20]: # Limit to first 20
session_rows += f"""
<tr>
<td>{session.get('Client', '')}</td>
<td>{session.get('Server', '')}</td>
<td>{session.get('Protocol', '')}</td>
<td>{session.get('Start Time', '')}</td>
<td>{session.get('Duration', '')}</td>
</tr>
"""
file_rows = ""
for file_info in self.report_data['files'][:20]: # Limit to first 20
file_rows += f"""
<tr>
<td>{file_info['name']}</td>
<td>{file_info['size']}</td>
<td>{file_info['path']}</td>
</tr>
"""
# Credentials section
credentials_warning = ""
credentials_section = ""
if self.report_data['credentials']:
credentials_warning = """
<div class="warning">
<strong>⚠️ Warning:</strong> Clear-text credentials were found in the network traffic!
</div>
"""
credential_rows = ""
for cred in self.report_data['credentials']:
credential_rows += f"""
<tr>
<td>{cred.get('Protocol', '')}</td>
<td>{cred.get('Username', '')}</td>
<td>{'*' * len(cred.get('Password', ''))}</td>
<td>{cred.get('Host', '')}</td>
</tr>
"""
credentials_section = f"""
<div class="section">
<h2>Credentials (Passwords Hidden)</h2>
<table>
<tr>
<th>Protocol</th>
<th>Username</th>
<th>Password</th>
<th>Host</th>
</tr>
{credential_rows}
</table>
</div>
"""
# Fill template
html_content = html_template.format(
pcap_file=self.report_data['pcap_file'],
analysis_date=self.report_data['analysis_date'],
host_count=len(self.report_data['hosts']),
session_count=len(self.report_data['sessions']),
file_count=len(self.report_data['files']),
credential_count=len(self.report_data['credentials']),
credentials_warning=credentials_warning,
host_rows=host_rows,
session_rows=session_rows,
file_rows=file_rows,
credentials_section=credentials_section
)
# Save report
report_file = self.output_dir / "analysis_report.html"
with open(report_file, 'w') as f:
f.write(html_content)
print(f"HTML report generated: {report_file}")
return report_file
def main():
import sys
if len(sys.argv) != 3:
print("Usage: python3 networkminer-html-report.py <output_dir> <pcap_file>")
sys.exit(1)
output_dir = sys.argv[1]
pcap_file = sys.argv[2]
reporter = NetworkMinerHTMLReporter(output_dir, pcap_file)
reporter.collect_data()
reporter.generate_html_report()
if __name__ == "__main__":
main()
Best Practices
Analysis Workflow
bash
#!/bin/bash
# networkminer-best-practices.sh
PCAP_FILE="$1"
CASE_NAME="$2"
ANALYST="$3"
if [ $# -ne 3 ]; then
echo "Usage: $0 <pcap_file> <case_name> <analyst_name>"
exit 1
fi
# Create case directory structure
CASE_DIR="/cases/$CASE_NAME"
mkdir -p "$CASE_DIR"/{evidence,analysis,reports,notes}
# Copy evidence with hash verification
echo "Copying evidence file..."
cp "$PCAP_FILE" "$CASE_DIR/evidence/"
ORIGINAL_HASH=$(sha256sum "$PCAP_FILE" | cut -d' ' -f1)
COPY_HASH=$(sha256sum "$CASE_DIR/evidence/$(basename "$PCAP_FILE")" | cut -d' ' -f1)
if [ "$ORIGINAL_HASH" != "$COPY_HASH" ]; then
echo "ERROR: Hash mismatch during evidence copy!"
exit 1
fi
# Create case log
CASE_LOG="$CASE_DIR/notes/case_log.txt"
echo "Case: $CASE_NAME" > "$CASE_LOG"
echo "Analyst: $ANALYST" >> "$CASE_LOG"
echo "Start Time: $(date)" >> "$CASE_LOG"
echo "Evidence File: $(basename "$PCAP_FILE")" >> "$CASE_LOG"
echo "Evidence Hash: $ORIGINAL_HASH" >> "$CASE_LOG"
echo "---" >> "$CASE_LOG"
# Run NetworkMiner analysis
echo "Running NetworkMiner analysis..."
OUTPUT_DIR="$CASE_DIR/analysis/networkminer"
mkdir -p "$OUTPUT_DIR"
mono NetworkMiner.exe --output "$OUTPUT_DIR" "$CASE_DIR/evidence/$(basename "$PCAP_FILE")"
# Document analysis steps
echo "$(date): NetworkMiner analysis completed" >> "$CASE_LOG"
echo "Output directory: $OUTPUT_DIR" >> "$CASE_LOG"
# Generate reports
echo "Generating reports..."
python3 networkminer-html-report.py "$OUTPUT_DIR" "$(basename "$PCAP_FILE")" > "$CASE_DIR/reports/"
echo "Analysis complete. Case directory: $CASE_DIR"
Performance Optimization
text
NetworkMiner Performance Tips:
1. PCAP File Size:
- Free version limited to 5MB PCAP files
- Professional version handles larger files
- Split large PCAPs if using free version
2. Memory Usage:
- Close unnecessary applications
- Increase virtual memory if needed
- Monitor RAM usage during analysis
3. Processing Speed:
- Use SSD storage for faster I/O
- Process files locally (not over network)
- Close GUI tabs not in use
4. Batch Processing:
- Process multiple small files vs. one large file
- Use command-line mode for automation
- Schedule analysis during off-hours
Evidence Handling
bash
#!/bin/bash
# evidence-handling-checklist.sh
echo "NetworkMiner Evidence Handling Checklist"
echo "========================================"
echo "1. Evidence Acquisition:"
echo " □ Verify PCAP file integrity (hash)"
echo " □ Document chain of custody"
echo " □ Create working copy for analysis"
echo " □ Store original in secure location"
echo -e "\n2. Analysis Environment:"
echo " □ Use isolated analysis system"
echo " □ Document system configuration"
echo " □ Ensure sufficient disk space"
echo " □ Backup analysis results"
echo -e "\n3. Documentation:"
echo " □ Record analysis start/end times"
echo " □ Document tools and versions used"
echo " □ Save all output files"
echo " □ Create analysis summary report"
echo -e "\n4. Quality Assurance:"
echo " □ Verify extracted files integrity"
echo " □ Cross-reference findings"
echo " □ Peer review analysis results"
echo " □ Archive complete case file"
Troubleshooting
Common Issues
bash
# Issue: NetworkMiner won't start on Linux
# Solution: Install required Mono components
sudo apt install mono-complete libmono-winforms2.0-cil
# Issue: PCAP file too large (free version)
# Solution: Split PCAP file
editcap -c 1000000 large_file.pcap split_file.pcap
# Issue: Missing extracted files
# Check file extraction settings in GUI
# Verify PCAP contains actual file transfers
# Issue: No credentials found
# Ensure traffic contains clear-text protocols
# Check for encrypted connections (HTTPS, SSH)
# Issue: Slow performance
# Close unnecessary GUI tabs
# Increase system memory
# Use command-line mode for batch processing
Debug Mode
bash
# Enable verbose logging
mono --debug NetworkMiner.exe capture.pcap
# Check Mono version compatibility
mono --version
# Verify PCAP file format
file capture.pcap
tcpdump -r capture.pcap -c 10
# Test with sample PCAP
wget https://wiki.wireshark.org/SampleCaptures/http.cap
mono NetworkMiner.exe http.cap
Log Analysis
bash
# Check system logs for errors
journalctl -u mono --since "1 hour ago"
# Monitor resource usage
top -p $(pgrep mono)
# Check disk space
df -h /tmp
# Verify file permissions
ls -la NetworkMiner.exe
ls -la *.pcap
Resources
- NetworkMiner Official Website
- NetworkMiner Professional
- NetworkMiner Manual
- Sample PCAP Files
- Network Forensics Guide
This cheat sheet provides comprehensive guidance for using NetworkMiner for network forensic analysis. Regular practice with sample PCAP files and understanding of network protocols enhance analysis effectiveness.