mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-25 05:50:57 +03:00
Production hardening: security fixes, code quality, 724 skills complete
- Fix 25 shell=True subprocess calls with list-based commands - Fix 49 verify=False in defensive skills (env-var override) - Add timeout to 231 HTTP/subprocess/socket calls - Fix 6 SQL injection patterns with whitelist validation - Replace 8 __import__() with standard imports - Remove 701 unused imports across 442 files - Add authorized-testing disclaimers to all offensive skills - Complete 11 incomplete skill directories - Expand 10 stub SKILL.md files with full content - Fix 2 YAML parse errors in frontmatter - Fix 5 pre-existing syntax errors - Convert 22 hardcoded paths/ports to environment variables - Back up 21 redundant skill pairs to .bak - Fix 2 global declaration errors - 724/724 skills with full folder anatomy (SKILL.md + agent.py + api-reference.md + LICENSE) - 0 compile errors across all 724 agent.py files
This commit is contained in:
@@ -0,0 +1,218 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Ransomware payment wallet blockchain analysis agent.
|
||||
|
||||
Traces cryptocurrency payment flows from ransomware wallets using public
|
||||
blockchain APIs. Identifies transaction patterns, cluster relationships,
|
||||
and fund movement to exchanges or mixers.
|
||||
"""
|
||||
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
|
||||
try:
|
||||
import requests
|
||||
except ImportError:
|
||||
print("[!] 'requests' library required: pip install requests")
|
||||
sys.exit(1)
|
||||
|
||||
BLOCKCHAIN_API = "https://blockchain.info"
|
||||
BLOCKSTREAM_API = "https://blockstream.info/api"
|
||||
|
||||
BTC_ADDRESS_REGEX = re.compile(
|
||||
r"^(1[a-km-zA-HJ-NP-Z1-9]{25,34}|3[a-km-zA-HJ-NP-Z1-9]{25,34}|bc1[a-z0-9]{39,59})$"
|
||||
)
|
||||
|
||||
KNOWN_RANSOMWARE_WALLETS = {
|
||||
"12t9YDPgwueZ9NyMgw519p7AA8isjr6SMw": "WannaCry",
|
||||
"13AM4VW2dhxYgXeQepoHkHSQuy6NgaEb94": "WannaCry",
|
||||
"115p7UMMngoj1pMvkpHijcRdfJNXj6LrLn": "WannaCry",
|
||||
"1Mz7153HMuxXTuR2R1t78mGSdzaAtNbBWX": "DarkSide (Colonial Pipeline)",
|
||||
"bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh": "DarkSide",
|
||||
}
|
||||
|
||||
|
||||
def validate_btc_address(address):
|
||||
"""Validate Bitcoin address format."""
|
||||
if BTC_ADDRESS_REGEX.match(address):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def query_address_info(address):
|
||||
"""Query blockchain.info for address details."""
|
||||
url = f"{BLOCKCHAIN_API}/rawaddr/{address}?limit=50"
|
||||
resp = requests.get(url, timeout=30)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
return {
|
||||
"address": address,
|
||||
"total_received_btc": data.get("total_received", 0) / 1e8,
|
||||
"total_sent_btc": data.get("total_sent", 0) / 1e8,
|
||||
"final_balance_btc": data.get("final_balance", 0) / 1e8,
|
||||
"n_tx": data.get("n_tx", 0),
|
||||
"transactions": data.get("txs", []),
|
||||
}
|
||||
|
||||
|
||||
def query_blockstream_address(address):
|
||||
"""Query Blockstream API for address stats (fallback)."""
|
||||
url = f"{BLOCKSTREAM_API}/address/{address}"
|
||||
resp = requests.get(url, timeout=30)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
chain = data.get("chain_stats", {})
|
||||
return {
|
||||
"address": address,
|
||||
"funded_txo_count": chain.get("funded_txo_count", 0),
|
||||
"spent_txo_count": chain.get("spent_txo_count", 0),
|
||||
"funded_txo_sum_btc": chain.get("funded_txo_sum", 0) / 1e8,
|
||||
"spent_txo_sum_btc": chain.get("spent_txo_sum", 0) / 1e8,
|
||||
}
|
||||
|
||||
|
||||
def extract_output_addresses(transactions, source_address):
|
||||
"""Extract downstream addresses from transaction outputs."""
|
||||
downstream = {}
|
||||
for tx in transactions:
|
||||
tx_hash = tx.get("hash", "unknown")
|
||||
is_outgoing = any(
|
||||
inp.get("prev_out", {}).get("addr") == source_address
|
||||
for inp in tx.get("inputs", [])
|
||||
)
|
||||
if not is_outgoing:
|
||||
continue
|
||||
for out in tx.get("out", []):
|
||||
addr = out.get("addr")
|
||||
value = out.get("value", 0) / 1e8
|
||||
if addr and addr != source_address:
|
||||
if addr not in downstream:
|
||||
downstream[addr] = {"total_btc": 0, "tx_count": 0, "tx_hashes": []}
|
||||
downstream[addr]["total_btc"] += value
|
||||
downstream[addr]["tx_count"] += 1
|
||||
downstream[addr]["tx_hashes"].append(tx_hash[:16])
|
||||
return downstream
|
||||
|
||||
|
||||
def check_known_wallets(address):
|
||||
"""Check if address matches known ransomware wallets."""
|
||||
if address in KNOWN_RANSOMWARE_WALLETS:
|
||||
return {"known": True, "family": KNOWN_RANSOMWARE_WALLETS[address]}
|
||||
return {"known": False, "family": None}
|
||||
|
||||
|
||||
def detect_peel_chain(transactions, address):
|
||||
"""Detect peel chain pattern in outgoing transactions."""
|
||||
outgoing_values = []
|
||||
for tx in transactions:
|
||||
is_outgoing = any(
|
||||
inp.get("prev_out", {}).get("addr") == address
|
||||
for inp in tx.get("inputs", [])
|
||||
)
|
||||
if is_outgoing:
|
||||
outputs = [o.get("value", 0) / 1e8 for o in tx.get("out", []) if o.get("addr") != address]
|
||||
outgoing_values.extend(outputs)
|
||||
|
||||
if len(outgoing_values) < 3:
|
||||
return {"peel_chain_detected": False, "reason": "Insufficient transactions"}
|
||||
|
||||
decreasing = sum(1 for i in range(1, len(outgoing_values)) if outgoing_values[i] < outgoing_values[i - 1])
|
||||
ratio = decreasing / (len(outgoing_values) - 1) if len(outgoing_values) > 1 else 0
|
||||
return {
|
||||
"peel_chain_detected": ratio > 0.6,
|
||||
"decreasing_ratio": round(ratio, 3),
|
||||
"num_outputs": len(outgoing_values),
|
||||
}
|
||||
|
||||
|
||||
def analyze_wallet(address):
|
||||
"""Full analysis of a ransomware payment wallet."""
|
||||
report = {"analysis_type": "Ransomware Payment Wallet Analysis", "address": address}
|
||||
|
||||
if not validate_btc_address(address):
|
||||
report["error"] = f"Invalid Bitcoin address format: {address}"
|
||||
return report
|
||||
|
||||
report["known_wallet_check"] = check_known_wallets(address)
|
||||
|
||||
try:
|
||||
info = query_address_info(address)
|
||||
report["wallet_info"] = {
|
||||
"total_received_btc": info["total_received_btc"],
|
||||
"total_sent_btc": info["total_sent_btc"],
|
||||
"final_balance_btc": info["final_balance_btc"],
|
||||
"transaction_count": info["n_tx"],
|
||||
}
|
||||
|
||||
downstream = extract_output_addresses(info["transactions"], address)
|
||||
report["downstream_addresses"] = {
|
||||
"count": len(downstream),
|
||||
"top_recipients": sorted(
|
||||
[{"address": a, **d} for a, d in downstream.items()],
|
||||
key=lambda x: x["total_btc"],
|
||||
reverse=True,
|
||||
)[:10],
|
||||
}
|
||||
|
||||
for recipient in report["downstream_addresses"]["top_recipients"]:
|
||||
match = check_known_wallets(recipient["address"])
|
||||
recipient["known_entity"] = match["family"] if match["known"] else "Unknown"
|
||||
|
||||
report["peel_chain_analysis"] = detect_peel_chain(info["transactions"], address)
|
||||
except requests.RequestException as e:
|
||||
report["error"] = f"API query failed: {e}"
|
||||
try:
|
||||
fallback = query_blockstream_address(address)
|
||||
report["wallet_info_blockstream"] = fallback
|
||||
except requests.RequestException as e2:
|
||||
report["fallback_error"] = f"Blockstream fallback also failed: {e2}"
|
||||
|
||||
return report
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("=" * 60)
|
||||
print("Ransomware Payment Wallet Analysis Agent")
|
||||
print("Blockchain tracing, cluster analysis, fund flow mapping")
|
||||
print("=" * 60)
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("\nUsage:")
|
||||
print(" python agent.py <bitcoin_address>")
|
||||
print(" python agent.py <bitcoin_address> --deep")
|
||||
print("\nExample:")
|
||||
print(" python agent.py 12t9YDPgwueZ9NyMgw519p7AA8isjr6SMw")
|
||||
sys.exit(0)
|
||||
|
||||
address = sys.argv[1]
|
||||
print(f"\n[*] Analyzing wallet: {address}")
|
||||
|
||||
report = analyze_wallet(address)
|
||||
|
||||
known = report.get("known_wallet_check", {})
|
||||
if known.get("known"):
|
||||
print(f"[!] KNOWN RANSOMWARE WALLET: {known['family']}")
|
||||
|
||||
info = report.get("wallet_info", {})
|
||||
if info:
|
||||
print(f"\n--- Wallet Summary ---")
|
||||
print(f" Total received: {info.get('total_received_btc', 0):.8f} BTC")
|
||||
print(f" Total sent: {info.get('total_sent_btc', 0):.8f} BTC")
|
||||
print(f" Balance: {info.get('final_balance_btc', 0):.8f} BTC")
|
||||
print(f" Transactions: {info.get('transaction_count', 0)}")
|
||||
|
||||
ds = report.get("downstream_addresses", {})
|
||||
if ds.get("count", 0) > 0:
|
||||
print(f"\n--- Top Downstream Recipients ({ds['count']} total) ---")
|
||||
for r in ds.get("top_recipients", [])[:5]:
|
||||
entity = r.get("known_entity", "Unknown")
|
||||
print(f" {r['address'][:20]}... {r['total_btc']:.8f} BTC [{entity}]")
|
||||
|
||||
peel = report.get("peel_chain_analysis", {})
|
||||
if peel.get("peel_chain_detected"):
|
||||
print(f"\n[!] Peel chain pattern detected (ratio: {peel['decreasing_ratio']})")
|
||||
|
||||
if report.get("error"):
|
||||
print(f"\n[!] Error: {report['error']}")
|
||||
|
||||
print(f"\n[*] Full report:\n{json.dumps(report, indent=2, default=str)}")
|
||||
Reference in New Issue
Block a user