1

ICMPv6チェックサムを計算する必要があります。RFC 2460で正しいマニュアルを見つけ、以下に貼り付けたc#でコードを記述しました。コードでは、ICMPv6メッセージの長さ(近隣アドバタイズメントの場合は32バイト)よりも、パケットの宛先IPであるチェックサム送信元IPに追加し、次にICMPv6の場合は58である次のヘッダーIDを追加することがわかります。次に、FORサイクルがあり、ICMPv6メッセージ全体をチェックサムに追加します(これは、私が信じるメッセージタイプで始まります。たとえば、近隣アドバタイズメントの場合は88 00 ...)。私が計算してチェックサムを補完するよりも、それは間違っています。実際にスニッフィングされた近隣アドバタイズメントのこのチェックサムを計算しようとしていますが、これも下にありますが、同じチェックサムを取得できません。私のコードで何が間違っている可能性がありますか?

static void Main(string[] args)
    {

        ICaptureDevice device = new OfflineCaptureDevice("icmp.pcap");
        device.Open();

        device.OnPacketArrival += new SharpPcap.PacketArrivalEventHandler(device_OnPacketArrival);
        device.Capture();


        Console.ReadKey();
    }

    private static void device_OnPacketArrival(object sender, SharpPcap.CaptureEventArgs e)
    {
        try
        {
            //packet conversions
            var packet = PacketDotNet.Packet.ParsePacket(e.Packet);
            var ethernetPacket = ((PacketDotNet.EthernetPacket)packet);
            int dlzka_packetu = e.Packet.Data.Length;
            string eth = BitConverter.ToString(ethernetPacket.Bytes);

            //now its in string field format - one string item is one byte, e.g. FF
            string[] eth_final2 = eth.Split('-');
            foreach (string bytes in eth_final2) { Console.Write(bytes + " "); }
            Console.WriteLine();

            //taking out source IP
            IPAddress src_ip = IPAddress.Parse(eth_final2[22]+eth_final2[23]+":"+eth_final2[24]+eth_final2[25]+":"+eth_final2[26]+eth_final2[27]+":"+eth_final2[28]+eth_final2[29]+":"+eth_final2[30]+eth_final2[31]+":"+eth_final2[32]+eth_final2[33]+":"+eth_final2[34]+eth_final2[35]+":"+eth_final2[36]+eth_final2[37]);

            //destination IP
            IPAddress dst_ip = IPAddress.Parse(eth_final2[38] + eth_final2[39] + ":" + eth_final2[40] + eth_final2[41] + ":" + eth_final2[42] + eth_final2[43] + ":" + eth_final2[44] + eth_final2[45] + ":" + eth_final2[46] + eth_final2[47] + ":" + eth_final2[48] + eth_final2[49] + ":" + eth_final2[50] + eth_final2[51] + ":" + eth_final2[52] + eth_final2[53]);

            Console.WriteLine(src_ip);
            Console.WriteLine(dst_ip);
            int icmpv6_length = 32;
            int next_header = 58;
            Console.WriteLine();

            string icmp_payload = "";

            //taking out ICMPv6 message
            for (int i = 54; i < 54 + 32; i++)
            {
                if (i == 56 || i == 57) { icmp_payload += "00"; }
                else icmp_payload += eth_final2[i];
            }

            Console.WriteLine(icmp_payload);
            byte[] icmp_bytes = GetStringToBytes(icmp_payload);


            //CALLING THE FUNCTION ICMPchecksum
            ushort sum = ICMPchecksum(src_ip.GetAddressBytes(), dst_ip.GetAddressBytes(), BitConverter.GetBytes(icmpv6_length), BitConverter.GetBytes(next_header), icmp_bytes);

            Console.WriteLine(sum.ToString("X"));


        }
        catch (Exception ex)
        {
            Console.WriteLine("ERROR");
        }


    }

    static byte[] GetStringToBytes(string value)
    {
        SoapHexBinary shb = SoapHexBinary.Parse(value);
        return shb.Value;
    }

    static ushort ICMPchecksum(byte[] src_ip, byte[] dst_ip, byte[] length, byte[] next, byte[] payload)
    {
        ushort checksum = 0;

        //length of byte fields
        Console.WriteLine("src_ip: "+src_ip.Length+" dst_ip: "+dst_ip.Length+" length: "+length.Length+" next_header: "+next.Length+" payload: "+payload.Length);

        //display all fields, which will be used for checksum calculation
        Console.WriteLine(BitConverter.ToString(src_ip));
        Console.WriteLine(BitConverter.ToString(dst_ip));
        Console.WriteLine(BitConverter.ToString(length));
        Console.WriteLine(BitConverter.ToString(next));
        Console.WriteLine(BitConverter.ToString(payload));


        //ADDS SOURCE IPv6 address
        checksum += BitConverter.ToUInt16(src_ip, 0);
        checksum += BitConverter.ToUInt16(src_ip, 2);
        checksum += BitConverter.ToUInt16(src_ip, 4);
        checksum += BitConverter.ToUInt16(src_ip, 6);
        checksum += BitConverter.ToUInt16(src_ip, 8);
        checksum += BitConverter.ToUInt16(src_ip, 10);
        checksum += BitConverter.ToUInt16(src_ip, 12);
        checksum += BitConverter.ToUInt16(src_ip, 14);

        //ADDS DEST IPv6 address
        checksum += BitConverter.ToUInt16(dst_ip, 0);
        checksum += BitConverter.ToUInt16(dst_ip, 2);
        checksum += BitConverter.ToUInt16(dst_ip, 4);
        checksum += BitConverter.ToUInt16(dst_ip, 6);
        checksum += BitConverter.ToUInt16(dst_ip, 8);
        checksum += BitConverter.ToUInt16(dst_ip, 10);
        checksum += BitConverter.ToUInt16(dst_ip, 12);
        checksum += BitConverter.ToUInt16(dst_ip, 14);

        //ADDS LENGTH OF ICMPv6 packet
        checksum += BitConverter.ToUInt16(length, 0);
        checksum += BitConverter.ToUInt16(length, 2);

        //ADDS NEXT HEADER ID = 58
        checksum += BitConverter.ToUInt16(next, 0);
        checksum += BitConverter.ToUInt16(next, 2);

        //ADDS WHOLE ICMPv6 message
        for (int i = 0; i < payload.Length; i = i + 2)
        {
            Console.WriteLine(i);
            checksum += BitConverter.ToUInt16(payload, i);
        }

        checksum += (ushort)(checksum >> 16);

        return (ushort)~checksum;
    }

そして、これがパケット画面です。

リンクのみ:http://img831.imageshack.us/img831/7237/icmpv6.png

加えて、ファイルをダウンロードできるリンク、私はテストに使用しています:

http://www.2shared.com/file/wIETWTWB/icmp.html

手伝ってくれてありがとう。

4

1 に答える 1

1

ペイロードはICMPv6メッセージで使用されます。これは、質問に投稿した写真にサインインしているためです。

少なくともそれは間違っています。チェックサムを計算するときは、最初にチェックサム自体を表すバイトを0に置き換える必要があります。

アップデート

icmp.pcapに基づいて、チェックサムを計算するためのスタンドアロンプ​​ログラムを作成しました。完全なソースについては、以下を参照してください。

最も重要なエラーは次のとおりです。

    ushort checksum = 0;

チェックサムは16ビットですが、このアルゴリズムでは一時的な値として少なくとも32ビットが必要です。

    uint checksum = 0;

チェックサムの計算には、加算のキャリーがラップアラウンドする1の補数演算が必要です。パフォーマンスを向上させるために、すべてのラッピングは最後に行われます。

checksum += (ushort)(checksum >> 16);

ただし、これはチェックサムが16ビットを超える場合にのみ可能です。そうでなければ、この行は役に立たないでしょう。

しかし、考慮すべきことが他にあります。BitConverter.ToUInt16は、プロセッサのエンディアン(おそらくリトルエンディアン)に依存します。結果が出A5ABます。これはおそらく期待どおりではありませんが、バイトを切り替えると、正しいバージョンが得られます。これを修正する関数をここから挿入しました。結果が出ABA5ます。一方、計算前にチェックサムを0に設定しなかった場合、チェックサムが有効であれば、 ICMPchecksumは常に0を返します。また、関数は奇数の長さのペイロードを処理できないことにも注意してください。

class Program {
    static void Main (string [] args)
    {
        byte[] src_ip = new byte[]
                            {
                                0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                                0x02, 0x19, 0x55, 0xff, 0xfe, 0x27, 0x27, 0xd0
                            };

        byte[] dst_ip = new byte[]
                            {
                                0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                                0x02, 0x22, 0x75, 0xff, 0xfe, 0xd6, 0xfe, 0x50
                            };
        byte[] length = new byte[] {0, 0, 0, 32};
        byte [] next = new byte [] { 0, 0, 0, 58 };
        byte[] payload = new byte[]
                             {
                                 0x88, 0x00, 0xab, 0xa5, 0xe0, 0x00, 0x00, 0x00, 
                                 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
                                 0x02, 0x19, 0x55, 0xff, 0xfe, 0x27, 0x27, 0xd0,
                                 0x02, 0x01, 0x00, 0x19, 0x55, 0x27, 0x27, 0xd0
                             };
#if true
        payload [2] = 0;
        payload [3] = 0;
#endif

        ushort checksum = ICMPchecksum(src_ip, dst_ip, length, next, payload);

        Console.WriteLine (checksum.ToString ("X"));
        Console.ReadKey ();
    }

    public static ushort BitConverterToUInt16 (byte [] value, int startIndex)
    {
#if false
            return System.BitConverter.ToUInt16 (value, startIndex);
#else
            return System.BitConverter.ToUInt16 (value.Reverse ().ToArray (), value.Length - sizeof (UInt16) - startIndex);
#endif
    }

    static ushort ICMPchecksum (byte [] src_ip, byte [] dst_ip, byte [] length, byte [] next, byte [] payload)
    {
        uint checksum = 0;

        //length of byte fields
        Console.WriteLine ("src_ip: " + src_ip.Length + " dst_ip: " + dst_ip.Length + " length: " + length.Length + " next_header: " + next.Length + " payload: " + payload.Length);

        //display all fields, which will be used for checksum calculation
        Console.WriteLine (BitConverter.ToString (src_ip));
        Console.WriteLine (BitConverter.ToString (dst_ip));
        Console.WriteLine (BitConverter.ToString (length));
        Console.WriteLine (BitConverter.ToString (next));
        Console.WriteLine (BitConverter.ToString (payload));


        //ADDS SOURCE IPv6 address
        checksum += BitConverterToUInt16 (src_ip, 0);
        checksum += BitConverterToUInt16 (src_ip, 2);
        checksum += BitConverterToUInt16 (src_ip, 4);
        checksum += BitConverterToUInt16 (src_ip, 6);
        checksum += BitConverterToUInt16 (src_ip, 8);
        checksum += BitConverterToUInt16 (src_ip, 10);
        checksum += BitConverterToUInt16 (src_ip, 12);
        checksum += BitConverterToUInt16 (src_ip, 14);

        //ADDS DEST IPv6 address
        checksum += BitConverterToUInt16 (dst_ip, 0);
        checksum += BitConverterToUInt16 (dst_ip, 2);
        checksum += BitConverterToUInt16 (dst_ip, 4);
        checksum += BitConverterToUInt16 (dst_ip, 6);
        checksum += BitConverterToUInt16 (dst_ip, 8);
        checksum += BitConverterToUInt16 (dst_ip, 10);
        checksum += BitConverterToUInt16 (dst_ip, 12);
        checksum += BitConverterToUInt16 (dst_ip, 14);

        //ADDS LENGTH OF ICMPv6 packet
        checksum += BitConverterToUInt16 (length, 0);
        checksum += BitConverterToUInt16 (length, 2);

        //ADDS NEXT HEADER ID = 58
        checksum += BitConverterToUInt16 (next, 0);
        checksum += BitConverterToUInt16 (next, 2);

        //ADDS WHOLE ICMPv6 message
        for (int i = 0; i < payload.Length; i = i + 2) {
            Console.WriteLine (i);
            checksum += BitConverterToUInt16 (payload, i);
        }

        checksum += (ushort)(checksum >> 16);

        return (ushort)~checksum;
    }
}
于 2012-04-08T20:32:20.757 に答える