阅读:2366回复:0
hook ndis5 and ndis6
网卡的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; } |
|