
Collecting Indicators Of Compromise
- 143 installs
- 27.3k repo stars
- Updated August 2, 2026
- mukul975/anthropic-cybersecurity-skills
Helps with ai & agent building tasks.
About
collecting-indicators-of-compromise is a Claude Code skill in the AI & Agent Building category.
- collecting-indicators-of-compromise
- AI & Agent Building
- AI-coding skill
Collecting Indicators Of Compromise by the numbers
- 143 all-time installs (skills.sh)
- +3 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #3,442 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill collecting-indicators-of-compromiseAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 143 |
|---|---|
| repo stars | ★ 27.3k |
| Last updated | August 2, 2026 |
| Repository | mukul975/anthropic-cybersecurity-skills ↗ |
What it does
Helps with ai & agent building tasks.
Files
Collecting Indicators of Compromise
When to Use
- During active incident response to identify and block adversary infrastructure
- Post-incident to document all observed adversary artifacts for future detection
- When sharing threat intelligence with ISACs, sector partners, or law enforcement
- When building detection rules in SIEM, EDR, or network security tools
- When enriching IOCs with threat intelligence context for risk scoring
Do not use for behavioral TTP analysis without accompanying technical indicators; use MITRE ATT&CK mapping for behavioral characterization.
Prerequisites
- Access to incident evidence sources: SIEM logs, EDR telemetry, memory dumps, disk images, network captures
- Threat intelligence platform (MISP, OpenCTI, ThreatConnect) for IOC management and sharing
- IOC enrichment tools: VirusTotal, OTX (AlienVault Open Threat Exchange), Shodan, DomainTools
- STIX 2.1 knowledge for structured IOC representation
- Sharing agreements with relevant ISACs (FS-ISAC, H-ISAC, IT-ISAC) or sector partners
Workflow
Step 1: Identify IOC Categories
Collect indicators across all categories from incident evidence:
Network Indicators:
- IP addresses (C2 servers, staging servers, exfiltration destinations)
- Domain names (C2 domains, phishing domains, DGA domains)
- URLs (malware download, C2 check-in, exfiltration endpoints)
- JA3/JA3S hashes (TLS client/server fingerprints)
- User-Agent strings (custom or unusual HTTP headers)
- DNS query patterns (tunneling signatures, DGA patterns)
Host Indicators:
- File hashes (MD5, SHA-1, SHA-256 of malware, tools, scripts)
- File paths (known malware installation directories)
- Registry keys (persistence mechanisms, configuration storage)
- Scheduled tasks and service names (persistence)
- Mutex/event names (malware instance synchronization)
- Named pipes (C2 communication channels, e.g., Cobalt Strike)
Email Indicators:
- Sender addresses and domains (spoofed or attacker-controlled)
- Subject lines and body content patterns
- Attachment names and hashes
- Embedded URLs
- Email header anomalies (SPF/DKIM/DMARC failures)
Step 2: Extract IOCs from Evidence Sources
Systematically extract indicators from each evidence source:
From SIEM/Log Analysis:
# Extract unique destination IPs from firewall logs
index=firewall action=blocked
| stats count by dest_ip
| where count > 100
# Extract domains from DNS query logs
index=dns query=*evil* OR query=*c2*
| stats count by queryFrom Memory Forensics:
# Extract network connections
vol -f memory.raw windows.netscan | grep ESTABLISHED
# Extract strings from suspicious process memory
vol -f memory.raw windows.memmap --pid 3847 --dump
strings -n 8 pid.3847.dmp | grep -E "(http|https)://"From Malware Analysis:
Sandbox Report IOC Extraction:
- Dropped files: 3 (hashes extracted)
- DNS queries: update.evil[.]com, cdn.malware[.]net
- HTTP connections: POST to https://185.220.101[.]42/gate.php
- Registry modified: HKCU\Software\Microsoft\Windows\CurrentVersion\Run\svcupdate
- Mutex created: Global\MTX_0x1234ABCD
- Named pipe: \\.\pipe\MSSE-1234-serverStep 3: Enrich IOCs with Context
Add threat intelligence context to each indicator:
IOC Enrichment Report:
━━━━━━━━━━━━━━━━━━━━━
IP: 185.220.101.42
VirusTotal: 12/89 vendors flag as malicious
Shodan: Open ports: 443, 8443, 80
Geolocation: Netherlands, AS208476
First Seen: 2025-10-01
Threat Intel: Associated with Qakbot C2 infrastructure
Confidence: High
TLP: AMBER
Domain: update.evil[.]com
Registration: 2025-10-28 (recently registered)
Registrar: Namecheap
WHOIS Privacy: Yes
VirusTotal: 8/89 vendors flag as malicious
DNS History: Resolved to 185.220.101.42, 91.215.85.17
Confidence: High
TLP: AMBERStep 4: Score and Prioritize IOCs
Assign confidence and risk scores to each indicator:
| Score | Confidence Level | Criteria |
|---|---|---|
| 90-100 | Confirmed Malicious | Multiple TI sources confirm, observed in active attack |
| 70-89 | Highly Suspicious | Single TI source confirms, behavioral analysis supports |
| 50-69 | Suspicious | Limited TI data, contextually suspicious |
| 30-49 | Unconfirmed | No TI matches, but anomalous in environment |
| 0-29 | Likely Benign | False positive indicators or legitimate infrastructure |
Step 5: Distribute IOCs for Detection and Blocking
Push IOCs to defensive systems for immediate protection:
- Firewall/IPS: Block C2 IPs and domains
- DNS: Sinkhole malicious domains
- EDR: Add file hashes to blocklist, create custom IOC watchlists
- Email Gateway: Block sender domains, attachment hashes, malicious URLs
- SIEM: Create correlation searches for IOC matches
- Web Proxy: Block URLs and domains in web filtering policy
Step 6: Share IOCs with Partners
Package IOCs in STIX 2.1 format for sharing:
{
"type": "indicator",
"spec_version": "2.1",
"id": "indicator--a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"created": "2025-11-15T18:00:00Z",
"modified": "2025-11-15T18:00:00Z",
"name": "Qakbot C2 Server IP",
"indicator_types": ["malicious-activity"],
"pattern": "[ipv4-addr:value = '185.220.101.42']",
"pattern_type": "stix",
"valid_from": "2025-11-15T14:23:00Z",
"confidence": 95,
"labels": ["c2", "qakbot"],
"object_marking_refs": ["marking-definition--f88d31f6-486f-44da-b317-01333bde0b82"]
}Submit to MISP, ISAC portals, and TAXII servers per sharing agreements.
Key Concepts
| Term | Definition |
|---|---|
| IOC (Indicator of Compromise) | Technical artifact observed during a security incident that indicates adversary presence (hash, IP, domain, etc.) |
| TLP (Traffic Light Protocol) | Standard for classifying the sharing restrictions of threat intelligence: WHITE, GREEN, AMBER, AMBER+STRICT, RED |
| STIX (Structured Threat Information Expression) | Standard language for representing cyber threat intelligence in a structured, machine-readable format |
| TAXII (Trusted Automated Exchange of Intelligence Information) | Transport protocol for sharing STIX-formatted threat intelligence between organizations |
| Confidence Score | Numerical rating (0-100) indicating the analyst's certainty that an indicator is truly malicious |
| IOC Lifecycle | Process of creating, validating, distributing, and eventually retiring indicators as they lose relevance |
| Defanging | Practice of modifying malicious URLs and domains in reports to prevent accidental clicks (e.g., evil[.]com) |
Tools & Systems
- MISP: Open-source threat intelligence sharing platform for managing, storing, and distributing IOCs
- VirusTotal: Multi-engine malware scanning and threat intelligence platform for IOC enrichment
- OpenCTI: Open-source cyber threat intelligence platform supporting STIX 2.1 natively
- Yeti: Open-source platform for organizing observables, indicators, and TTPs
- CyberChef: GCHQ's data transformation tool useful for decoding, defanging, and formatting IOCs
Common Scenarios
Scenario: Post-Incident IOC Package for ISAC Sharing
Context: After responding to a Qakbot infection that led to Cobalt Strike deployment, the IR team must package all IOCs for sharing with the Financial Services ISAC (FS-ISAC).
Approach: 1. Compile all network, host, and email indicators from the investigation 2. Enrich each IOC with VirusTotal and MISP correlation data 3. Assign confidence scores based on direct observation vs. secondary correlation 4. Mark all IOCs with TLP:AMBER for partner sharing 5. Export as STIX 2.1 bundle and submit to FS-ISAC TAXII feed 6. Create a human-readable IOC summary report for email distribution
Pitfalls:
- Including internal IP addresses or hostnames in shared IOC packages (information leakage)
- Sharing IOCs at TLP:WHITE that should be restricted to TLP:AMBER
- Not defanging URLs and domains in human-readable reports
- Sharing IP addresses of legitimate CDNs or cloud providers as malicious IOCs
Output Format
INDICATOR OF COMPROMISE REPORT
================================
Incident: INC-2025-1547
Date: 2025-11-15
TLP: AMBER
Sharing: FS-ISAC, internal SOC
NETWORK INDICATORS
Type | Value | Confidence | Context
---------|--------------------------|------------|--------
IPv4 | 185.220.101[.]42 | 95 | Qakbot C2 server
IPv4 | 91.215.85[.]17 | 90 | Cobalt Strike C2
Domain | update.evil[.]com | 95 | Staging domain
URL | hxxps://185.220[.]101.42/gate.php | 95 | C2 check-in
JA3 | a0e9f5d64349fb13191bc7...| 80 | Qakbot TLS fingerprint
HOST INDICATORS
Type | Value | Confidence | Context
---------|--------------------------|------------|--------
SHA-256 | a1b2c3d4e5f6... | 100 | Qakbot dropper
SHA-256 | b2c3d4e5f6a7... | 100 | Cobalt Strike beacon
FilePath | C:\Users\*\AppData\Local\Temp\update.exe | 85 | Dropper location
RegKey | HKCU\...\Run\svcupdate | 90 | Persistence
Mutex | Global\MTX_0x1234ABCD | 95 | Qakbot instance lock
Task | WindowsUpdate | 90 | Scheduled task persistence
EMAIL INDICATORS
Type | Value | Confidence | Context
---------|--------------------------|------------|--------
Sender | billing@spoofed[.]com | 95 | Phishing sender
Subject | "Invoice-Nov2025" | 70 | Phishing subject line
Hash | c3d4e5f6a7b8... | 100 | Malicious .docm attachment
TOTAL: 14 indicators | HIGH confidence avg: 91
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to the Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by the Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding any notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. Please do not remove or change
the license header comment from a contributed file except when
necessary.
Copyright 2026 mukul975
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
API Reference: IOC Collection Agent
Overview
Extracts indicators of compromise from text/files using regex patterns, enriches them via VirusTotal and MalwareBazaar APIs, assigns confidence scores, and exports as a STIX 2.1 bundle.
Dependencies
| Package | Version | Purpose |
|---|---|---|
| requests | >=2.28 | API enrichment calls |
| stix2 | >=3.0 | STIX 2.1 bundle creation |
CLI Usage
python agent.py --input-file incident_report.txt --vt-key <key> --output iocs.json
python agent.py --input-text "C2 at 185.220.101.42 hash a1b2c3..." --output iocs.jsonKey Functions
extract_iocs_from_text(text)
Extracts IPv4 addresses, domains, SHA-256/MD5 hashes, and URLs using regex patterns.
extract_iocs_from_file(file_path)
Reads a file and delegates to extract_iocs_from_text.
enrich_ip_virustotal(ip_address, api_key)
Queries VirusTotal v3 API for IP reputation (malicious count, ASN, country).
enrich_hash_malwarebazaar(file_hash)
Queries MalwareBazaar for file hash metadata (family, type, tags).
enrich_domain_abuseipdb(domain, api_key)
Checks domain reputation via AbuseIPDB API (abuse confidence, report count).
score_ioc(ioc_type, enrichment_data)
Assigns confidence score (0-100) based on enrichment results and detection counts.
export_stix_bundle(iocs_with_scores, output_path)
Creates STIX 2.1 Indicator objects and exports as a Bundle JSON file.
External APIs Used
| API | Endpoint | Auth | Purpose |
|---|---|---|---|
| VirusTotal v3 | /api/v3/ip_addresses/{ip} | API key header | IP reputation |
| MalwareBazaar | https://mb-api.abuse.ch/api/v1/ | None | Hash lookup |
| AbuseIPDB | /api/v2/check | API key header | Domain/IP reputation |
IOC Types Supported
| Type | Regex Pattern | STIX Pattern |
|---|---|---|
| IPv4 | \b(?:\d{1,3}\.){3}\d{1,3}\b | [ipv4-addr:value = '...'] |
| Domain | \b(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}\b | [domain-name:value = '...'] |
| SHA-256 | \b[a-fA-F0-9]{64}\b | [file:hashes.'SHA-256' = '...'] |
| MD5 | \b[a-fA-F0-9]{32}\b | [file:hashes.MD5 = '...'] |
| URL | https?://[^\s"'<>]+ | [url:value = '...'] |
#!/usr/bin/env python3
"""IOC Collection Agent - Extracts, enriches, and exports indicators of compromise."""
import json
import re
import logging
import argparse
from datetime import datetime
import requests
from stix2 import Indicator, Bundle
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)
IPV4_PATTERN = re.compile(r"\b(?:\d{1,3}\.){3}\d{1,3}\b")
DOMAIN_PATTERN = re.compile(r"\b(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}\b")
SHA256_PATTERN = re.compile(r"\b[a-fA-F0-9]{64}\b")
MD5_PATTERN = re.compile(r"\b[a-fA-F0-9]{32}\b")
URL_PATTERN = re.compile(r"https?://[^\s\"'<>]+")
def extract_iocs_from_text(text):
"""Extract IOCs (IPs, domains, hashes, URLs) from unstructured text."""
iocs = {
"ipv4": list(set(IPV4_PATTERN.findall(text))),
"domain": list(set(DOMAIN_PATTERN.findall(text))),
"sha256": list(set(SHA256_PATTERN.findall(text))),
"md5": list(set(MD5_PATTERN.findall(text))),
"url": list(set(URL_PATTERN.findall(text))),
}
total = sum(len(v) for v in iocs.values())
logger.info("Extracted %d IOCs from text input", total)
return iocs
def extract_iocs_from_file(file_path):
"""Extract IOCs from a file (text report, log file, etc.)."""
with open(file_path, "r", errors="ignore") as f:
content = f.read()
return extract_iocs_from_text(content)
def enrich_ip_virustotal(ip_address, api_key):
"""Enrich an IP address using VirusTotal API."""
url = f"https://www.virustotal.com/api/v3/ip_addresses/{ip_address}"
headers = {"x-apikey": api_key}
resp = requests.get(url, headers=headers, timeout=30)
if resp.status_code == 200:
data = resp.json()["data"]["attributes"]
result = {
"ip": ip_address,
"malicious": data.get("last_analysis_stats", {}).get("malicious", 0),
"country": data.get("country", "unknown"),
"asn": data.get("asn", 0),
"as_owner": data.get("as_owner", "unknown"),
}
logger.info("VT enrichment for %s: %d malicious detections", ip_address, result["malicious"])
return result
return {"ip": ip_address, "error": resp.status_code}
def enrich_hash_malwarebazaar(file_hash):
"""Enrich a file hash using MalwareBazaar API."""
url = "https://mb-api.abuse.ch/api/v1/"
resp = requests.post(url, data={"query": "get_info", "hash": file_hash}, timeout=30)
result = resp.json()
if result.get("query_status") == "ok":
sample = result["data"][0]
return {
"hash": file_hash,
"family": sample.get("signature", "unknown"),
"file_type": sample.get("file_type", "unknown"),
"tags": sample.get("tags", []),
"first_seen": sample.get("first_seen"),
}
return {"hash": file_hash, "status": "not_found"}
def enrich_domain_abuseipdb(domain, api_key):
"""Check domain reputation via AbuseIPDB."""
url = "https://api.abuseipdb.com/api/v2/check"
headers = {"Key": api_key, "Accept": "application/json"}
resp = requests.get(url, headers=headers, params={"ipAddress": domain}, timeout=30)
if resp.status_code == 200:
data = resp.json()["data"]
return {
"domain": domain,
"abuse_confidence": data.get("abuseConfidenceScore", 0),
"total_reports": data.get("totalReports", 0),
"country": data.get("countryCode", "unknown"),
}
return {"domain": domain, "error": resp.status_code}
def score_ioc(ioc_type, enrichment_data):
"""Assign confidence score (0-100) based on enrichment results."""
if ioc_type == "ipv4":
malicious_count = enrichment_data.get("malicious", 0)
if malicious_count >= 10:
return 95
elif malicious_count >= 5:
return 80
elif malicious_count >= 1:
return 60
return 30
elif ioc_type in ("sha256", "md5"):
if enrichment_data.get("family") and enrichment_data["family"] != "unknown":
return 95
return 50
return 50
def export_stix_bundle(iocs_with_scores, output_path):
"""Export IOCs as a STIX 2.1 bundle."""
pattern_map = {
"ipv4": lambda v: f"[ipv4-addr:value = '{v}']",
"domain": lambda v: f"[domain-name:value = '{v}']",
"url": lambda v: f"[url:value = '{v}']",
"sha256": lambda v: f"[file:hashes.'SHA-256' = '{v}']",
"md5": lambda v: f"[file:hashes.MD5 = '{v}']",
}
stix_indicators = []
for ioc in iocs_with_scores:
ioc_type = ioc["type"]
pattern_fn = pattern_map.get(ioc_type)
if pattern_fn:
indicator = Indicator(
name=f"{ioc_type}: {ioc['value']}",
pattern=pattern_fn(ioc["value"]),
pattern_type="stix",
valid_from=datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ"),
confidence=ioc.get("confidence", 50),
labels=[ioc_type],
)
stix_indicators.append(indicator)
bundle = Bundle(objects=stix_indicators)
with open(output_path, "w") as f:
f.write(bundle.serialize(pretty=True))
logger.info("STIX bundle exported: %d indicators to %s", len(stix_indicators), output_path)
def generate_ioc_report(iocs_with_scores):
"""Print a formatted IOC report."""
lines = [
"INDICATOR OF COMPROMISE REPORT",
"=" * 40,
f"Date: {datetime.utcnow().strftime('%Y-%m-%d %H:%M UTC')}",
f"Total IOCs: {len(iocs_with_scores)}",
"",
]
for ioc_type in ["ipv4", "domain", "sha256", "md5", "url"]:
typed = [i for i in iocs_with_scores if i["type"] == ioc_type]
if typed:
lines.append(f"\n{ioc_type.upper()} ({len(typed)}):")
for ioc in typed[:10]:
lines.append(f" {ioc['value'][:60]:60s} Confidence: {ioc.get('confidence', 'N/A')}")
print("\n".join(lines))
def main():
parser = argparse.ArgumentParser(description="IOC Collection Agent")
parser.add_argument("--input-file", help="File to extract IOCs from")
parser.add_argument("--input-text", help="Text string to extract IOCs from")
parser.add_argument("--vt-key", help="VirusTotal API key for enrichment")
parser.add_argument("--output", default="ioc_bundle.json", help="STIX bundle output")
args = parser.parse_args()
raw_iocs = {}
if args.input_file:
raw_iocs = extract_iocs_from_file(args.input_file)
elif args.input_text:
raw_iocs = extract_iocs_from_text(args.input_text)
iocs_with_scores = []
for ioc_type, values in raw_iocs.items():
for value in values:
entry = {"type": ioc_type, "value": value, "confidence": 50}
if ioc_type == "ipv4" and args.vt_key:
enrichment = enrich_ip_virustotal(value, args.vt_key)
entry["confidence"] = score_ioc("ipv4", enrichment)
entry["enrichment"] = enrichment
elif ioc_type in ("sha256", "md5"):
enrichment = enrich_hash_malwarebazaar(value)
entry["confidence"] = score_ioc(ioc_type, enrichment)
entry["enrichment"] = enrichment
iocs_with_scores.append(entry)
generate_ioc_report(iocs_with_scores)
export_stix_bundle(iocs_with_scores, args.output)
if __name__ == "__main__":
main()