Extracts indicators of compromise (IOCs) from malware samples, including file hashes, network indicators (IPs, domains, URLs, PCAP indicators), host artifacts (file paths, registry keys, mutexes), and behavioral patterns, using tools like CyberChef, then defangs and exports them in standard threat-intel formats. Use for IOC extraction, threat indicator harvesting, or building detection content from a sample.
Extracts indicators of compromise (IOCs) from malware samples, including file hashes, network indicators (IPs, domains, URLs, PCAP indicators), host artifacts (file paths, registry keys, mutexes), and behavioral patterns, using tools like CyberChef, then defangs and exports them in standard threat-intel formats. Use for IOC extraction, threat indicator harvesting, or building detection content from a sample.
Pull network indicators from strings, PCAP, and sandbox reports:
# Extract network IOCs from stringsimport re
withopen("malware_sample.exe", "rb") as f:
data = f.read()
# Extract ASCII and Unicode strings
ascii_strings = re.findall(b'[ -~]{4,}', data)
unicode_strings = re.findall(b'(?:[ -~]\x00){4,}', data)
all_strings = [s.decode('ascii', errors='ignore') for s in ascii_strings]
all_strings += [s.decode('utf-16-le', errors='ignore') for s in unicode_strings]
# IP addresses (excluding private ranges for C2 indicators)
ip_pattern = re.compile(r'\b(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\b')
ips = set()
for s in all_strings:
for ip in ip_pattern.findall(s):
# Filter out private/reserved ranges
octets = [int(o) for o in ip.split('.')]
if octets[0] notin [10, 127, 0] andnot (octets[0] == 172and16 <= octets[1] <= 31) andnot (octets[0] == 192and octets[1] == 168):
ips.add(ip)
# Domain names
domain_pattern = re.compile(r'\b[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z]{2,})+\b')
domains = set()
for s in all_strings:
for d in domain_pattern.findall(s):
ifnot d.endswith(('.dll', '.exe', '.sys', '.com.au')):
domains.add(d)
# URLs
url_pattern = re.compile(r'https?://[^\s<>"{}|\\^`\[\]]+')
urls = set()
for s in all_strings:
for u in url_pattern.findall(s):
urls.add(u)
print("NETWORK IOCs:")
print(f" IPs: {ips}")
print(f" Domains: {domains}")
print(f" URLs: {urls}")
Step 3: Extract Host-Based IOCs
Identify file paths, registry keys, mutexes, and services:
# Extract host-based IOCs from sandbox reportimport json
withopen("cuckoo_report.json") as f:
report = json.load(f)
print("HOST IOCs:")
# File paths created or modifiedprint("\nFile Paths:")
for f in report["behavior"]["summary"].get("files", []):
ifany(p in f.lower() for p in ["temp", "appdata", "system32", "programdata"]):
print(f" [DROPPED] {f}")
# Registry keys for persistenceprint("\nRegistry Keys:")
for key in report["behavior"]["summary"].get("write_keys", []):
ifany(p in key.lower() for p in ["run", "service", "startup", "shell"]):
print(f" [PERSIST] {key}")
# Mutexes (unique to malware family)print("\nMutexes:")
for mutex in report["behavior"]["summary"].get("mutexes", []):
if mutex notin ["Local\\!IETld!Mutex", "RasPbFile"]: # Filter known Windows mutexesprint(f" [MUTEX] {mutex}")
# Created servicesprint("\nServices:")
for svc in report["behavior"]["summary"].get("started_services", []):
print(f" [SERVICE] {svc}")
Defang indicators for safe sharing and validate against threat intelligence:
# Defang IOCs for safe sharingdefdefang_ip(ip):
return ip.replace(".", "[.]")
defdefang_url(url):
return url.replace("http", "hxxp").replace(".", "[.]")
defdefang_domain(domain):
return domain.replace(".", "[.]")
# Validate IOCs against VirusTotalimport requests
VT_API_KEY = "your_api_key"defcheck_vt_ip(ip):
resp = requests.get(f"https://www.virustotal.com/api/v3/ip_addresses/{ip}",
headers={"x-apikey": VT_API_KEY})
data = resp.json()
stats = data["data"]["attributes"]["last_analysis_stats"]
return stats["malicious"]
defcheck_vt_domain(domain):
resp = requests.get(f"https://www.virustotal.com/api/v3/domains/{domain}",
headers={"x-apikey": VT_API_KEY})
data = resp.json()
stats = data["data"]["attributes"]["last_analysis_stats"]
return stats["malicious"]
# Validate each IOCfor ip in ips:
detections = check_vt_ip(ip)
print(f" {defang_ip(ip)} - VT: {detections} detections")
Step 6: Export IOCs in Standard Formats
Generate structured IOC outputs for sharing and ingestion:
# Export as STIX 2.1 bundlefrom stix2 import Indicator, Bundle, Malware, Relationship
import datetime
indicators = []
# File hash indicator
indicators.append(Indicator(
name="Malware SHA-256 Hash",
pattern=f"[file:hashes.'SHA-256' = '{sha256_hash}']",
pattern_type="stix",
valid_from=datetime.datetime.now(datetime.timezone.utc),
labels=["malicious-activity"]
))
# IP indicatorfor ip in ips:
indicators.append(Indicator(
name=f"C2 IP Address {ip}",
pattern=f"[ipv4-addr:value = '{ip}']",
pattern_type="stix",
valid_from=datetime.datetime.now(datetime.timezone.utc),
labels=["malicious-activity"]
))
# Domain indicatorfor domain in domains:
indicators.append(Indicator(
name=f"C2 Domain {domain}",
pattern=f"[domain-name:value = '{domain}']",
pattern_type="stix",
valid_from=datetime.datetime.now(datetime.timezone.utc),
labels=["malicious-activity"]
))
bundle = Bundle(objects=indicators)
withopen("iocs_stix.json", "w") as f:
f.write(bundle.serialize(pretty=True))
# Export as CSV for SIEM ingestionimport csv
withopen("iocs.csv", "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["type", "value", "context", "confidence"])
writer.writerow(["sha256", sha256_hash, "malware_sample", "high"])
for ip in ips:
writer.writerow(["ipv4", ip, "c2_server", "high"])
for domain in domains:
writer.writerow(["domain", domain, "c2_domain", "high"])
for url in urls:
writer.writerow(["url", url, "c2_url", "high"])
Key Concepts
Term
Definition
IOC (Indicator of Compromise)
Forensic artifact observed in a network or system that indicates a potential intrusion: hashes, IPs, domains, file paths, registry keys
Defanging
Modifying IOCs to prevent accidental activation (e.g., replacing dots with [.] in URLs and IPs for safe sharing in reports)
Imphash
MD5 hash of the import table functions in a PE file; samples from the same malware family often share the same imphash
STIX/TAXII
Structured Threat Information Expression / Trusted Automated Exchange; standards for encoding and transmitting threat intelligence
JA3/JA3S
TLS client/server fingerprint based on ClientHello/ServerHello parameters; identifies specific malware families by their TLS implementation
Fuzzy Hashing (ssdeep)
Context-triggered piecewise hashing that identifies similar files even with minor modifications; useful for malware variant detection
MISP
Malware Information Sharing Platform; open-source threat intelligence platform for collecting, storing, and sharing IOCs
Tools & Systems
iocextract (Python): Automated IOC extraction library supporting IPs, URLs, domains, hashes, and YARA rules from text
MISP: Open-source threat intelligence sharing platform for structured IOC management and distribution
CyberChef: Web-based tool for decoding, decrypting, and transforming data useful for deobfuscating encoded IOCs
tshark: Command-line network protocol analyzer for extracting network IOCs from PCAP files
VirusTotal: Online service for validating and enriching IOCs with community detection results and threat intelligence
Common Scenarios
Scenario: Building a Comprehensive IOC Package from a Ransomware Sample
Context: A ransomware incident requires rapid IOC extraction for blocking across the enterprise while the full investigation continues. Multiple data sources are available: the sample binary, PCAP from network monitoring, and a Cuckoo sandbox report.
Approach:
Compute all file hashes (MD5, SHA-1, SHA-256, imphash, ssdeep) for the ransomware binary and any dropped files
Extract network IOCs from strings in the binary (hardcoded C2 addresses)
Parse the PCAP for DNS queries, HTTP requests, and TLS SNI fields
Extract host IOCs from the sandbox report (file paths, registry keys, mutexes, ransom note filenames)
Validate all network IOCs against VirusTotal to confirm malicious status and check for known associations
Defang all indicators and compile into STIX 2.1 format for sharing and CSV for SIEM ingestion
Submit to MISP event for organizational and community sharing
Pitfalls:
Including IP addresses of legitimate CDNs or cloud services without validating context (e.g., AWS IPs used for hosting, not inherently malicious)
Not defanging URLs and IPs in reports, leading to accidental clicks or DNS resolution
Extracting strings from packed binaries (IOCs from packed samples are unreliable; unpack first)
Forgetting to include dropped file hashes (the initial dropper and the final payload are separate IOCs)