pdavidchang
驱动牛犊
驱动牛犊
  • 注册日期2006-06-14
  • 最后登录2015-10-13
  • 粉丝0
  • 关注0
  • 积分32分
  • 威望251点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2726回复:11

数据包拦截实现

楼主#
更多 发布于:2010-05-07 16:23
通过注册假协议的方法hook ndis,要hook哪些handler呢?

我要求将所有发送出去的数据都截获,然后用自己构造的PACKET再将数据包原样发送出去。
接收到的数据也要截获,用自己构造的PACKET送入网卡。
需要怎么做啊?
发送的时候我都是NdisAllocateMemory,NdisAllocateBuffer,NdisAllocatePacket,构造了MyPacket,再调用SendHandler或SendPacketsHandler发送出去MyPacket,再处理SendCompleteHandler,释放,好像没什么问题。
接受的时候同样做NdisAllocateMemory,NdisAllocateBuffer,NdisAllocatePacket,构造了MyPacket,调用ReceiveHandler或ReceivePacketHandler接受,不知道还要怎样处理,我的要蓝屏??

还有一问,我想在驱动初始化的时候NdisAllocateMemory,NdisAllocateBuffer,NdisAllocatePacket,分配这些,然后每次处理数据的时候就不用再重新分配了,应该效率要高一些,可是这样做要蓝屏,为什么呢?

希望有前辈们尽快帮我解决一下啊!!
pdavidchang
驱动牛犊
驱动牛犊
  • 注册日期2006-06-14
  • 最后登录2015-10-13
  • 粉丝0
  • 关注0
  • 积分32分
  • 威望251点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2010-05-07 16:26
现在的驱网人气貌似不是很好啊
cyliu
论坛版主
论坛版主
  • 注册日期2003-06-13
  • 最后登录2014-04-11
  • 粉丝5
  • 关注0
  • 积分1238分
  • 威望2531点
  • 贡献值0点
  • 好评度577点
  • 原创分14分
  • 专家分10分
板凳#
发布于:2010-05-07 16:38
不是没有人气,而是所要知道的问题都有贴了,自己去查看一些贴就可以了。

最后一个问题不知道你怎么处理,当然不知道为什么蓝屏。

初始化就申请一个数据报内存,不蓝才怪呢。把问题描述清楚些才能知道原因。
走走看看开源好 Solaris vs Linux
pdavidchang
驱动牛犊
驱动牛犊
  • 注册日期2006-06-14
  • 最后登录2015-10-13
  • 粉丝0
  • 关注0
  • 积分32分
  • 威望251点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2010-05-09 20:16
我的问题很简单也很清楚啊,就是把所有ndis处理的包hook了,拦截到我的包中,再将我的包发出去,包的所有内容不做任何修改。
至于说以前的帖子,不是没认真找,说实话就像大海捞针,而且很多也是问的问题而没有答案,或者不是我要的答案啊。
要是有这么一个系统的讲解这方面的帖子,该有多好啊,或者是我没看到,还望坛主指教呢。
我 是 个新手,但谁都有过这个阶段啊,如果达人们肯小小的指点一下,岂不是受益匪浅。
“初始化就申请一个数据报内存,不蓝才怪呢”,到底该怎么做呢?
不知坛主可不可以指点几篇帖子让小弟去学习学习啊?
vipfengxiao
驱动牛犊
驱动牛犊
  • 注册日期2009-12-29
  • 最后登录2011-12-21
  • 粉丝1
  • 关注0
  • 积分79分
  • 威望681点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2010-05-10 12:23
发送的时候:(oldPacket是原来的包,newPacket是你重组的包

    
       NdisGetPacketFlags(newPacket) = Flags;


        NdisQueryPacket(oldPacket, NULL, NULL, &ndis_buffer, &totaLlen);
      status = NdisAllocateMemory((PVOID)&newBuf, totaLlen, 0, MaxAddress);
     if(status != NDIS_STATUS_SUCCESS)
     {
         //内存分配失败,用原包发送
          NDIS_PACKET_FIRST_NDIS_BUFFER(newPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(oldPacket);
             NDIS_PACKET_LAST_NDIS_BUFFER(newPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(oldPacket);
     }
     else
     {
     //    NdisZeroMemory((PVOID)&newBuf, totaLlen);
         tmpBuf = newBuf;
         //自己分配内存构建新包
          while (NULL != ndis_buffer)
            {
                NdisQueryBufferSafe(ndis_buffer, &address, &current_len, NormalPagePriority);
                NdisMoveMemory(tmpBuf, address, current_len);
                (PUCHAR)tmpBuf += current_len;
                NdisGetNextBuffer(ndis_buffer, &ndis_buffer);
            }
          
          NdisAllocateBuffer(&status, &myBuf, pAdapt->SendPacketPoolHandle, newBuf, totaLlen);                    
            if (NDIS_STATUS_SUCCESS != status)
            {
                  DBGPRINT(("setPacketDesc-------------->NdisAllocateBuffer FAILED\n"));
                NdisFreeMemory(newBuf, totaLlen, 0);
                NDIS_PACKET_FIRST_NDIS_BUFFER(newPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(oldPacket);
                NDIS_PACKET_LAST_NDIS_BUFFER(newPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(oldPacket);
            }
          else
         {
             // DBGPRINT(("setPacketDesc-------------->NdisAllocateBuffer SUCCESSED\n"));
              NdisChainBufferAtFront(newPacket, myBuf);
         }
     }


到这里只是包重组了 没做任何修改  如果你需要做修改可以在myBuf里面修改任何你想要修改的东西

接收的时候:
   // 将包头和 LookAheadBuffer 复制到新分配的内存中
   NdisZeroMemory(pPacketContent, BUFFER_SIZE);
   NdisMoveMemory(pPacketContent, HeaderBuffer, HeaderBufferSize);
   NdisMoveMemory(pPacketContent+ HeaderBufferSize, LookAheadBuffer, LookAheadBufferSize);
   PacketLen = PacketSize+HeaderBufferSize;
   Status=NdisAllocateMemoryWithTag((PVOID *)&pPacket, 4, 'maDN');
   if(Status != NDIS_STATUS_SUCCESS)
   {
    DbgPrint("PTReceive:NdisAllocateMemory Failed\n");
    return(NDIS_STATUS_NOT_ACCEPTED);
   }
   if(pPacket== NULL)
   {
    DbgPrint("PTReceive:pPacket==NULL\n");
    return(NDIS_STATUS_NOT_ACCEPTED);
   }
  // 在包池中分配包描述符
    NdisDprAllocatePacket(&Status, &MyPacket, pAdapt->RecvPacketPoolHandle);
    if(Status == NDIS_STATUS_SUCCESS)
    {
     DbgPrint("--------------------------------------------------------开始关联包.\n");
     // 在缓冲池中分配缓冲描述符,将包描述符与缓冲描述符关联。
     NdisAllocateBuffer(&Status, &pPacketBuffer, pAdapt->RecvBufferPoolHandle, pPacketContent,PacketLen);
     NdisChainBufferAtFront(MyPacket, pPacketBuffer);
    
     MyPacket->Private.Head->Next = NULL;
     MyPacket->Private.Tail = NULL;
     RecvRsvd=(PRECV_RSVD)(MyPacket->MiniportReserved);
     RecvRsvd->OriginalPkt = NULL;
     NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);
    
     // 向上层协议驱动指示数据包,防真网卡行为。
     NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);
     if(NDIS_GET_PACKET_STATUS(MyPacket) != NDIS_STATUS_PENDING)
     {
      DBGPRINT(("In PtReceive And Free Memory\n"));
      NdisFreeBuffer(pPacketBuffer);
      
      NdisFreeMemory(pPacketContent, BUFFER_SIZE, 0);
      NdisFreeMemory(pPacket, 4, 0);
      
      NdisDprFreePacket(MyPacket);
     }
    }

这里也是对包没有做任何修改 你要修改的话可以在pPacketContent做任何你想做的事情然后关联

讲的很清楚了 你要还做不出来我也没办法了
cyliu
论坛版主
论坛版主
  • 注册日期2003-06-13
  • 最后登录2014-04-11
  • 粉丝5
  • 关注0
  • 积分1238分
  • 威望2531点
  • 贡献值0点
  • 好评度577点
  • 原创分14分
  • 专家分10分
5楼#
发布于:2010-05-10 12:26
1 除了最后一个问题其他没说你描述不清楚

2 最后一个问题你没有描述清楚:是开始申请一个池,还是只有一个数据报?不知道

3 察看精华贴,有关于ndis流程的介绍。

4 每个人都在工作,既然有答案了,何必再回答? 只有我还这么无聊出来说话,呵呵!

每个人都有新手阶段,但每个人也都是这么经历过来的。所以有了资料,还是需要自己去查找整理消化。当然确实是难题的除外。
走走看看开源好 Solaris vs Linux
pdavidchang
驱动牛犊
驱动牛犊
  • 注册日期2006-06-14
  • 最后登录2015-10-13
  • 粉丝0
  • 关注0
  • 积分32分
  • 威望251点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2010-05-10 16:52
谢谢cyliu,谢谢vipfengxiao,我开始去消化吸收了。
如果再遇到问题不过还望你们一如既往的帮助小弟。
其实我也是从一无所知到现在的哈,我也会自己去努力学习的。
总之,谢谢你们。
pdavidchang
驱动牛犊
驱动牛犊
  • 注册日期2006-06-14
  • 最后登录2015-10-13
  • 粉丝0
  • 关注0
  • 积分32分
  • 威望251点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2010-05-10 17:54
这样吧,我把我的这部分代码贴上来,主要是接收包的部分,现在我只hook了ReceivePacketHandler
INT NDIS_API
MyReceivePacket( IN    NDIS_HANDLE ProtocolBindingContext,  IN    PNDIS_PACKET Packet)
{
    INT nRet;
    BOOLEAN bIsMyFilterPacket = FALSE;
    //KdPrint(("---HOOK-----MyReceivePacket\n"));

    bIsMyFilterPacket = MyFilterReceivePacket(Packet);
    if (bIsMyFilterPacket)
    {
        //KdPrint(("FilterReceivePacket success!\n"));
        nRet = ((RECEIVE_PACKET_HANDLER)m_pReceivePacket)(ProtocolBindingContext, m_pMyPacket);//    
        if (NDIS_GET_PACKET_STATUS(m_pMyPacket) != NDIS_STATUS_PENDING)
        {
            //KdPrint(("ReceivePacket free...\n"));
            if (m_pMyBuffer)
            {
                NdisFreeBuffer(m_pMyBuffer);
                m_pMyBuffer = NULL;
            }
            if (m_pBuffer)
            {
                NdisFreeMemory(m_pBuffer, m_nMyPacketLen, 0);
                m_pBuffer = NULL;
            }
            if (m_pMyPacket)
            {
                NdisFreePacket(m_pMyPacket);
                m_pMyPacket = NULL;
            }
        }
    }
    else
        nRet = ((RECEIVE_PACKET_HANDLER)m_pReceivePacket)(ProtocolBindingContext, Packet);

    return nRet;
}

//我的处理接收数据包的函数
BOOLEAN MyFilterReceivePacket(PNDIS_PACKET pPacket)
{
    NTSTATUS nStatus;
    DWORD dwPacketSize = 0;
    PVOID pBuffer = NULL;
    PNDIS_BUFFER pCurrentBuffer,pNextBuffer;
    PVOID pVirtualAddress;
    UINT len;
    DWORD count = 0;

    //取得包的大小及第一个NDIS_BUFFER指针
    //或者pCurrentBuffer = pPacket->Private.Head;
    NdisQueryPacket(pPacket, NULL, NULL, &pCurrentBuffer, &dwPacketSize);
    if (dwPacketSize < sizeof(ETHHDR))
        return FALSE;

    //分配空间
    nStatus = NdisAllocateMemoryWithTag(&pBuffer, dwPacketSize, 'NAMW');
    if (nStatus != NDIS_STATUS_SUCCESS || pBuffer == NULL)
        return FALSE;

    //读取包
    while (pCurrentBuffer != NULL)
    {
        //NdisQueryBufferSafe can't use in wdm1.0
        NdisQueryBufferSafe(pCurrentBuffer, &pVirtualAddress, &len, NormalPagePriority);
        if(!pVirtualAddress)
        {
            break;
        }
        if (count + len > dwPacketSize)
            break;
        NdisMoveMemory(&((BYTE *)pBuffer)[count], pVirtualAddress, len);
        count += len;
        NdisGetNextBuffer(pCurrentBuffer, &pNextBuffer);//
        pCurrentBuffer = pNextBuffer;
    }

    //////////////////////////////////////////////////////////////////////////
             //这部分就是将原始包拷贝到我的PACKET中,不做任何修改

    m_nMyPacketLen = dwPacketSize;

    m_pBuffer = NULL;
    nStatus = NdisAllocateMemoryWithTag(&m_pBuffer, m_nMyPacketLen, 'NAMW');
    if (nStatus != NDIS_STATUS_SUCCESS)
        return FALSE;

    //------------
    NdisZeroMemory((BYTE*)m_pBuffer, m_nMyPacketLen);
    NdisMoveMemory((BYTE*)m_pBuffer, (BYTE*)pBuffer, m_nMyPacketLen);

    m_pMyBuffer = NULL;
    //m_hMyBufferPool,m_hMyPacketPool是在初始化的时候分配的
             NdisAllocateBuffer(&nStatus, &m_pMyBuffer, m_hMyBufferPool, m_pBuffer, m_nMyPacketLen);
    if (nStatus != NDIS_STATUS_SUCCESS)
        return FALSE;

    m_pMyPacket = NULL;
    NdisAllocatePacket(&nStatus, &m_pMyPacket, m_hMyPacketPool);
    if (nStatus != NDIS_STATUS_SUCCESS)
        return FALSE;

    NdisChainBufferAtFront(m_pMyPacket, m_pMyBuffer);
    m_pMyPacket->Private.Head->Next=NULL;
    m_pMyPacket->Private.Tail=NULL;
    NDIS_SET_PACKET_HEADER_SIZE(m_pMyPacket,14);
    //NdisSetPacketFlags(m_pMyPacket, NDIS_FLAGS_DONT_LOOPBACK); //避免收到自己发送的包

    ////////////////////////////////////////////////////////////////////////////

    //释放空间
    NdisFreeMemory(pBuffer, dwPacketSize, 0);
    return TRUE;
}

其他hook函数我没有做任何处理,仅仅是调用了原来的Handler。
可是调试的时候还是要死,不知道还要在SendCompleteHandler里做什么处理吗?
还烦cyliu,vipfengxiao有时间的话给我看看哈,谢谢了!
pdavidchang
驱动牛犊
驱动牛犊
  • 注册日期2006-06-14
  • 最后登录2015-10-13
  • 粉丝0
  • 关注0
  • 积分32分
  • 威望251点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2010-05-11 11:05
to vipfengxiao:
" Status=NdisAllocateMemoryWithTag((PVOID *)&pPacket, 4, 'maDN'); "
请问这里分配的pPacket是用来做什么的呢?
vipfengxiao
驱动牛犊
驱动牛犊
  • 注册日期2009-12-29
  • 最后登录2011-12-21
  • 粉丝1
  • 关注0
  • 积分79分
  • 威望681点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2010-05-11 12:13
回 8楼(pdavidchang) 的帖子
这个没用 是我的程序中用到的你不用管
pdavidchang
驱动牛犊
驱动牛犊
  • 注册日期2006-06-14
  • 最后登录2015-10-13
  • 粉丝0
  • 关注0
  • 积分32分
  • 威望251点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2010-05-11 15:07
Re:回 8楼(pdavidchang) 的帖子
引用第9楼vipfengxiao于2010-05-11 12:13发表的 回 8楼(pdavidchang) 的帖子 :
这个没用 是我的程序中用到的你不用管  


那么请问我贴的代码有什么问题呢?期待你的回复啊,呵呵
pdavidchang
驱动牛犊
驱动牛犊
  • 注册日期2006-06-14
  • 最后登录2015-10-13
  • 粉丝0
  • 关注0
  • 积分32分
  • 威望251点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2010-05-12 09:20
游客

返回顶部