mcpField
A
analyzing-network-covert-channels-in-malware

analyzing-network-covert-channels-in-malware

github.com/mukul975安全35.2k374 次安装8 周前更新
代码仓库

关于 analyzing-network-covert-channels-in-malware

面向事件响应人员、SOC 分析师和威胁猎人的安全分析技能,用于检查恶意软件网络隐蔽通道。它提供隧道检测、外传量估算及 C2 模式提取流程。

主要功能

  1. 01DNS 隧道检测
  2. 02ICMP 载荷异常分析
  3. 03HTTP 隐蔽通道分析
  4. 04数据外传量估算
  5. 05C2 模式与信标间隔提取

适用场景

  1. 01调查恶意软件网络通信
  2. 02构建检测规则与狩猎查询
  3. 03验证网络监控覆盖范围

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill analyzing-network-covert-channels-in-malware

安装后在 Claude Code 中输入/analyzing-network-covert-channels-in-malware确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

LICENSE
assets/
template.md
references/
api-reference.md
standards.md
workflows.md
scripts/
agent.py

详细介绍

恶意软件中的网络隐蔽信道分析

概述

恶意软件会利用隐蔽信道,将 C2 通信和数据外传伪装成看似合法的网络流量。DNS 隧道将数据编码在 DNS 查询和响应中(工具 iodine、dnscat2 以及 FrameworkPOS 等恶意软件家族均使用此技术)。ICMP 隧道将数据隐藏在回显请求/响应载荷中(icmpsh、ptunnel)。HTTP 隐蔽信道将 C2 数据嵌入标头、Cookie 或隐写图像中。协议滥用则利用允许通过的协议绕过防火墙。现代基于 ML 的方法检测 DNS 隧道的召回率可达 99% 以上,但低吞吐量的数据外传仍然难以检测。Palo Alto Unit42 在 2024 年持续追踪了三场大型 DNS 隧道活动(TrkCdn、SecShow、Savvy Seahorse),表明这种技术仍然普遍存在。

适用场景

  • 调查需要分析恶意软件网络隐蔽信道的安全事件时
  • 为此领域构建检测规则或威胁狩猎查询时
  • SOC 分析师需要针对此类分析制定结构化流程时
  • 验证相关攻击技术的安全监控覆盖范围时

前置条件

  • Python 3.9+,以及 scapy、dpkt、dnslib
  • 用于 PCAP 分析的 Wireshark/tshark
  • 用于网络监控的 Zeek(原名 Bro)
  • DNS 查询日志基础设施
  • 了解数据包级别的 DNS、ICMP、HTTP 协议

工作流

步骤 1:检测 DNS 隧道
#!/usr/bin/env python3
"""Detect DNS tunneling and covert channels in network traffic."""
import sys
import json
import math
from collections import Counter, defaultdict

try:
    from scapy.all import rdpcap, DNS, DNSQR, DNSRR, IP, ICMP
except ImportError:
    print("pip install scapy")
    sys.exit(1)


def entropy(data):
    if not data:
        return 0
    freq = Counter(data)
    length = len(data)
    return -sum((c/length) * math.log2(c/length) for c in freq.values())


def analyze_dns_tunneling(pcap_path):
    """Detect DNS tunneling indicators in PCAP."""
    packets = rdpcap(pcap_path)
    domain_stats = defaultdict(lambda: {
        "queries": 0, "total_qname_len": 0, "subdomain_lengths": [],
        "query_types": Counter(), "unique_subdomains": set(),
    })

    for pkt in packets:
        if pkt.haslayer(DNS) and pkt.haslayer(DNSQR):
            qname = pkt[DNSQR].qname.decode('utf-8', errors='replace').rstrip('.')
            qtype = pkt[DNSQR].qtype

            parts = qname.split('.')
            if len(parts) >= 3:
                base_domain = '.'.join(parts[-2:])
                subdomain = '.'.join(parts[:-2])

                stats = domain_stats[base_domain]
                stats["queries"] += 1
                stats["total_qname_len"] += len(qname)
                stats["subdomain_lengths"].append(len(subdomain))
                stats["query_types"][qtype] += 1
                stats["unique_subdomains"].add(subdomain)

    # Score domains for tunneling indicators
    suspicious = []
    for domain, stats in domain_stats.items():
        if stats["queries"] < 5:
            continue

        avg_subdomain_len = (sum(stats["subdomain_lengths"]) /
                             len(stats["subdomain_lengths"]))
        unique_ratio = len(stats["unique_subdomains"]) / stats["queries"]

        # Calculate subdomain entropy
        all_subdomains = ''.join(stats["unique_subdomains"])
        sub_entropy = entropy(all_subdomains)

        score = 0
        reasons = []

        if avg_subdomain_len > 30:
            score += 30
            reasons.append(f"Long subdomains (avg {avg_subdomain_len:.0f} chars)")
        if unique_ratio > 0.9:
            score += 25
            reasons.append(f"High uniqueness ({unique_ratio:.2%})")
        if sub_entropy > 4.0:
            score += 25
            reasons.append(f"High entropy ({sub_entropy:.2f})")
        if stats["query_types"].get(16, 0) > 10:  # TXT records
            score += 20
            reasons.append(f"Many TXT queries ({stats['query_types'][16]})")

        if score >= 50:
            suspicious.append({
                "domain": domain,
                "score": score,
                "queries": stats["queries"],
                "avg_subdomain_length": round(avg_subdomain_len, 1),
                "unique_subdomains": len(stats["unique_subdomains"]),
                "subdomain_entropy": round(sub_entropy, 2),
                "reasons": reasons,
            })

    return sorted(suspicious, key=lambda x: -x["score"])


def analyze_icmp_tunneling(pcap_path):
    """Detect ICMP tunneling in PCAP."""
    packets = rdpcap(pcap_path)
    icmp_stats = defaultdict(lambda: {"count": 0, "payload_sizes": [], "payloads": []})

    for pkt in packets:
        if pkt.haslayer(ICMP) and pkt.haslayer(IP):
            src = pkt[IP].src
            dst = pkt[IP].dst
            key = f"{src}->{dst}"

            payload = bytes(pkt[ICMP].payload)
            icmp_stats[key]["count"] += 1
            icmp_stats[key]["payload_sizes"].append(len(payload))
            if len(payload) > 64:
                icmp_stats[key]["payloads"].append(payload[:100])

    suspicious = []
    for flow, stats in icmp_stats.items():
        if stats["count"] < 5:
            continue
        avg_size = sum(stats["payload_sizes"]) / len(stats["payload_sizes"])
        if avg_size > 64 or stats["count"] > 100:
            suspicious.append({
                "flow": flow,
                "packets": stats["count"],
                "avg_payload_size": round(avg_size, 1),
                "reason": "Large/frequent ICMP payloads suggest tunneling",
            })

    return suspicious


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print(f"Usage: {sys.argv[0]} <pcap_file>")
        sys.exit(1)

    print("[+] DNS Tunneling Analysis")
    dns_results = analyze_dns_tunneling(sys.argv[1])
    for r in dns_results:
        print(f"  {r['domain']} (score: {r['score']})")
        for reason in r['reasons']:
            print(f"    - {reason}")

    print("\n[+] ICMP Tunneling Analysis")
    icmp_results = analyze_icmp_tunneling(sys.argv[1])
    for r in icmp_results:
        print(f"  {r['flow']}: {r['reason']}")

验证标准

  • 通过熵、子域名长度和查询量分析检测 DNS 隧道
  • 通过载荷大小异常识别 ICMP 隐蔽信道
  • 区分隧道域名与合法的 CDN/云流量
  • 根据捕获的流量估算数据外传量
  • 提取 C2 通信模式和信标间隔

参考资料

评论

支持 Markdown