blankheart
驱动牛犊
驱动牛犊
  • 注册日期2008-07-30
  • 最后登录2009-01-24
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望17点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1825回复:2

修改prassthru实现网络数据包的修改出现蓝屏,请高手救命!

楼主#
更多 发布于:2008-09-18 10:55
如题,代码如下:
请高手指教:
NDIS_STATUS
MPSend(
    IN    NDIS_HANDLE                MiniportAdapterContext,
    IN    PNDIS_PACKET            Packet,
    IN    UINT                    Flags
    )

{
    PADAPT                pAdapt = (PADAPT)MiniportAdapterContext;
    NDIS_STATUS            Status;
    PNDIS_PACKET        MyPacket;
    PVOID                MediaSpecificInfo = NULL;
    ULONG                MediaSpecificInfoSize = 0;
#ifdef NDIS51
        {
        PNDIS_PACKET_STACK        pStack;
        BOOLEAN                    Remaining;
                       pStack = NdisIMGetCurrentPacketStack(Packet, &Remaining);
        if (Remaining)
        {
            ASSERT(pStack);
            NdisSend(&Status,
                  pAdapt->BindingHandle,
                      Packet);
            return(Status);
        }
    }
#endif // NDIS51    
    NdisAllocatePacket(&Status,  &MyPacket,pAdapt->SendPacketPoolHandle);

    if (Status == NDIS_STATUS_SUCCESS)
    {
        PSEND_RSVD            SendRsvd;
        
        //添加的代码用于修改数据包
        BOOLEAN bPass = TRUE;
        UCHAR buffer[MAX_PACKET_LEN];
        ULONG nReadBytes;
        PIPHeader pIPHeader;
        PNDIS_BUFFER MyBuffer;
        PUCHAR pPacketContent;
        USHORT iphdrlen;

        // 读取封包中的数据,这里仅读取封包头即可
        FltReadPacketData(Packet, buffer, MAX_PACKET_LEN, &nReadBytes);
        // 检查过滤规则,看看是否允许这个封包进行修改
        bPass = FltCheckFilterRules(buffer, nReadBytes, TRUE);
        if (!bPass)
        {
            pIPHeader = (PIPHeader)(buffer+14);
            iphdrlen = (pIPHeader->iphVerLen & 0x0f) * sizeof(ULONG);

             //point to IP Packet header
            //修改dscp字段 我主要用改程序来修改dscp字段,所以修改的部分就在这里了
            pIPHeader->ipTOS=0x12;
            pIPHeader->ipChecksum=0x00;
            // 计算ip首部校验和
            pIPHeader->ipChecksum = checksum((USHORT *)pIPHeader,iphdrlen);
            //===========================================================================
            //把数据copy给mybuffer
            NdisAllocateBuffer(&Status,&MyBuffer,pAdapt->SendPacketPoolHandle,buffer,nReadBytes);
            NdisChainBufferAtFront(MyPacket, MyBuffer);  //把MyBuffer关联到MyPacket          
            SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved);
                                                               SendRsvd->OriginalPkt = MyPacket;
            MyPacket->Private.Head->Next = NULL;
            MyPacket->Private.Tail = NULL;
            NdisSetPacketFlags(MyPacket, NDIS_FLAGS_DONT_LOOPBACK);
            NdisReturnPackets(&Packet, 1);
            NdisSend(&Status,pAdapt->BindingHandle,MyPacket);
                                                                pPacketContent=buffer;
            if(Status != NDIS_STATUS_PENDING)
            {
                NdisUnchainBufferAtFront(MyPacket ,&MyBuffer); //从MyPacket中解除buffer
                NdisQueryBufferSafe(MyBuffer,&pPacketContent, &nReadBytes,NormalPagePriority );
                if(buffer != NULL)
                    NdisFreeMemory(buffer,nReadBytes, 0);
                NdisFreeBuffer(MyBuffer);
            }

         }
        else
        {
            SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved);
            SendRsvd->OriginalPkt = Packet;
            MyPacket->Private.Flags = Flags;
            MyPacket->Private.Head = Packet->Private.Head;
            MyPacket->Private.Tail = Packet->Private.Tail;
#ifdef WIN9X
            MyPacket->Private.ValidCounts = FALSE;
#endif

            NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket),
                NDIS_OOB_DATA_FROM_PACKET(Packet),
                sizeof(NDIS_PACKET_OOB_DATA));

#ifndef WIN9X
            NdisIMCopySendPerPacketInfo(MyPacket, Packet);
#endif

            
            NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet,
                &MediaSpecificInfo,
                &MediaSpecificInfoSize);
            if (MediaSpecificInfo || MediaSpecificInfoSize)
            {
                NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket,
                    MediaSpecificInfo,
                    MediaSpecificInfoSize);
            }
            NdisSend(&Status,
                pAdapt->BindingHandle,
                MyPacket);
            if (Status != NDIS_STATUS_PENDING)
            {
#ifndef WIN9X
                NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket);
#endif
                NdisFreePacket(MyPacket);
            }

        }
    }
    else
    {
    }

    return(Status);
}
blankheart
驱动牛犊
驱动牛犊
  • 注册日期2008-07-30
  • 最后登录2009-01-24
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望17点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2008-09-18 10:58
下面是上面要用到的函数的定义,其中FltCheckFilterRules函数实现的只是检查改数据包是不是ip包,如果是ip包我们就对其进行数据修改
//计算校验和
USHORT checksum(USHORT* buff, int size)
{
    unsigned long cksum = 0;
    while(size>1)
    {
        cksum += *buff++;
        size -= sizeof(USHORT);
    }
    // 是奇数
    if(size)
    {
        cksum += *(UCHAR*)buff;
    }
    // 将32位的chsum高16位和低16位相加,然后取反
    cksum = (cksum >> 16) + (cksum & 0xffff);
    cksum += (cksum >> 16);            
    return (USHORT)(~cksum);
}

// 读取封包中的数据
void FltReadPacketData(PNDIS_PACKET pPacket,
                       PUCHAR lpBufferIn, ULONG nNumberToRead, PUINT lpNumberOfRead)
{    
    PUCHAR pBuf;
    ULONG nBufferSize;
    PNDIS_BUFFER pBufferDes = NULL;
    // 检查参数
    if(pPacket == NULL || lpBufferIn == NULL || nNumberToRead == 0)
    {
        if(lpNumberOfRead != NULL)
        {
            *lpNumberOfRead = 0;
            return ;
        }
    }

    // 设置返回数据
    *lpNumberOfRead = 0;
    // 遍历封包中的缓冲区描述表,将数据复制到用户缓冲区
    pBufferDes = pPacket->Private.Head;
    while(pBufferDes != pPacket->Private.Tail && pBufferDes != NULL)
    {
        // 获取此缓冲区描述表的缓冲区信息
        NdisQueryBufferSafe(pBufferDes, &pBuf, &nBufferSize, NormalPagePriority);
        if(pBuf == NULL)
            return;

        if(nNumberToRead > nBufferSize) // 复制整个缓冲区
        {
            NdisMoveMemory(lpBufferIn + *lpNumberOfRead, pBuf, nBufferSize);
            nNumberToRead -= nBufferSize;
            *lpNumberOfRead += nBufferSize;
        }
        else                            // 仅复制剩下的部分
        {
            NdisMoveMemory(lpBufferIn + *lpNumberOfRead, pBuf, nNumberToRead);
            *lpNumberOfRead += nNumberToRead;
            return;
        }
        // 下一个缓冲区描述表
        pBufferDes = pBufferDes->Next;
    }
}

// 检查过滤规则
BOOLEAN FltCheckFilterRules(PUCHAR pPacketData, ULONG nDataLen, BOOLEAN bIncludeETHdr)
{    
    int nLeavingLen = nDataLen;

    PETHeader pEtherHdr;
    PIPHeader pIpHdr;
    PTCPHeader pTcpHdr;
    PUDPHeader pUdpHdr;



    // 从缓冲区中萃取出IP头
    // 如果包含以太头,就要先检查以太头
    if(bIncludeETHdr)
    {
        if(nLeavingLen < sizeof(ETHeader))
        {
            return TRUE;
        }
        nLeavingLen -= sizeof(ETHeader);

        pEtherHdr = (PETHeader)pPacketData;

        if(pEtherHdr->type != 0x8) // 如果不是IP协议,则不处理
            return TRUE;

        pIpHdr = (PIPHeader)(pEtherHdr + 1);
    }
    else
    {
        pIpHdr = (PIPHeader)pPacketData;
    }

    // 验证剩余数据长度,防止发生内核非法访问
    if(nLeavingLen < sizeof(IPHeader))
        return TRUE;
    nLeavingLen -= sizeof(IPHeader);


    // 检查版本信息,我们仅处理IPv4
    if(((pIpHdr->iphVerLen >> 4) & 0x0f) == 6)
    {
        return TRUE;
    }

    // 默认情况下接收所有封包
    return FALSE;
}
blankheart
驱动牛犊
驱动牛犊
  • 注册日期2008-07-30
  • 最后登录2009-01-24
  • 粉丝0
  • 关注0
  • 积分1分
  • 威望17点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2008-09-18 11:01
这个程序编译通过后,我将它安装以后,一开机就出现蓝屏,我调了很久了 ,实在是调不出来了,请高手指点指点,老板催得慌,我饭碗不保啊,救命啊!
游客

返回顶部