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

如何用C#代码创建仅含源/目的MAC、IP及数据的pcap文件?

手动用C#构造PCAP文件的简便方法

其实完全不需要依赖第三方库就能实现——PCAP文件格式是公开的,咱们手动构造各个部分就行,非常直接。下面是一个完整的实现,只需要传入你需要的源MAC、源IP、目的MAC、目的IP和数据,就能生成可以用Wireshark等工具打开的PCAP文件。

核心思路

PCAP文件由两部分组成:

  1. 全局头:描述文件的基本信息(版本、数据链路类型等)
  2. 数据包序列:每个数据包包含包头(时间戳、长度)和实际的帧数据(以太网帧 + IP包 + 传输层数据 + 你的自定义数据)

咱们直接构造这些字节流,写入文件即可。

完整代码实现

using System;
using System.IO;
using System.Runtime.InteropServices;

public class PcapCreator
{
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    private struct PcapGlobalHeader
    {
        public uint MagicNumber;
        public ushort VersionMajor;
        public ushort VersionMinor;
        public int TimeZoneOffset;
        public uint SigFigs;
        public uint SnapLength;
        public uint NetworkType;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    private struct PcapPacketHeader
    {
        public uint TimestampSeconds;
        public uint TimestampMicroseconds;
        public uint CapturedLength;
        public uint OriginalLength;
    }

    public static void CreatePcapFile(string filePath, byte[] srcMac, byte[] srcIp, byte[] destMac, byte[] destIp, byte[] data)
    {
        // 构造PCAP全局头(标准小端格式)
        var globalHeader = new PcapGlobalHeader
        {
            MagicNumber = 0xA1B2C3D4, // PCAP标准魔数
            VersionMajor = 2,
            VersionMinor = 4,
            TimeZoneOffset = 0, // UTC时间
            SigFigs = 0,
            SnapLength = 65535, // 最大捕获长度
            NetworkType = 1 // 数据链路类型:以太网
        };

        // 获取当前UTC时间戳(PCAP使用Unix时间)
        var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        var timeSpan = DateTime.UtcNow - epoch;
        uint timestampSeconds = (uint)timeSpan.TotalSeconds;
        uint timestampMicroseconds = (uint)(timeSpan.TotalMilliseconds * 1000);

        // 构造以太网帧头部(14字节)
        byte[] ethernetFrame = new byte[14];
        Array.Copy(destMac, 0, ethernetFrame, 0, 6); // 目的MAC
        Array.Copy(srcMac, 0, ethernetFrame, 6, 6); // 源MAC
        ethernetFrame[12] = 0x08; ethernetFrame[13] = 0x00; // 帧类型:IPv4

        // 构造IPv4头部(20字节,无扩展选项)
        byte[] ipHeader = new byte[20];
        ipHeader[0] = 0x45; // 版本(4) + 头部长度(5*4=20字节)
        ipHeader[1] = 0x00; // 服务类型
        ushort ipTotalLength = (ushort)(20 + 8 + data.Length); // IP头+UDP头+数据总长度
        WriteBigEndian(ipTotalLength, ipHeader, 2);
        ipHeader[4] = 0x00; ipHeader[5] = 0x00; // 标识
        ipHeader[6] = 0x00; ipHeader[7] = 0x00; // 标志+片偏移
        ipHeader[8] = 0x40; // TTL=64
        ipHeader[9] = 0x11; // 协议类型:UDP
        ipHeader[10] = 0x00; ipHeader[11] = 0x00; // 校验和(先设0,后面计算)
        Array.Copy(srcIp, 0, ipHeader, 12, 4); // 源IP
        Array.Copy(destIp, 0, ipHeader, 16, 4); // 目的IP

        // 计算IPv4头部校验和
        ushort ipChecksum = CalculateChecksum(ipHeader);
        WriteBigEndian(ipChecksum, ipHeader, 10);

        // 构造UDP头部(8字节)
        byte[] udpHeader = new byte[8];
        WriteBigEndian((ushort)1234, udpHeader, 0); // 源端口(可自定义)
        WriteBigEndian((ushort)5678, udpHeader, 2); // 目的端口(可自定义)
        ushort udpLength = (ushort)(8 + data.Length); // UDP头+数据长度
        WriteBigEndian(udpLength, udpHeader, 4);
        udpHeader[6] = 0x00; udpHeader[7] = 0x00; // UDP校验和(可选设0)

        // 拼接完整的数据包
        byte[] packetData = new byte[ethernetFrame.Length + ipHeader.Length + udpHeader.Length + data.Length];
        int offset = 0;
        Array.Copy(ethernetFrame, 0, packetData, offset, ethernetFrame.Length);
        offset += ethernetFrame.Length;
        Array.Copy(ipHeader, 0, packetData, offset, ipHeader.Length);
        offset += ipHeader.Length;
        Array.Copy(udpHeader, 0, packetData, offset, udpHeader.Length);
        offset += udpHeader.Length;
        Array.Copy(data, 0, packetData, offset, data.Length);

        // 构造数据包头部
        var packetHeader = new PcapPacketHeader
        {
            TimestampSeconds = timestampSeconds,
            TimestampMicroseconds = timestampMicroseconds,
            CapturedLength = (uint)packetData.Length,
            OriginalLength = (uint)packetData.Length
        };

        // 写入PCAP文件
        using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
        using (var bw = new BinaryWriter(fs))
        {
            // 写入全局头(注意字节序:PCAP使用小端,直接用BitConverter即可)
            bw.Write(BitConverter.GetBytes(globalHeader.MagicNumber));
            bw.Write(BitConverter.GetBytes(globalHeader.VersionMajor));
            bw.Write(BitConverter.GetBytes(globalHeader.VersionMinor));
            bw.Write(BitConverter.GetBytes(globalHeader.TimeZoneOffset));
            bw.Write(BitConverter.GetBytes(globalHeader.SigFigs));
            bw.Write(BitConverter.GetBytes(globalHeader.SnapLength));
            bw.Write(BitConverter.GetBytes(globalHeader.NetworkType));

            // 写入数据包头部
            bw.Write(BitConverter.GetBytes(packetHeader.TimestampSeconds));
            bw.Write(BitConverter.GetBytes(packetHeader.TimestampMicroseconds));
            bw.Write(BitConverter.GetBytes(packetHeader.CapturedLength));
            bw.Write(BitConverter.GetBytes(packetHeader.OriginalLength));

            // 写入数据包内容
            bw.Write(packetData);
        }
    }

    // 辅助方法:将ushort以大端序写入字节数组
    private static void WriteBigEndian(ushort value, byte[] buffer, int offset)
    {
        byte[] bytes = BitConverter.GetBytes(value);
        if (BitConverter.IsLittleEndian) Array.Reverse(bytes);
        Array.Copy(bytes, 0, buffer, offset, 2);
    }

    // 计算校验和(用于IP头部)
    private static ushort CalculateChecksum(byte[] data)
    {
        uint sum = 0;
        int i = 0;
        while (i < data.Length)
        {
            sum += (ushort)((data[i] << 8) | data[i + 1]);
            i += 2;
        }
        // 处理奇数长度(这里IP头是20字节,偶数,所以实际不会触发)
        if (data.Length % 2 != 0)
        {
            sum += (ushort)(data[data.Length - 1] << 8);
        }
        // 折叠求和并取反
        sum = (sum >> 16) + (sum & 0xFFFF);
        sum += sum >> 16;
        return (ushort)~sum;
    }

    // 示例调用
    public static void Main()
    {
        // 替换成你需要的参数
        byte[] srcMac = new byte[] { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
        byte[] srcIp = new byte[] { 192, 168, 1, 100 };
        byte[] destMac = new byte[] { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF };
        byte[] destIp = new byte[] { 8, 8, 8, 8 };
        byte[] data = System.Text.Encoding.ASCII.GetBytes("Hello from custom PCAP!");

        CreatePcapFile("output.pcap", srcMac, srcIp, destMac, destIp, data);
        Console.WriteLine("PCAP文件已生成!");
    }
}

关键说明

  1. 不需要任何第三方库:所有逻辑都是原生C#实现,直接编译运行即可。
  2. 参数灵活:你只需要传入源MAC、源IP、目的MAC、目的IP和自定义数据,其他部分(如端口、TTL)可以根据需要修改。
  3. 兼容性:生成的PCAP文件可以被Wireshark、tcpdump等工具正常打开解析,因为完全遵循PCAP标准格式。
  4. 可扩展:如果不需要UDP层,你可以直接把数据作为IP包的payload,只需要修改IP头的协议字段(比如设为0xFF表示私有协议),并调整IP总长度为20 + data.Length,去掉UDP头的代码即可。

内容的提问来源于stack exchange,提问作者ARMisKing

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:42:13