mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-24 13:40:57 +03:00
Complete folder anatomy for all 649 cybersecurity skills + update LICENSE to Mahipal
- Add scripts/agent.py and references/api-reference.md to all remaining skills - Update all 648 LICENSE files: copyright now reads 'Mahipal' - Add implementing-security-monitoring-with-datadog (new skill with full anatomy) - All 649 skills now have: SKILL.md, LICENSE, scripts/agent.py, references/api-reference.md
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Agent for performing malware IOC extraction from files, reports, and samples."""
|
||||
|
||||
import json
|
||||
import argparse
|
||||
import re
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
from collections import Counter
|
||||
|
||||
|
||||
IOC_PATTERNS = {
|
||||
"ipv4": re.compile(r"\b(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\b"),
|
||||
"ipv6": re.compile(r"\b(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\b"),
|
||||
"domain": re.compile(r"\b(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+(?:com|net|org|io|ru|cn|xyz|top|info|biz|cc|tk|ml|ga|cf|gq|pw)\b"),
|
||||
"url": re.compile(r"https?://[^\s<>\"'\)]+"),
|
||||
"email": re.compile(r"\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\b"),
|
||||
"md5": re.compile(r"\b[a-f0-9]{32}\b"),
|
||||
"sha1": re.compile(r"\b[a-f0-9]{40}\b"),
|
||||
"sha256": re.compile(r"\b[a-f0-9]{64}\b"),
|
||||
"cve": re.compile(r"CVE-\d{4}-\d{4,7}", re.I),
|
||||
"registry_key": re.compile(r"(?:HKLM|HKCU|HKCR|HKU|HKCC)\\[^\s\"']+"),
|
||||
"file_path_windows": re.compile(r"[A-Z]:\\(?:[^\s\\\"]+\\)*[^\s\\\"]+\.\w{1,5}"),
|
||||
"file_path_unix": re.compile(r"/(?:tmp|var|etc|usr|home|opt|bin|sbin)/[^\s\"']+"),
|
||||
"mutex": re.compile(r"(?:Global|Local)\\[^\s\"']+"),
|
||||
"bitcoin_addr": re.compile(r"\b[13][a-km-zA-HJ-NP-Z1-9]{25,34}\b"),
|
||||
"mitre_technique": re.compile(r"T\d{4}(?:\.\d{3})?"),
|
||||
"user_agent": re.compile(r"Mozilla/5\.0[^\n\"]{20,200}"),
|
||||
}
|
||||
|
||||
DEFANGED_PATTERNS = {
|
||||
"ip_defanged": (re.compile(r"\b\d+\[\.\]\d+\[\.\]\d+\[\.\]\d+\b"), lambda m: m.group().replace("[.]", ".")),
|
||||
"url_defanged": (re.compile(r"hxxps?://[^\s]+"), lambda m: m.group().replace("hxxp", "http")),
|
||||
"domain_defanged": (re.compile(r"\b\S+\[\.\]\S+\b"), lambda m: m.group().replace("[.]", ".")),
|
||||
}
|
||||
|
||||
|
||||
def extract_iocs_from_text(text):
|
||||
"""Extract all IOC types from raw text."""
|
||||
refanged = text
|
||||
for name, (pattern, fixer) in DEFANGED_PATTERNS.items():
|
||||
refanged = pattern.sub(fixer, refanged)
|
||||
extracted = {}
|
||||
for ioc_type, pattern in IOC_PATTERNS.items():
|
||||
matches = list(set(pattern.findall(refanged)))
|
||||
if matches:
|
||||
extracted[ioc_type] = sorted(matches)[:200]
|
||||
private_ip = re.compile(r"^(?:10\.|172\.(?:1[6-9]|2\d|3[01])\.|192\.168\.|127\.)")
|
||||
if "ipv4" in extracted:
|
||||
extracted["ipv4"] = [ip for ip in extracted["ipv4"] if not private_ip.match(ip)]
|
||||
return extracted
|
||||
|
||||
|
||||
def extract_from_file(file_path):
|
||||
"""Extract IOCs from a file (text, PDF text, or report)."""
|
||||
content = Path(file_path).read_text(encoding="utf-8", errors="replace")
|
||||
iocs = extract_iocs_from_text(content)
|
||||
total = sum(len(v) for v in iocs.values())
|
||||
return {
|
||||
"source": file_path, "total_iocs": total,
|
||||
"by_type": {k: len(v) for k, v in iocs.items()},
|
||||
"indicators": iocs,
|
||||
}
|
||||
|
||||
|
||||
def hash_file(file_path):
|
||||
"""Calculate file hashes for malware sample identification."""
|
||||
data = Path(file_path).read_bytes()
|
||||
return {
|
||||
"file": file_path,
|
||||
"size_bytes": len(data),
|
||||
"md5": hashlib.md5(data).hexdigest(),
|
||||
"sha1": hashlib.sha1(data).hexdigest(),
|
||||
"sha256": hashlib.sha256(data).hexdigest(),
|
||||
}
|
||||
|
||||
|
||||
def extract_strings(file_path, min_length=6):
|
||||
"""Extract printable strings from binary file."""
|
||||
data = Path(file_path).read_bytes()
|
||||
ascii_strings = re.findall(rb"[\x20-\x7e]{%d,}" % min_length, data)
|
||||
wide_strings = re.findall(rb"(?:[\x20-\x7e]\x00){%d,}" % min_length, data)
|
||||
all_strings = [s.decode("ascii", errors="replace") for s in ascii_strings]
|
||||
all_strings += [s.decode("utf-16-le", errors="replace") for s in wide_strings]
|
||||
iocs = extract_iocs_from_text("\n".join(all_strings))
|
||||
suspicious = []
|
||||
suspicious_kw = ["http", "socket", "connect", "download", "upload", "exec", "cmd.exe",
|
||||
"powershell", "reg add", "CreateRemoteThread", "VirtualAlloc", "WriteProcessMemory",
|
||||
"LoadLibrary", "GetProcAddress", "WinExec", "ShellExecute"]
|
||||
for s in all_strings:
|
||||
if any(kw.lower() in s.lower() for kw in suspicious_kw):
|
||||
suspicious.append(s[:200])
|
||||
return {
|
||||
"file": file_path, "total_strings": len(all_strings),
|
||||
"suspicious_strings": suspicious[:30],
|
||||
"extracted_iocs": {k: len(v) for k, v in iocs.items()},
|
||||
"ioc_details": iocs,
|
||||
}
|
||||
|
||||
|
||||
def generate_ioc_report(file_path, output=None):
|
||||
"""Generate comprehensive IOC extraction report."""
|
||||
hashes = hash_file(file_path)
|
||||
strings = extract_strings(file_path)
|
||||
report = {
|
||||
"generated": datetime.utcnow().isoformat() if "datetime" in dir() else "",
|
||||
"file_info": hashes,
|
||||
"strings_analysis": {
|
||||
"total": strings["total_strings"],
|
||||
"suspicious": strings["suspicious_strings"],
|
||||
},
|
||||
"extracted_iocs": strings["ioc_details"],
|
||||
"ioc_summary": strings["extracted_iocs"],
|
||||
}
|
||||
if output:
|
||||
with open(output, "w") as f:
|
||||
json.dump(report, f, indent=2)
|
||||
return report
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Malware IOC Extraction Agent")
|
||||
sub = parser.add_subparsers(dest="command")
|
||||
t = sub.add_parser("text", help="Extract IOCs from text/report file")
|
||||
t.add_argument("--file", required=True)
|
||||
h = sub.add_parser("hash", help="Calculate file hashes")
|
||||
h.add_argument("--file", required=True)
|
||||
s = sub.add_parser("strings", help="Extract strings and IOCs from binary")
|
||||
s.add_argument("--file", required=True)
|
||||
s.add_argument("--min-length", type=int, default=6)
|
||||
r = sub.add_parser("report", help="Generate full IOC report")
|
||||
r.add_argument("--file", required=True)
|
||||
r.add_argument("--output", help="Output JSON file")
|
||||
args = parser.parse_args()
|
||||
if args.command == "text":
|
||||
result = extract_from_file(args.file)
|
||||
elif args.command == "hash":
|
||||
result = hash_file(args.file)
|
||||
elif args.command == "strings":
|
||||
result = extract_strings(args.file, args.min_length)
|
||||
elif args.command == "report":
|
||||
result = generate_ioc_report(args.file, args.output)
|
||||
else:
|
||||
parser.print_help()
|
||||
return
|
||||
print(json.dumps(result, indent=2, default=str))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user