首页
社区
课程
招聘
[求助]数据包拦截实现
发表于: 2010-5-12 16:01 10884

[求助]数据包拦截实现

2010-5-12 16:01
10884
做ndis hook时,我要求将所有发送出去接收到的数据都截获,然后再将数据包用自己构造的PACKET原样receive。我把我的这部分代码贴上来,主要是接收包,现在我只hook了NdisReceivePacket

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里做什么处理吗?
请各位前辈帮忙看看啊,十分感谢!

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 244
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
参考这个帖子的方法.使用来相当的爽
http://bbs.pediy.com/showthread.php?t=81204

如果只是监听的话,用WinPcap也是个不错的选择.
2010-5-12 17:32
0
雪    币: 284
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
SendCompleteHandler()中截获你自己发的包,该包不能传给被你HOOK的SendCompleteHandler,因为那不是它的包。
你可以在你自己申请的Packet中ProtocolReserved中设置你的标识,在SendCompleteHandler()中截获并释放掉,同时不能再调用被HOOK的SendCompleteHandler。
......
NdisAllocatePacketPoolEx(&Status,
                                        &hPacketPool,
                                        16, 16,
                                        sizeof(SEND_RSVD));

.....
NdisAllocatePacket( &Status, &Packet, hPacketPool );
.....
SendRsvd = (PSEND_RSVD)Packet->ProtocolReserved;
SendRsvd->PacketID = PACKET_ID;

.....

然后调用原来的OpenBlock中的SendHandler来发送包:

HookContext.dobSendHandler(
                        HookContext.pOpenBlock->BindingHandle,
                        Packet);

.....
在你自己的SendComplete()中如下处理:
        PSEND_RSVD                                SendRsvd;
        SEND_COMPLETE_HANDLER        SendComplete;

        SendRsvd = (PSEND_RSVD)Packet->ProtocolReserved;
       
        if (SendRsvd->PacketID == PACKET_ID)
        {
                // 你发的包,做清理工作
                //
                ........
        }
        else
        {
                // 被HOOK协议的包,调用Hooked routine
                //
                SendComplete = HookContext.dobSendCompleteHandler;
                if (SendComplete)
                {
                        SendComplete(ProtocolBindingContext,
                                                 Packet,
                                                 Status);
                }
        }

HOOK方式下的发包大概就这样。

至于调试的时候死机,你得用Windbg调试看看到底是哪出错了。
2010-5-12 20:10
0
雪    币: 213
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
谢谢yeerh,我要用的ndis hook哈。
谢谢ceabie,我现在主要问题是在收包的时候哈。
2010-5-13 09:01
0
游客
登录 | 注册 方可回帖
返回
//