3

このサイトから: http://www.enderunix.org/docs/en/rawipspoof/

次の関数をプルしました

unsigned short in_cksum(unsigned short *addr, int len)
{
    int nleft = len;
    int sum = 0;
    unsigned short *w = addr;
    unsigned short answer = 0;

    while (nleft > 1) {
        sum += *w++;
        nleft -= 2;
    }

    if (nleft == 1) {
        *(unsigned char *) (&answer) = *(unsigned char *) w;
        sum += answer;
    }

    sum = (sum >> 16) + (sum & 0xFFFF);
    sum += (sum >> 16);
    answer = ~sum;
    return (answer);
}

unsigned short in_cksum_tcp(int src, int dst, unsigned short *addr, int len)
{
    struct psd_tcp buf;
    u_short ans;

    memset(&buf, 0, sizeof(buf));
    buf.src.s_addr = src;
    buf.dst.s_addr = dst;
    buf.pad = 0;
    buf.proto = IPPROTO_TCP;
    buf.tcp_len = htons(len);
    memcpy(&(buf.tcp), addr, len);
    ans = in_cksum((unsigned short *)&buf, 12 + len);
    return (ans);
}

ただし、受信 TCP パケットに対してこれを実行すると、現在と同じチェックサム結果が得られません (チェックサム関数を実行する前に、受信 TCP チェックサムを保存し、パケットのチェックサムをゼロに設定します)。 )

ここで、IP ヘッダーに対して「in_cksum」を実行すると、正しい答えが得られます。

そのサイトの TCP 疑似ヘッダーは次のとおりです。

struct psd_tcp {
    struct in_addr src;
    struct in_addr dst;
    unsigned char pad;
    unsigned char proto;
    unsigned short tcp_len;
    struct tcphdr tcp;
};

これを機能させるために何かが欠けていますか?

4

1 に答える 1

1

さて、あなたの主な間違いは、チェックサムの計算に TCP ペイロードを含めるのを忘れていることです。ヘッダーだけです (おっと)。この説明については、RFC 793 のセクション 3.1 (http://www.ietf.org/rfc/rfc793.txt) を参照してください。

チェックサム フィールドは、ヘッダーとテキスト内のすべての 16 ビット ワードの 1 の補数の合計の 16 ビットの 1 の補数です。

もちろん、これは「len」引数が TCP ヘッダーの長さであると仮定した私です。ペイロードが含まれている場合は、さまざまな問題があります (memcpy からソースより小さいバッファーへ...)。

ペイロードのチェックサムを行っている場合、RFC には見逃されやすい別の小さな点があることに注意してください。

セグメントにチェックサム対象の奇数のヘッダーおよびテキスト オクテットが含まれている場合、最後のオクテットの右側にゼロが埋め込まれ、チェックサム用の 16 ビット ワードが形成されます。

チェックサムを計算する前に、必要に応じてペイロードにゼロを埋め込むことを忘れないでください。

于 2012-11-06T17:08:32.647 に答える