taianmonkey
驱动牛犊
驱动牛犊
  • 注册日期2006-03-23
  • 最后登录2014-08-18
  • 粉丝0
  • 关注0
  • 积分163分
  • 威望602点
  • 贡献值0点
  • 好评度10点
  • 原创分0分
  • 专家分0分
阅读:2062回复:4

关于数据包转发的问题

楼主#
更多 发布于:2013-06-05 14:36
我要实现如下功能:
在截获的数据包内容中,加入自己的信息,转发到其他的机器上,现在的问题是:那边机器收到的数据包中 ,没有我加入的信息.


NDIS_STATUS
    FakePacket(
    PNDIS_PACKET pPacket ,
    PADAPT       pAdapt  ,
    BOOLEAN      bSender
)
{
    NDIS_STATUS    nRet           = NDIS_STATUS_FAILURE;
    PUCHAR         pPacketContent = NULL;
    PUCHAR         pCustomPacketContent = NULL;
    PNDIS_BUFFER   NdisBuffer ;
    UINT           TotalPacketLength = 0;
    UINT           copysize = 0;
    UINT           DataOffset = 0 ;
    UINT           PhysicalBufferCount;
    UINT           BufferCount  ;
    PUCHAR         tembuffer = NULL ;
    UINT           ActualDataLength=0;
    PVOID           VirtualAddress;
    UINT           Length=0;
    UINT           DataToCopy;
    PNDIS_BUFFER   Buffer;
    UINT           HeaderSize = 0;
    PETHERNET_FRAME pEthernetFrame = NULL;
    PIP_HEADER       pIpHeader = NULL;
    PTCP_HEADER       pTcpHeader = NULL;
    PUDP_HEADER       pUdpHeader = NULL;
    PICMP_HEADER   pIcmpHeader = NULL;
    UINT           uOldPacketSize;
    UINT           uIpHeader = IP_HEADER_LENGTH;
    UINT           uTcpHeader = TCP_HEADER_LENGTH;
    UINT           uUdpHeader = UDP_HEADER_LENGTH;
    UINT           uIcmpHeader =ICMP_HEADER_LENGTH;
    UINT           uRealDataSize = 0;
    UINT           nIndex = 0;
    UINT           nHeaderLen = 0;
    do
    {
        if ( pPacket == NULL ) break;
        //if( g_nTimesSend == 0 ) break;

        HeaderSize = NDIS_GET_PACKET_HEADER_SIZE(pPacket);

        nRet = NdisAllocateMemoryWithTag( &pPacketContent, 2048, TAG);
        if( nRet != NDIS_STATUS_SUCCESS ) break;
        NdisZeroMemory( pPacketContent, 2048 ) ;

        // 找到第一个Ndis_Buffer。然后通过通过NdisGetNextBuffer来获得后续的NDIS_BUFFER。
        // 如果只是找第一个节点,更快且方便的方法是调用NdisGetFirstBufferFromPacket。
        NdisQueryPacket(pPacket,  // NDIS_PACKET        
            &PhysicalBufferCount,// 内存中的物理块数
            &BufferCount,         // 多少个NDIS_BUFFER包
            &NdisBuffer,         // 将返回第一个包
            &TotalPacketLength     // 总共的包数据长度
            );

        while(TRUE){

            // 取得Ndis_Buffer中存储缓冲区的虚拟地址。
            // 这个函数的另一个版本是NdisQueryBuffer。
            // 后者在系统资源低或者甚至耗尽的时候,会产生Bug Check,导致蓝屏。
            NdisQueryBufferSafe(NdisBuffer,
                &tembuffer,// 缓冲区地址
                &copysize, // 缓冲区大小
                NormalPagePriority
                );

            // 如果tembuffer为NULL,说明当前系统资源匮乏。
            if(tembuffer != NULL){
                NdisMoveMemory( pPacketContent + DataOffset , tembuffer, copysize) ;            
                DataOffset += copysize;
            }

            // 获得下一个NDIS_BUFFER。
            // 如果得到的是一个NULL指针,说明已经到了链式缓冲区的末尾,我们的循环应该结束了。
            NdisGetNextBuffer(NdisBuffer , &NdisBuffer ) ;

            if( NdisBuffer == NULL )
                break ;
        }


        DBGPRINT(("FakePacket : BufferCount : %d , NdisQueryPacket - TotalPacketLength : %d  , DataOffset : %d\n " , BufferCount , TotalPacketLength,DataOffset));

        pEthernetFrame = (PETHERNET_FRAME)&pPacketContent[0];

        //判断是否为IP数据包
        if(NTOHS(pEthernetFrame->FrameType)!=ETHERTYPE_IP)
        {
            DBGPRINT(("==========> not IP packet\n"));
            break;
        }

        if( bSender == TRUE )
        {
            //如果为IP数据包则判断是否获得了IP数据包的足够数据,以太网帧头14+IP包头20
            if(TotalPacketLength<ETHERNET_FRAME_LENGTH+IP_HEADER_LENGTH)
            {
                break;
            }
            else
                pIpHeader=(PIP_HEADER)&pPacketContent[ETHERNET_FRAME_LENGTH];


            RtlCopyMemory(pEthernetFrame->DestinationAddress, g_client_mac, MAC_LEN);
            RtlCopyMemory(pEthernetFrame->SourceAddress, g_server_mac, MAC_LEN);

            switch(pIpHeader->Protocol)
            {
            case PROTOCOL_TCP:
                uRealDataSize = TotalPacketLength - ETHERNET_FRAME_LENGTH - IP_HEADER_LENGTH - TCP_HEADER_LENGTH;
                DBGPRINT((" ======> [TCP] uRealDataSize : %d\n" , uRealDataSize ));
                nHeaderLen = ETHERNET_FRAME_LENGTH + IP_HEADER_LENGTH + TCP_HEADER_LENGTH;
                pTcpHeader = (PTCP_HEADER)&pPacketContent[ETHERNET_FRAME_LENGTH +IP_HEADER_LENGTH];
                break;
            case PROTOCOL_UDP:
                uRealDataSize = TotalPacketLength - ETHERNET_FRAME_LENGTH - IP_HEADER_LENGTH - UDP_HEADER_LENGTH;
                DBGPRINT((" ======> [UDP] uRealDataSize : %d\n" , uRealDataSize ));
                nHeaderLen = ETHERNET_FRAME_LENGTH + IP_HEADER_LENGTH + UDP_HEADER_LENGTH;
                pUdpHeader = (PUDP_HEADER)&pPacketContent[ETHERNET_FRAME_LENGTH +IP_HEADER_LENGTH];
                break;
            case PROTOCOL_ICMP:
                uRealDataSize = TotalPacketLength - ETHERNET_FRAME_LENGTH - IP_HEADER_LENGTH - ICMP_HEADER_LENGTH;
                DBGPRINT((" ======> [ICMP] uRealDataSize : %d\n" , uRealDataSize ));
                nHeaderLen = ETHERNET_FRAME_LENGTH + IP_HEADER_LENGTH + ICMP_HEADER_LENGTH;
                pIcmpHeader = (PICMP_HEADER)&pPacketContent[ETHERNET_FRAME_LENGTH +IP_HEADER_LENGTH];
                break;
            default:
                uRealDataSize = 0;
                break;
            }

            if ( uRealDataSize > 0 )
            {
                custom_header_info  csHeaderInfo = {0};

                nRet = NdisAllocateMemoryWithTag( &pCustomPacketContent , uRealDataSize + FLAG_LEN + 4 ,  TAG );
                if( nRet != NDIS_STATUS_SUCCESS ) break;
                NdisZeroMemory( pCustomPacketContent, uRealDataSize + FLAG_LEN + 4 ) ;
                DBGPRINT(("FakePacket -- before xor Data : \n"));
                PrintBufData( &pPacketContent[nHeaderLen] , uRealDataSize );

                //仅仅对实际的数据作异或操作
                for ( nIndex = 0 ; nIndex < uRealDataSize ; nIndex++ )
                {
                    char* pBuf = &pPacketContent[nHeaderLen+nIndex];
                    *pBuf ^= XOR_SEED;
                }

                //build our special header
                RtlCopyMemory( csHeaderInfo.szMd5 , DEF_szMd5Flag , FLAG_LEN );
                csHeaderInfo.protocol_type = _htonl(CHALLENGE_PACKET);

                DBGPRINT(("FakePacket -- after xor Data : \n"));
                PrintBufData( &pPacketContent[nHeaderLen] , uRealDataSize );

                //rebuild real data
                NdisMoveMemory( pCustomPacketContent , &csHeaderInfo , FLAG_LEN + 4 );
                NdisMoveMemory( pCustomPacketContent + FLAG_LEN + 4 , &pPacketContent[nHeaderLen] , uRealDataSize );

                NdisZeroMemory( &pPacketContent[nHeaderLen], uRealDataSize ) ;
                NdisMoveMemory( pPacketContent + nHeaderLen , pCustomPacketContent , uRealDataSize + FLAG_LEN + 4 );


                pIpHeader->DestinationIp   = g_uDestIp;
                pIpHeader->SourceIp        = g_uSrcIp;  
                //calc modified packet size
                pIpHeader->DatagramLength = _htons( TotalPacketLength + FLAG_LEN + 4 );

                //checksum IP header
                pIpHeader->CheckSum       = 0;
                pIpHeader->CheckSum       = _htons(checksum( &pPacketContent[ETHERNET_FRAME_LENGTH] , IP_HEADER_LENGTH ));


                DBGPRINT(("\nHere , show modified packet:\n"));
                PrintBufData( pPacketContent , NTOHS(pIpHeader->DatagramLength));

                switch(pIpHeader->Protocol)
                {
                case PROTOCOL_TCP:
                    nRet = ModifyPacketWndSize( PROTOCOL_TCP , pPacketContent , NTOHS(pIpHeader->DatagramLength) );
                    break;
                case PROTOCOL_UDP:
                    nRet = ModifyPacketWndSize( PROTOCOL_UDP , pPacketContent , NTOHS(pIpHeader->DatagramLength) );
                    break;
                case PROTOCOL_ICMP:
                    break;
                default:
                    break;
                }

                if ( nRet == NDIS_STATUS_SUCCESS )
                {
                    DBGPRINT(( "[sender] FakePacket Checksum : 0x%x , DatagramLength : %d , source ip : %d.%d.%d.%d , dest ip : %d.%d.%d.%d\n" ,NTOHS(pIpHeader->CheckSum) , NTOHS(pIpHeader->DatagramLength) , dbg_ip(NTOHL(g_uSrcIp)) , dbg_ip(NTOHL(g_uDestIp))));
                    PrinfPacketRealData( pPacketContent , NTOHS(pIpHeader->DatagramLength) );

                    DBGPRINT(("\nBefore CD_SendPacket"));

                    //send modified packet
                    nRet = CD_SendPacket(pAdapt, &pPacketContent, NTOHS(pIpHeader->DatagramLength) );
                    if (nRet != NDIS_STATUS_SUCCESS && nRet != NDIS_STATUS_PENDING)
                    {
                        DbgPrint("MySendPacket error : 0x%08x\n", nRet);
                    }
                    else
                    {
                        //DbgPrint(" \n ");
                    }
                }
            }        
        }
        else
        {
            //如果为IP数据包则判断是否获得了IP数据包的足够数据,以太网帧头14+IP包头20
            if(TotalPacketLength<ETHERNET_FRAME_LENGTH+IP_HEADER_LENGTH)
            {
                break;
            }
            else
                pIpHeader=(PIP_HEADER)&pPacketContent[ETHERNET_FRAME_LENGTH];


            DBGPRINT(( "[receiver] FakePacket Checksum : 0x%x , DatagramLength : %d , src ip : %d.%d.%d.%d , dest ip : %d.%d.%d.%d\n" , NTOHS(pIpHeader->CheckSum) , NTOHS( pIpHeader->DatagramLength )  , dbg_ip( NTOHL( pIpHeader->SourceIp )) , dbg_ip(NTOHL( pIpHeader->DestinationIp )) ));

            switch(pIpHeader->Protocol)
            {
            case PROTOCOL_TCP:
                uRealDataSize = TotalPacketLength - ETHERNET_FRAME_LENGTH - IP_HEADER_LENGTH - TCP_HEADER_LENGTH;
                //DBGPRINT((" <====== [TCP] uRealDataSize : %d\n" , uRealDataSize ));
                nHeaderLen = ETHERNET_FRAME_LENGTH + IP_HEADER_LENGTH + TCP_HEADER_LENGTH;
                break;
            case PROTOCOL_UDP:
                uRealDataSize = TotalPacketLength - ETHERNET_FRAME_LENGTH - IP_HEADER_LENGTH - UDP_HEADER_LENGTH;
                //DBGPRINT((" <====== [UDP] uRealDataSize : %d\n" , uRealDataSize ));
                nHeaderLen = ETHERNET_FRAME_LENGTH + IP_HEADER_LENGTH + UDP_HEADER_LENGTH;
                break;
            case PROTOCOL_ICMP:
                uRealDataSize = TotalPacketLength - ETHERNET_FRAME_LENGTH - IP_HEADER_LENGTH - ICMP_HEADER_LENGTH;
                //DBGPRINT((" <====== [ICMP] uRealDataSize : %d\n" , uRealDataSize ));
                nHeaderLen = ETHERNET_FRAME_LENGTH + IP_HEADER_LENGTH + ICMP_HEADER_LENGTH;
                break;
            default: break;
            }
 
            if ( uRealDataSize > 0 )
            {
                if( pIpHeader->SourceIp ==  g_uSrcIp )
                {
                    DbgPrint("===============》收到数据包了\n");

                    PrintBufData( pPacketContent , NTOHS(pIpHeader->DatagramLength));


                    for ( nIndex = 0 ; nIndex < uRealDataSize ; nIndex++ )
                    {
                        char* pBuf = &pPacketContent[nHeaderLen+nIndex];
                        *pBuf ^= XOR_SEED;
                    }
                    DBGPRINT(("FakePacket -- after xor Data : \n"));
                    //PrintPacket( pPacket );
                    PrintBufData( pPacketContent , NTOHS(pIpHeader->DatagramLength));
                }
            }
        }
        

    } while (0);
    
    if( pPacketContent != NULL )
        NdisFreeMemory(pPacketContent, 0, 0);

    if( pCustomPacketContent != NULL )
        NdisFreeMemory(pCustomPacketContent, 0, 0);
    return nRet;
}


NDIS_STATUS
    CD_SendPacket (
    PADAPT          pAdapt,
    PVOID           pBuffer,
    ULONG           dwBufferLength
    )
{
    NDIS_STATUS     nRet       = NDIS_STATUS_FAILURE;
    PNDIS_PACKET    ndisPacket = NULL;
    PNDIS_BUFFER    ndisBuffer = NULL;
    PUCHAR          sendBuffer = NULL;

    PSEND_RSVD      sendRsvd = NULL;
    NDIS_PHYSICAL_ADDRESS highestAcceptableAddress;
    highestAcceptableAddress.QuadPart = -1;

    do
    {
        if(pBuffer == NULL) break;
        if(dwBufferLength < ETH_MIN_PACKET_SIZE || dwBufferLength > ETH_MAX_PACKET_SIZE) break;

        nRet = NdisAllocateMemory(&sendBuffer, dwBufferLength, 0, highestAcceptableAddress);
        //status = NdisAllocateMemoryWithTag (&sendBuffer, dwBufferLength, TAG);
        if (nRet != NDIS_STATUS_SUCCESS)        break;

        RtlZeroMemory(sendBuffer, dwBufferLength);
        RtlMoveMemory(sendBuffer, pBuffer, dwBufferLength);

        NdisAllocatePacket(&nRet, &ndisPacket, pAdapt->SendPacketPoolHandle);
        if (nRet != NDIS_STATUS_SUCCESS)
        {
            NdisFreeMemory(sendBuffer, dwBufferLength, 0);
            break;
        }

        NdisAllocateBuffer(&nRet, &ndisBuffer, pAdapt->SendPacketPoolHandle, sendBuffer, dwBufferLength);

        DBGPRINT(("SendRawData -> Allocate return: 0x%x, %d\n", sendBuffer, dwBufferLength));

        if (nRet != NDIS_STATUS_SUCCESS)
        {
            NdisFreeMemory(sendBuffer, dwBufferLength, 0);
            NdisFreePacket(ndisPacket);
            break;
        }

        NdisChainBufferAtFront(ndisPacket, ndisBuffer);

        sendRsvd = (PSEND_RSVD)(ndisPacket->ProtocolReserved);
        sendRsvd->OriginalPkt = (PNDIS_PACKET)1; //标记自己

        ndisPacket->Private.Head->Next = NULL;
        ndisPacket->Private.Tail = NULL;

        NdisSetPacketFlags(ndisPacket, NDIS_FLAGS_DONT_LOOPBACK);
        DBGPRINT(("SendRawData -> Now send!\n"));
        NdisSend(&nRet, pAdapt->BindingHandle, ndisPacket);
        if (nRet != STATUS_PENDING)
        {
            NdisUnchainBufferAtFront(ndisPacket, &ndisBuffer);
            NdisQueryBufferSafe(ndisBuffer, &sendBuffer, &dwBufferLength, NormalPagePriority);
            NdisFreeBuffer(ndisBuffer);
            NdisFreeMemory(sendBuffer, dwBufferLength, 0);
            NdisFreePacket(ndisPacket);
            DBGPRINT(("SendRawData -> Released!\n"));
        }

    } while (0);
    return nRet;
}
taianmonkey
驱动牛犊
驱动牛犊
  • 注册日期2006-03-23
  • 最后登录2014-08-18
  • 粉丝0
  • 关注0
  • 积分163分
  • 威望602点
  • 贡献值0点
  • 好评度10点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2013-06-05 15:07
给俺点提示呀
iihacker
论坛版主
论坛版主
  • 注册日期2010-01-07
  • 最后登录2017-08-16
  • 粉丝5
  • 关注8
  • 积分377分
  • 威望1941点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
  • 社区居民
板凳#
发布于:2013-06-07 13:29
1   改了IP的大小,还要改TCP UDP包的大小的段。加上校验,(你的ModifyPacketWndSize不知道改了没有)
2   最好别用虚拟机进行2台机器测试,我遇见过数据未变的情况。
3 你先把UDP搞定再说吧,TCP这样改肯定不行 。序列号维护问题。自己看一下TCP协议

最好自己windbg跟一下
NDIS 1群74755180 NDIS 2群182802097 交换机软硬件技术群 187471475 FPGA PCI PCIE 群187471817
taianmonkey
驱动牛犊
驱动牛犊
  • 注册日期2006-03-23
  • 最后登录2014-08-18
  • 粉丝0
  • 关注0
  • 积分163分
  • 威望602点
  • 贡献值0点
  • 好评度10点
  • 原创分0分
  • 专家分0分
地板#
发布于:2013-06-08 10:04
NDIS_STATUS ModifyPacketWndSize( UCHAR    Protocol,  PVOID pPacketContent,INT iPacketSize)
{
    //定义数据包tcp/ip结构指针
    int                  nLeavingLen;
    PETHERNET_FRAME      pEtherHdr=NULL;
    PIP_HEADER           pIpHdr=NULL;
    PTCP_HEADER          pTcpHdr=NULL;
    PUDP_HEADER          pUdpHdr=NULL;
    CHAR                 *pData=NULL;
    NDIS_STATUS          nRet = NDIS_STATUS_FAILURE;
 
    do
    {
        if (pPacketContent==NULL) break;
 
        if( ( Protocol == PROTOCOL_TCP ) || ( Protocol == PROTOCOL_UDP ) )
        {
            //获得以太帧头,过滤协议,过滤ip协议,放行其他协议
            nLeavingLen=iPacketSize;
            if(nLeavingLen < sizeof(EHTERNET_FRAME))    break;
            nLeavingLen -= sizeof(EHTERNET_FRAME);        
            pEtherHdr = (PETHERNET_FRAME)pPacketContent;    
            if(NTOHS(pEtherHdr->FrameType)!=ETHERTYPE_IP) // 如果不是IP协议,则不处理
                break;
            //获得ip头
            pIpHdr = (PIP_HEADER)(pEtherHdr + 1);
            // 验证剩余数据长度,防止发生内核非法访问
            if(nLeavingLen < sizeof(IP_HEADER))
                break;
            nLeavingLen -= sizeof(IP_HEADER);
            // 检查版本信息,我们仅处理IPv4
            if(((pIpHdr->VersionAndHeaderLength >> 4) & 0x0f) == 6)
            {
                break;
            }
 
            // 如果是TCP封包,修改窗口大小
            if(pIpHdr->Protocol == PROTOCOL_TCP)
            {
                //TCP伪数据包头指针
                PSDHEADER *pPsdHeader=NULL;
                //数据包校验缓存大小
                INT iTcpCheckoutBufSize;
                NDIS_PHYSICAL_ADDRESS phyaddr = {-1};
                NDIS_STATUS Status;
 
                //修改窗口大小
                pTcpHdr = (PTCP_HEADER)(pIpHdr + 1);
                pTcpHdr->Window=200;
                KdPrint(("改变窗口大小!\n"));
                //pTcpHdr->flags=0;
                //Tcp数据校验
                iTcpCheckoutBufSize=sizeof(PSDHEADER)+nLeavingLen;
                Status=NdisAllocateMemory(&pPsdHeader,iTcpCheckoutBufSize,0,phyaddr);
                if (Status==NDIS_STATUS_SUCCESS)
                {
                    NdisZeroMemory(pPsdHeader,iTcpCheckoutBufSize);
 
                    //填充伪TCP头
                    pPsdHeader->daddr=pIpHdr->SourceIp;
                    pPsdHeader->saddr=pIpHdr->DestinationIp;
                    pPsdHeader->mbz=0;
                    pPsdHeader->ptcl=PROTOCOL_TCP;
                    pPsdHeader->tcpl=htons(nLeavingLen);
                    ////计算TCP校验和
                    pTcpHdr->CheckSum=0;
                    NdisMoveMemory((PCHAR)pPsdHeader+sizeof(PSDHEADER),pTcpHdr,nLeavingLen);
                    pTcpHdr->CheckSum=checksum((PUSHORT)pPsdHeader,iTcpCheckoutBufSize);
                    NdisFreeMemory(pPsdHeader,iTcpCheckoutBufSize,0);
                    nRet = NDIS_STATUS_SUCCESS;
                }
            }
            else if ( pIpHdr->Protocol == PROTOCOL_UDP )
            {
                //UDP伪数据包头指针
                PSDHEADER *pPsdHeader=NULL;
                //数据包校验缓存大小
                INT iUdpCheckoutBufSize;
                NDIS_PHYSICAL_ADDRESS phyaddr = {-1};
                NDIS_STATUS Status;
 
                pUdpHdr = (PUDP_HEADER)(pIpHdr + 1);
 
                iUdpCheckoutBufSize=sizeof(PSDHEADER)+nLeavingLen;
                Status=NdisAllocateMemory(&pPsdHeader,iUdpCheckoutBufSize,0,phyaddr);
                if (Status==NDIS_STATUS_SUCCESS)
                {
                    NdisZeroMemory(pPsdHeader,iUdpCheckoutBufSize);
 
                    //填充伪UDP头
                    pPsdHeader->daddr=pIpHdr->SourceIp;
                    pPsdHeader->saddr=pIpHdr->DestinationIp;
                    pPsdHeader->mbz=0;
                    pPsdHeader->ptcl=PROTOCOL_UDP;
                    pPsdHeader->tcpl=htons(nLeavingLen);
                    ////计算UDP校验和
                    pUdpHdr->CheckSum=0;
                    NdisMoveMemory((PCHAR)pPsdHeader+sizeof(PSDHEADER),pUdpHdr,nLeavingLen);
                    pUdpHdr->CheckSum=checksum((PUSHORT)pPsdHeader,iUdpCheckoutBufSize);
                    NdisFreeMemory(pPsdHeader,iUdpCheckoutBufSize,0);
                    nRet = NDIS_STATUS_SUCCESS;
                }
            }
        }
    } while (0);
    return nRet;
}
taianmonkey
驱动牛犊
驱动牛犊
  • 注册日期2006-03-23
  • 最后登录2014-08-18
  • 粉丝0
  • 关注0
  • 积分163分
  • 威望602点
  • 贡献值0点
  • 好评度10点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2013-06-13 10:25
有做过的人吗,提示一下吧
游客

返回顶部