本帖最后由 fo1_sky 于 2014-01-04 19:58:35 编辑

解决方案 »

  1.   

    字数太多了,换IP的代码ChangeSendIP函数在这里给出VOID ChangeSendIP( PUCHAR buffer, int total_length )
    {
            // 找到ip头所在位置
    //PUCHAR ipheaderStart = buffer + 22;
    //////////////////////////////////////////////////////////////////////////
    // IP头结构
    // 4位版本号|4位首部长度|8位服务类型|16位总长度|
    // 16位标识 | 3位标志 | 13位片偏移
    // 8位生存时间| 8位协议 | 16位首部检验各
    // 32位源IP地址
    // 32位目的IP地址
    // 选项(如果有)
    // 数据
    // 前面的不用管,只要找到第十二位的源IP,进行修改,然后计算校验各
    //  USHORT ipTotalLen = 0;
    PUCHAR ipHeaderStart = buffer + 14; PUCHAR tcpHeadStart = 0;
    USHORT tcpSourcePort = 0;
    USHORT tcpDstPort = 0;
    UINT sourceIP = 0;
    UINT targetIP = 0; UINT seriNUM = 0; // 找到IP首部长度
    UCHAR ipHeadLen = *((PUCHAR)ipHeaderStart);
    ipHeadLen = ( ipHeadLen & 0X0F ) * 4;
    // TCP结构
    // 16位源端口 | 16位目的端口
    // 32位序号
    // 32位确认序号
    // 4位首部 | 保留6位 | URG|ACK|PSH|RST|SYN|FIN | 16位窗口大小
    // 16位校验和 | 16位紧急指针
    // 选项
    // 数据
    // 找到TCP的目的端口,如果目的端口不是80,则直接返回,暂时把所有的请求都进行
    // 替换
    tcpHeadStart = ipHeaderStart + ipHeadLen;
    tcpDstPort = NTOHS( *((PUSHORT)(tcpHeadStart + 2)));
    tcpSourcePort = NTOHS( *((PUSHORT)(tcpHeadStart)));
            // 用于测试的判断
    if ( tcpDstPort != 6000 && tcpSourcePort != 6000 && tcpDstPort != 80 && tcpSourcePort != 80 )
    {
    return;
    } // 找到总的长度位置,然后转换成本机字节序
    *((PUCHAR)ipHeaderStart + 10) = 0;
    ipTotalLen = NTOHS ( *((PUSHORT) ( ipHeaderStart + 2 ) ) ); sourceIP = *((UINT*)(ipHeaderStart + 12));
    sourceIP = NTOHL( sourceIP );
    sourceIP = GeneratorIP( sourceIP, tcpSourcePort );
    sourceIP = HTONL( sourceIP );
    *((UINT*)(ipHeaderStart + 12)) = sourceIP;        // 先把校验和清空,然后再重新计算
    { {
    *((PUSHORT)(ipHeaderStart + 10 )) = 0;
    *((PUSHORT)(ipHeaderStart + 10 )) = cal_chksum( (PUSHORT)ipHeaderStart, (int) ipHeadLen );
    } }
    }
      

  2.   

    计算校验和,不光有IP包的校验和要计算,还要重新计算Tcp数据包的校验和:typedef struct IP_HEADER
    {
    UCHAR  VIHL;          // Version and IHL
    UCHAR  TOS;           // Type Of Service
    USHORT TotLen;        // Total Length
    USHORT ID;            // Identification
    USHORT FlagOff;       // Flags and Fragment Offset
    UCHAR  TTL;         // Time To Live
    UCHAR  Protocol;    // Protocol
    USHORT Checksum;    // Checksum
    ULONG  iaSrc; // Internet Address - Source
    ULONG  iaDst; // Internet Address - Destination
    }IP_HEADER, *PIP_HEADER;typedef struct PSD_HEADER
    {  
    ULONG  srcip; //源IP地址
    ULONG  dstip; //目的IP地址
    UCHAR  mbz; //置空(0) 
    UCHAR  Protocol; //协议类型
    USHORT plen; //TCP/UDP数据包的长度(即从TCP/UDP报头算起到数据包结束的长度 单位:字节)  
    }PSD_HEADER, *PPSD_HEADER;
    // 求校验和函数
    USHORT CheckSum(ULONG addedCksum, USHORT *buffer, int size)
    {
        unsigned long cksum = addedCksum;
        while (size > 1) 
        {
            cksum += *buffer++;
            size -= sizeof(USHORT);
        }
        if (size) 
        {
            cksum += *(UCHAR*)buffer;
        }
        // 对每个16bit进行二进制反码求和
        cksum = (cksum >> 16) + (cksum & 0xffff);
        cksum += (cksum >>16);
        return (USHORT)(~cksum);
    }// 求校验和函数
    ULONG CheckSumOnlyAdd(USHORT *buffer, int size)
    {
        unsigned long cksum=0;
        while (size > 1) 
        {
            cksum += *buffer++;
            size -= sizeof(USHORT);
        }
        return cksum;
    }//求TCP或者UDP的校验和
    USHORT ReCalcCheckSum(PUCHAR pPacketContent)
    {
    USHORT checkSum;
    PSD_HEADER psdHeader; PIP_HEADER  pIPHeader  = (PIP_HEADER)(pPacketContent + IP_OFFSET);
    UINT ipHeaderLen = (pIPHeader->VIHL & 0x0F) * 4;
    PUSHORT pData = (PUSHORT)(pPacketContent + IP_OFFSET + ipHeaderLen);
    USHORT pLen = HTONS(pIPHeader->TotLen) - ipHeaderLen; psdHeader.dstip = pIPHeader->iaDst.S_un.S_addr;
    psdHeader.srcip = pIPHeader->iaSrc.S_un.S_addr;
    psdHeader.mbz = 0;
    psdHeader.Protocol = pIPHeader->Protocol;
    psdHeader.plen = HTONS(pLen); checkSum = CheckSum(CheckSumOnlyAdd((PUSHORT)&psdHeader, sizeof(PSD_HEADER)), 
    pData, pLen); return checkSum;
    }
      

  3.   

    谢谢你这么细心看完我的代码.
    我还想确定,如果没有修改TCP数据段的内容,那么也需要重新校验?这个检验应该不包括IP头啊?
    还有PSDHeader,我在协议说明里面没找到在哪里定义的,能再说明一下吗?
      

  4.   

    我还想确定,如果没有修改TCP数据段的内容,那么也需要重新校验?
    因为你改了IP,而Tcp数据包是要较验IP地址的。这个检验应该不包括IP头啊?
    这个校验不包括IP头,要校验伪头部 + TCP数据包头 + TCP数据包数据,结果放在TCP数据包头的Checksum字段里。还有PSDHeader,我在协议说明里面没找到在哪里定义的,能再说明一下吗?
    PSDHeader就是伪头部,TCP/UDP数据包较验都要用到,结构上面有定义。
    dstip、srcip:目标IP地址、源IP地址,mbz设成0就行。
    Protocol设成IP数据包里的协议字段值就行,plen设成TCP/UDP数据包的长度(包头+数据)记得调用函数之前,先把TCP/UDP数据包头的Checksum字段设成0