reverse-skills-max: initial public release (restored, redacted, hardened)

This commit is contained in:
baradok609hecl1pq6qi
2026-10-20 02:17:15 +03:00
commit da24c2bd20
2227 changed files with 443931 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
Apache License 2.0 — see the repository root LICENSE file for the full text.
Copyright the AnalystAIPack contributors.
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

View File

@@ -0,0 +1,85 @@
---
name: extracting-iocs-from-analysis-output
description: 'Extracts indicators of compromise from raw analysis artifacts: parsing strings
dumps, sandbox reports, PCAP summaries, and logs for URLs, domains, IPs, hashes, mutexes, and
file paths, then deduplicating and typing them. Activates for requests to extract IOCs from
analysis output, pull indicators from a report, or harvest atomic indicators.'
domain: cybersecurity
subdomain: lab-foundations
tags:
- lab-foundations
- ioc
- extraction
- parsing
- automation
version: 1.0.0
author: analyst-ai-pack
license: Apache-2.0
mitre_attack:
- T1071
- T1583
d3fend:
- D3-DA
references:
- 'MITRE ATT&CK — https://attack.mitre.org/'
- 'IOC types and indicator extraction patterns — https://github.com/InQuest/python-iocextract'
---
# Extracting IOCs from Analysis Output
## When to Use
- You have raw analysis output (strings, sandbox JSON, PCAP notes, logs) and need the atomic
indicators out of it.
- You want a deduplicated, typed indicator set to feed enrichment, defanging, or detection.
- You are building the indicator section of a report from analysis artifacts.
**Do not use** naive substring matching that produces noise — validate indicator shapes and
filter obvious false positives (version strings that look like IPs, library domains).
## Prerequisites
- The analysis artifacts as text/JSON; the defanging skill for safe output.
## Workflow
### Step 1: Gather the artifacts
Collect strings output, sandbox report fields, network summaries, and relevant log excerpts into
text the extractor can scan.
### Step 2: Extract by pattern
Pull URLs, domains, IPv4 addresses, email addresses, and hashes (MD5/SHA-1/SHA-256) with
validated patterns; also capture host artifacts (mutexes, registry keys, file paths) where the
format allows.
```bash
python scripts/analyst.py extract analysis.txt
```
### Step 3: Filter and deduplicate
Drop benign noise (Microsoft/CDN domains, localhost, RFC1918 where irrelevant) and deduplicate;
keep a record of what was filtered and why.
### Step 4: Type and hand off
Tag each indicator with its type and pass the set to enrichment/defanging for reporting.
## Validation
- Extracted indicators match valid shapes (no malformed IPs/hashes).
- The set is deduplicated and obvious benign noise is filtered with a rationale.
- Each indicator is typed and ready for enrichment/defanging.
## Pitfalls
- Capturing version numbers as IPs or library hostnames as C2.
- Missing indicators split across lines or encoded (base64) in the artifacts.
- Not recording what was filtered, losing analyst auditability.
## References
- See [`references/api-reference.md`](references/api-reference.md) for the IOC extractor.
- MITRE ATT&CK and indicator-extraction patterns (linked in frontmatter).

View File

@@ -0,0 +1,34 @@
# API Reference: Extracting IOCs from Analysis Output
## Overview
`scripts/analyst.py` scans analysis text for URLs, domains, IPv4 addresses, emails, and hashes
using validated patterns, filters benign noise (RFC1918 IPs, well-known service domains), and
deduplicates. It reads a local text file only and performs no network activity.
## Dependencies
| Package | Version | Purpose |
|---------|---------|---------|
| (stdlib) | — | regex, JSON, file IO |
## Core functions
### `extract(text)`
Returns typed, deduplicated indicators and counts, with benign filtering applied.
### `_is_private(ip)` / `_benign_domain(d)`
Noise filters for private address space and common service domains.
## Usage
```bash
python scripts/analyst.py extract analysis.txt
```
## Sources
- MITRE ATT&CK — https://attack.mitre.org/
- Indicator-extraction patterns (validated IPv4 octets, hash lengths) —
https://github.com/InQuest/python-iocextract
- RFC1918 private address ranges for noise filtering — IETF RFC 1918

View File

@@ -0,0 +1,68 @@
#!/usr/bin/env python3
"""Extract and type indicators of compromise from raw analysis text.
Scans text for URLs, domains, IPv4 addresses, emails, and hashes using validated patterns,
filters common benign noise (RFC1918, localhost, well-known service domains), and deduplicates.
It reads a local text file only and performs no network activity.
"""
from __future__ import annotations
import argparse
import json
import re
import sys
from pathlib import Path
RE_URL = re.compile(r"\bhttps?://[^\s\"'<>)\]]+", re.I)
RE_IPV4 = re.compile(r"\b(?:(?:25[0-5]|2[0-4]\d|1?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|1?\d?\d)\b")
RE_EMAIL = re.compile(r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b")
RE_DOMAIN = re.compile(r"\b(?:[a-z0-9-]+\.)+[a-z]{2,}\b", re.I)
RE_MD5 = re.compile(r"\b[a-f0-9]{32}\b", re.I)
RE_SHA1 = re.compile(r"\b[a-f0-9]{40}\b", re.I)
RE_SHA256 = re.compile(r"\b[a-f0-9]{64}\b", re.I)
BENIGN_DOMAINS = {"microsoft.com", "windows.com", "msftncsi.com", "schemas.xmlsoap.org",
"w3.org", "verisign.com", "digicert.com", "localhost"}
def _is_private(ip: str) -> bool:
parts = [int(x) for x in ip.split(".")]
return (parts[0] == 10 or (parts[0] == 172 and 16 <= parts[1] <= 31)
or (parts[0] == 192 and parts[1] == 168) or parts[0] == 127)
def _benign_domain(d: str) -> bool:
return any(d.lower() == b or d.lower().endswith("." + b) for b in BENIGN_DOMAINS)
def extract(text: str) -> dict:
filtered = []
urls = sorted(set(RE_URL.findall(text)))
ips = sorted({ip for ip in RE_IPV4.findall(text) if not _is_private(ip)})
emails = sorted(set(RE_EMAIL.findall(text)))
domains = sorted({d for d in RE_DOMAIN.findall(text)
if not RE_IPV4.fullmatch(d) and not _benign_domain(d)})
hashes = sorted(set(RE_SHA256.findall(text)) | set(RE_SHA1.findall(text))
| set(RE_MD5.findall(text)))
return {
"indicators": {"urls": urls, "domains": domains, "ipv4": ips,
"emails": emails, "hashes": hashes},
"counts": {"urls": len(urls), "domains": len(domains), "ipv4": len(ips),
"emails": len(emails), "hashes": len(hashes)},
"filtered_note": "private IPs and well-known service domains removed",
}
def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(description="Extract IOCs from analysis output")
sub = parser.add_subparsers(dest="cmd", required=True)
p = sub.add_parser("extract")
p.add_argument("file")
args = parser.parse_args(argv)
text = Path(args.file).read_text(encoding="utf-8-sig", errors="replace")
print(json.dumps(extract(text), indent=2))
return 0
if __name__ == "__main__":
sys.exit(main())