You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SharpPcap捕获首个TCP包问题:解决端口扫描时重复输出端口状态的问题

SharpPcap捕获首个TCP包问题:解决端口扫描时重复输出端口状态的问题

嘿,我刚好碰到过类似的SharpPcap捕获重复包的问题,你的情况完全能理解——明明服务器的SYN-ACK只需要处理一次,结果后续的TCP包(比如你提到的“TCP Port numbers reused”报文)也满足了你的判断条件,导致重复输出端口状态。给你两个实用的解决思路:

方法一:用标记变量跳过已处理的端口

这是最直接的修改方式,核心就是用一个变量记录我们是否已经处理过目标端口的状态,一旦处理完成,后续符合条件的包直接跳过即可。

单端口扫描场景

如果你的工具是单次扫描单个端口,只需要在类级别声明一个布尔标记:

private bool _hasProcessedPort = false;
private int _targetPort; // 假设你的目标端口存在这个类变量中

然后修改你的OnPacketArrival逻辑,先检查标记再处理:

if (tcp != null && ip != null && tcp.SourcePort == _targetPort && eth.SourceHardwareAddress == gatewayMac)
{
    // 核心:如果已经处理过这个端口,直接跳过后续逻辑
    if (_hasProcessedPort)
    {
        return;
    }

    if (tcp.Synchronize && tcp.Acknowledgment)
    {
        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine($"Port {_targetPort} is open.");
        device.SendPacket(ethernetPacket2);
        _hasProcessedPort = true; // 处理完成后标记为已处理
    }
    else if (tcp.Reset || (tcp.Reset && tcp.Acknowledgment))
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine($"Port {_targetPort} is closed.");
        _hasProcessedPort = true;
    }
    else if (!tcp.Reset && !tcp.Acknowledgment)
    {
        Console.ForegroundColor = ConsoleColor.Yellow;
        Console.WriteLine($"Port {_targetPort} is filtered.");
        _hasProcessedPort = true;
    }
}

多端口扫描场景

如果是批量扫描多个端口,就用一个字典来记录每个端口的处理状态:

private Dictionary<int, bool> _processedPorts = new Dictionary<int, bool>();

然后在处理逻辑中加入端口检查:

if (tcp != null && ip != null && eth.SourceHardwareAddress == gatewayMac)
{
    int currentPort = tcp.SourcePort;
    // 检查当前端口是否已经处理过
    if (_processedPorts.ContainsKey(currentPort) && _processedPorts[currentPort])
    {
        return;
    }

    if (tcp.Synchronize && tcp.Acknowledgment)
    {
        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine($"Port {currentPort} is open.");
        device.SendPacket(ethernetPacket2);
        _processedPorts[currentPort] = true;
    }
    // 其余判断逻辑同理,处理完成后标记端口为已处理
    else if (tcp.Reset || (tcp.Reset && tcp.Acknowledgment))
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine($"Port {currentPort} is closed.");
        _processedPorts[currentPort] = true;
    }
    else if (!tcp.Reset && !tcp.Acknowledgment)
    {
        Console.ForegroundColor = ConsoleColor.Yellow;
        Console.WriteLine($"Port {currentPort} is filtered.");
        _processedPorts[currentPort] = true;
    }
}

方法二:提前过滤不需要的包

从根源上减少进入处理逻辑的包,利用SharpPcap的包过滤功能,只捕获我们真正需要的SYN-ACK或RST响应包,那些“端口复用”之类的无关包直接在捕获阶段就被过滤掉。

你可以在启动捕获前设置过滤规则:

// 只捕获目标端口发来的SYN-ACK或RST包
device.Filter = $"tcp src port {_targetPort} and (tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn|tcp-ack or tcp[tcpflags] & tcp-rst != 0)";

这个过滤规则基于pcap的过滤语法,精准筛选出我们需要的握手响应包,后续就不会有无关包触发重复判断了。

两种方法各有优劣:标记变量的方式改动小,适合你现有逻辑的快速调整;包过滤的方式更高效,能减少不必要的包处理开销,你可以根据自己的扫描场景选择。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 10:33:02