lybf2631
驱动牛犊
驱动牛犊
  • 注册日期2011-02-25
  • 最后登录2011-03-05
  • 粉丝0
  • 关注0
  • 积分6分
  • 威望31点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2366回复:0

hook ndis5 and ndis6

楼主#
更多 发布于:2011-02-25 03:17
网卡的offload开启的情况下目的机器就收不到包,关闭offload就可以,很奇怪,希望大牛们指点下

PFN_RtlGetVersion pfnRtlGetVersion = NULL;
        UNICODE_STRING ustrFuncName ;
        RtlInitUnicodeString(&ustrFuncName, L"RtlGetVersion");
        pfnRtlGetVersion = MmGetSystemRoutineAddress(&ustrFuncName);
        if (pfnRtlGetVersion)
        {        
            pfnRtlGetVersion((PRTL_OSVERSIONINFOW)&osverinfo);
            
            FLOG(("dwMajorVersion=%d dwMinorVersion=%d wServicePackMajor=%d wServicePackMinor=%d\n",
                osverinfo.dwMajorVersion,osverinfo.dwMinorVersion,osverinfo.wServicePackMajor,osverinfo.wServicePackMinor));
            if(6 <= osverinfo.dwMajorVersion)
            {
                FLOG(("windows vista 7 2008 and later .. \r\n"));
                

                offset_OpenQueue    = NDIS_PROTOCOL_BLOCK_OFFSET_WIN7_OpenQueue;
                offset_NextProtocol = NDIS_PROTOCOL_BLOCK_OFFSET_WIN7_NextProtocol;
                offset_Name            = NDIS_PROTOCOL_BLOCK_OFFSET_WIN7_Name;

                offset_Open_BindDeviceName  = NDIS_OPEN_BLOCK_OFFSET_WIN7_BindDeviceName;
                offset_Open_Next            = NDIS_OPEN_BLOCK_OFFSET_WIN7_Next;
                
            }else{
                FLOG(("windows xp 2003 and before .. \n"));

                offset_OpenQueue    = NDIS_PROTOCOL_BLOCK_OFFSET_OpenQueue;
                offset_NextProtocol = NDIS_PROTOCOL_BLOCK_OFFSET_NextProtocol;
                offset_Name            = NDIS_PROTOCOL_BLOCK_OFFSET_Name;
                
                offset_Open_BindDeviceName = NDIS_OPEN_BLOCK_OFFSET_BindDeviceName;
                offset_Open_Next            = NDIS_OPEN_BLOCK_OFFSET_Next;
            }
        }else{
            offset_OpenQueue    = NDIS_PROTOCOL_BLOCK_OFFSET_OpenQueue;
            offset_NextProtocol = NDIS_PROTOCOL_BLOCK_OFFSET_NextProtocol;
            offset_Name            = NDIS_PROTOCOL_BLOCK_OFFSET_Name;

            offset_Open_BindDeviceName = NDIS_OPEN_BLOCK_OFFSET_BindDeviceName;
            offset_Open_Next            = NDIS_OPEN_BLOCK_OFFSET_Next;
        }  

        do
        {                
            ANSI_STRING tempStr;

            //
            //if(6 <= osverinfo.dwMajorVersion)
            //{
            //    _asm int 3;
            //}

            //获取NDIS_PROTOCOL_BLOCK
            pPBlockList = GetPTBlock();            

            while(pPBlockList)
            {            
                //获取协议名称
                pProtoName = (PNDIS_STRING)(pPBlockList+offset_Name);//Name

                if(FALSE == RtlCompareUnicodeString(pProtoName,&TcpipString,TRUE) )
                {
                    UCHAR* pOpenBlock = ((UCHAR**)(pPBlockList+offset_OpenQueue))[0];//OpenQueue
            
                    //
                    RtlUnicodeStringToAnsiString(&tempStr,pProtoName,TRUE);
                    FLOG(("ProtoName=%s\n",tempStr.Buffer));
                    RtlFreeAnsiString(&tempStr);
                
                    while(pOpenBlock)
                    {
                        //
                        pDeviceName = ((PNDIS_STRING*)(pOpenBlock+offset_Open_BindDeviceName))[0];

                        RtlUnicodeStringToAnsiString(&tempStr,pDeviceName,TRUE);
                        FLOG(("pOpenBlock->BindDeviceName=%s \n",tempStr.Buffer));//name
                        RtlFreeAnsiString(&tempStr);

                        HookingBlock(pOpenBlock);

                        pOpenBlock = ((UCHAR**)(pOpenBlock+offset_Open_Next))[0];//next adapter
                    }
                }

                pPBlockList = ((UCHAR**)((UCHAR*)pPBlockList+offset_NextProtocol))[0];//Next
            }            

        }while(FALSE);


////
VOID HookingBlock(UCHAR* pOpenBlock)
{    
    FLOG(("HookingBlock\n"));
    

    if(6 > osverinfo.dwMajorVersion)
    {
        //NDIS5
        PNDIS_OPEN_BLOCK pBlock = (PNDIS_OPEN_BLOCK)pOpenBlock;
        HookNdisFunc(HookedReceiveHandler,(PVOID *)&pBlock->ReceiveHandler,pOpenBlock);
        HookNdisFunc(HookedReceivePacketHandler,(PVOID *)&pBlock->ReceivePacketHandler,pOpenBlock);

        HookNdisFunc(HookedSendHandler,(PVOID *)&pBlock->SendHandler,pOpenBlock);
        HookNdisFunc(HookedSendPacketsHandler,(PVOID *)&pBlock->SendPacketsHandler,pOpenBlock);
    }else{
                HookNdisFunc(HookedReceiveNetBufferLists,(PVOID *)(pOpenBlock+0x478),pOpenBlock);

        if(FALSE == HookedNdisSendNetBufferLists)
        {
            //ndis!NdisSendNetBufferLists

            KIRQL Irql;                    

            //获取函数地址
            void* ndis_base = find_system_dll("ndis.sys");
            if(ndis_base)
            {
                AddrNdisSendNetBufferLists = (ULONG)find_export(ndis_base,"NdisSendNetBufferLists");
            }
            do
            {
                if(0 == AddrNdisSendNetBufferLists)
                {
                    break;
                }

                //保存函数前5个字节内容
                RtlCopyMemory(OriginalBytes,(UCHAR *)AddrNdisSendNetBufferLists,5);

                //写入4字节跳转偏移地址
                *(ULONG *)(JmpAddress+1)=(ULONG)NewNdisSendNetBufferLists-((ULONG)AddrNdisSendNetBufferLists+5);

                _asm                                            //disable WP bit
                {
                    mov eax,cr0                                 //move CR0 register into EAX
                    and eax,not 000010000h                      //disable WP bit
                    mov cr0,eax                                 //write register back
                }
                //写入Naked函数
                RtlCopyMemory(OldNdisSendNetBufferLists,OriginalBytes,5);

                //提升IRQL中断级
                Irql=KeRaiseIrqlToDpcLevel();
                //五个字节JMP写入目标函数
                RtlCopyMemory((UCHAR *)AddrNdisSendNetBufferLists,JmpAddress,5);  
                //恢复Irql
                KeLowerIrql(Irql);
                _asm                                            //enable WP bit
                {
                    mov eax,cr0                                 //move CR0 register into EAX
                    or eax,000010000h                           //enable WP bit        
                    mov cr0,eax                                 //write register back          
                }
                HookedNdisSendNetBufferLists = TRUE;

                FLOG(("HookedNdisSendNetBufferLists =%x\n",AddrNdisSendNetBufferLists));
            }while(FALSE);            
        }        
    
    }

}

//
void NatSendHandler(char* pPacket,ULONG dLen)
{
    struct ether_header*     p_et_header;
    struct ip*                 p_ip_header;
    struct tcphdr*             p_tcp_header;
    struct udphdr*             p_udp_header;

    if(dLen < sizeof(struct ether_header))
    {
        goto ExitTheFilter;
    }
    p_et_header = (struct ether_header*)pPacket;
    switch( ntohs( p_et_header->ether_type ) )
    {
        // See ..\B2Winet/ethernet.h for ETHERTYPE Definitions
        case ETHERTYPE_IP:
        break;

        case ETHERTYPE_ARP:
        default:
        goto ExitTheFilter;
    }

    if(dLen < sizeof(struct ether_header)+sizeof(struct ip))
    {
        goto ExitTheFilter;
    }
    p_ip_header = (struct ip*)(pPacket+sizeof(struct ether_header));
    switch( p_ip_header->ip_v )
    {
        case 4:        // IPv4
        break;

        case 6:        // IPv6
        default:
        goto ExitTheFilter;
    }

    if(p_ip_header->ip_dst.s_addr == pNatIP->sourIP)
    {
        FLOG(("NatSendHandler\n"));

        p_ip_header->ip_dst.s_addr = pNatIP->destIP;                
        p_ip_header->ip_sum = GetIncCheckSum(p_ip_header->ip_sum,pNatIP->sourIP,pNatIP->destIP);

        do
        {
            USHORT iphdrlen = (p_ip_header->ip_hl & 0x0f) * sizeof(ULONG);//ip头的实际大小

            if(IPPROTO_TCP == p_ip_header->ip_p)
            {
                if(dLen < sizeof(struct ether_header)+iphdrlen+sizeof(struct tcphdr))
                {
                    break;
                }
                p_tcp_header = (struct tcphdr*)((UCHAR*)p_ip_header+iphdrlen);
                p_tcp_header->th_sum = GetIncCheckSum(p_tcp_header->th_sum,pNatIP->sourIP,pNatIP->destIP);
            }
            if(IPPROTO_UDP == p_ip_header->ip_p)
            {
                if(dLen < sizeof(struct ether_header)+iphdrlen+sizeof(struct udphdr))
                {
                    break;
                }
                p_udp_header = (struct udphdr*)((UCHAR*)p_ip_header+iphdrlen);
                p_udp_header->uh_sum = GetIncCheckSum(p_udp_header->uh_sum,pNatIP->sourIP,pNatIP->destIP);
            }
            //ok

        }while(FALSE);        
    }

    //exit
ExitTheFilter:    
    return;
}
游客

返回顶部