阅读:2133回复:4
关于数据包转发的问题
我要实现如下功能:
在截获的数据包内容中,加入自己的信息,转发到其他的机器上,现在的问题是:那边机器收到的数据包中 ,没有我加入的信息. NDIS_STATUS FakePacket( PNDIS_PACKET pPacket , PADAPT pAdapt , BOOLEAN bSender ) { NDIS_STATUS nRet = NDIS_STATUS_FAILURE; PUCHAR pPacketContent = NULL; PUCHAR pCustomPacketContent = NULL; PNDIS_BUFFER NdisBuffer ; UINT TotalPacketLength = 0; UINT copysize = 0; UINT DataOffset = 0 ; UINT PhysicalBufferCount; UINT BufferCount ; PUCHAR tembuffer = NULL ; UINT ActualDataLength=0; PVOID VirtualAddress; UINT Length=0; UINT DataToCopy; PNDIS_BUFFER Buffer; UINT HeaderSize = 0; PETHERNET_FRAME pEthernetFrame = NULL; PIP_HEADER pIpHeader = NULL; PTCP_HEADER pTcpHeader = NULL; PUDP_HEADER pUdpHeader = NULL; PICMP_HEADER pIcmpHeader = NULL; UINT uOldPacketSize; UINT uIpHeader = IP_HEADER_LENGTH; UINT uTcpHeader = TCP_HEADER_LENGTH; UINT uUdpHeader = UDP_HEADER_LENGTH; UINT uIcmpHeader =ICMP_HEADER_LENGTH; UINT uRealDataSize = 0; UINT nIndex = 0; UINT nHeaderLen = 0; do { if ( pPacket == NULL ) break; //if( g_nTimesSend == 0 ) break; HeaderSize = NDIS_GET_PACKET_HEADER_SIZE(pPacket); nRet = NdisAllocateMemoryWithTag( &pPacketContent, 2048, TAG); if( nRet != NDIS_STATUS_SUCCESS ) break; NdisZeroMemory( pPacketContent, 2048 ) ; // 找到第一个Ndis_Buffer。然后通过通过NdisGetNextBuffer来获得后续的NDIS_BUFFER。 // 如果只是找第一个节点,更快且方便的方法是调用NdisGetFirstBufferFromPacket。 NdisQueryPacket(pPacket, // NDIS_PACKET &PhysicalBufferCount,// 内存中的物理块数 &BufferCount, // 多少个NDIS_BUFFER包 &NdisBuffer, // 将返回第一个包 &TotalPacketLength // 总共的包数据长度 ); while(TRUE){ // 取得Ndis_Buffer中存储缓冲区的虚拟地址。 // 这个函数的另一个版本是NdisQueryBuffer。 // 后者在系统资源低或者甚至耗尽的时候,会产生Bug Check,导致蓝屏。 NdisQueryBufferSafe(NdisBuffer, &tembuffer,// 缓冲区地址 ©size, // 缓冲区大小 NormalPagePriority ); // 如果tembuffer为NULL,说明当前系统资源匮乏。 if(tembuffer != NULL){ NdisMoveMemory( pPacketContent + DataOffset , tembuffer, copysize) ; DataOffset += copysize; } // 获得下一个NDIS_BUFFER。 // 如果得到的是一个NULL指针,说明已经到了链式缓冲区的末尾,我们的循环应该结束了。 NdisGetNextBuffer(NdisBuffer , &NdisBuffer ) ; if( NdisBuffer == NULL ) break ; } DBGPRINT(("FakePacket : BufferCount : %d , NdisQueryPacket - TotalPacketLength : %d , DataOffset : %d\n " , BufferCount , TotalPacketLength,DataOffset)); pEthernetFrame = (PETHERNET_FRAME)&pPacketContent[0]; //判断是否为IP数据包 if(NTOHS(pEthernetFrame->FrameType)!=ETHERTYPE_IP) { DBGPRINT(("==========> not IP packet\n")); break; } if( bSender == TRUE ) { //如果为IP数据包则判断是否获得了IP数据包的足够数据,以太网帧头14+IP包头20 if(TotalPacketLength<ETHERNET_FRAME_LENGTH+IP_HEADER_LENGTH) { break; } else pIpHeader=(PIP_HEADER)&pPacketContent[ETHERNET_FRAME_LENGTH]; RtlCopyMemory(pEthernetFrame->DestinationAddress, g_client_mac, MAC_LEN); RtlCopyMemory(pEthernetFrame->SourceAddress, g_server_mac, MAC_LEN); switch(pIpHeader->Protocol) { case PROTOCOL_TCP: uRealDataSize = TotalPacketLength - ETHERNET_FRAME_LENGTH - IP_HEADER_LENGTH - TCP_HEADER_LENGTH; DBGPRINT((" ======> [TCP] uRealDataSize : %d\n" , uRealDataSize )); nHeaderLen = ETHERNET_FRAME_LENGTH + IP_HEADER_LENGTH + TCP_HEADER_LENGTH; pTcpHeader = (PTCP_HEADER)&pPacketContent[ETHERNET_FRAME_LENGTH +IP_HEADER_LENGTH]; break; case PROTOCOL_UDP: uRealDataSize = TotalPacketLength - ETHERNET_FRAME_LENGTH - IP_HEADER_LENGTH - UDP_HEADER_LENGTH; DBGPRINT((" ======> [UDP] uRealDataSize : %d\n" , uRealDataSize )); nHeaderLen = ETHERNET_FRAME_LENGTH + IP_HEADER_LENGTH + UDP_HEADER_LENGTH; pUdpHeader = (PUDP_HEADER)&pPacketContent[ETHERNET_FRAME_LENGTH +IP_HEADER_LENGTH]; break; case PROTOCOL_ICMP: uRealDataSize = TotalPacketLength - ETHERNET_FRAME_LENGTH - IP_HEADER_LENGTH - ICMP_HEADER_LENGTH; DBGPRINT((" ======> [ICMP] uRealDataSize : %d\n" , uRealDataSize )); nHeaderLen = ETHERNET_FRAME_LENGTH + IP_HEADER_LENGTH + ICMP_HEADER_LENGTH; pIcmpHeader = (PICMP_HEADER)&pPacketContent[ETHERNET_FRAME_LENGTH +IP_HEADER_LENGTH]; break; default: uRealDataSize = 0; break; } if ( uRealDataSize > 0 ) { custom_header_info csHeaderInfo = {0}; nRet = NdisAllocateMemoryWithTag( &pCustomPacketContent , uRealDataSize + FLAG_LEN + 4 , TAG ); if( nRet != NDIS_STATUS_SUCCESS ) break; NdisZeroMemory( pCustomPacketContent, uRealDataSize + FLAG_LEN + 4 ) ; DBGPRINT(("FakePacket -- before xor Data : \n")); PrintBufData( &pPacketContent[nHeaderLen] , uRealDataSize ); //仅仅对实际的数据作异或操作 for ( nIndex = 0 ; nIndex < uRealDataSize ; nIndex++ ) { char* pBuf = &pPacketContent[nHeaderLen+nIndex]; *pBuf ^= XOR_SEED; } //build our special header RtlCopyMemory( csHeaderInfo.szMd5 , DEF_szMd5Flag , FLAG_LEN ); csHeaderInfo.protocol_type = _htonl(CHALLENGE_PACKET); DBGPRINT(("FakePacket -- after xor Data : \n")); PrintBufData( &pPacketContent[nHeaderLen] , uRealDataSize ); //rebuild real data NdisMoveMemory( pCustomPacketContent , &csHeaderInfo , FLAG_LEN + 4 ); NdisMoveMemory( pCustomPacketContent + FLAG_LEN + 4 , &pPacketContent[nHeaderLen] , uRealDataSize ); NdisZeroMemory( &pPacketContent[nHeaderLen], uRealDataSize ) ; NdisMoveMemory( pPacketContent + nHeaderLen , pCustomPacketContent , uRealDataSize + FLAG_LEN + 4 ); pIpHeader->DestinationIp = g_uDestIp; pIpHeader->SourceIp = g_uSrcIp; //calc modified packet size pIpHeader->DatagramLength = _htons( TotalPacketLength + FLAG_LEN + 4 ); //checksum IP header pIpHeader->CheckSum = 0; pIpHeader->CheckSum = _htons(checksum( &pPacketContent[ETHERNET_FRAME_LENGTH] , IP_HEADER_LENGTH )); DBGPRINT(("\nHere , show modified packet:\n")); PrintBufData( pPacketContent , NTOHS(pIpHeader->DatagramLength)); switch(pIpHeader->Protocol) { case PROTOCOL_TCP: nRet = ModifyPacketWndSize( PROTOCOL_TCP , pPacketContent , NTOHS(pIpHeader->DatagramLength) ); break; case PROTOCOL_UDP: nRet = ModifyPacketWndSize( PROTOCOL_UDP , pPacketContent , NTOHS(pIpHeader->DatagramLength) ); break; case PROTOCOL_ICMP: break; default: break; } if ( nRet == NDIS_STATUS_SUCCESS ) { DBGPRINT(( "[sender] FakePacket Checksum : 0x%x , DatagramLength : %d , source ip : %d.%d.%d.%d , dest ip : %d.%d.%d.%d\n" ,NTOHS(pIpHeader->CheckSum) , NTOHS(pIpHeader->DatagramLength) , dbg_ip(NTOHL(g_uSrcIp)) , dbg_ip(NTOHL(g_uDestIp)))); PrinfPacketRealData( pPacketContent , NTOHS(pIpHeader->DatagramLength) ); DBGPRINT(("\nBefore CD_SendPacket")); //send modified packet nRet = CD_SendPacket(pAdapt, &pPacketContent, NTOHS(pIpHeader->DatagramLength) ); if (nRet != NDIS_STATUS_SUCCESS && nRet != NDIS_STATUS_PENDING) { DbgPrint("MySendPacket error : 0x%08x\n", nRet); } else { //DbgPrint(" \n "); } } } } else { //如果为IP数据包则判断是否获得了IP数据包的足够数据,以太网帧头14+IP包头20 if(TotalPacketLength<ETHERNET_FRAME_LENGTH+IP_HEADER_LENGTH) { break; } else pIpHeader=(PIP_HEADER)&pPacketContent[ETHERNET_FRAME_LENGTH]; DBGPRINT(( "[receiver] FakePacket Checksum : 0x%x , DatagramLength : %d , src ip : %d.%d.%d.%d , dest ip : %d.%d.%d.%d\n" , NTOHS(pIpHeader->CheckSum) , NTOHS( pIpHeader->DatagramLength ) , dbg_ip( NTOHL( pIpHeader->SourceIp )) , dbg_ip(NTOHL( pIpHeader->DestinationIp )) )); switch(pIpHeader->Protocol) { case PROTOCOL_TCP: uRealDataSize = TotalPacketLength - ETHERNET_FRAME_LENGTH - IP_HEADER_LENGTH - TCP_HEADER_LENGTH; //DBGPRINT((" <====== [TCP] uRealDataSize : %d\n" , uRealDataSize )); nHeaderLen = ETHERNET_FRAME_LENGTH + IP_HEADER_LENGTH + TCP_HEADER_LENGTH; break; case PROTOCOL_UDP: uRealDataSize = TotalPacketLength - ETHERNET_FRAME_LENGTH - IP_HEADER_LENGTH - UDP_HEADER_LENGTH; //DBGPRINT((" <====== [UDP] uRealDataSize : %d\n" , uRealDataSize )); nHeaderLen = ETHERNET_FRAME_LENGTH + IP_HEADER_LENGTH + UDP_HEADER_LENGTH; break; case PROTOCOL_ICMP: uRealDataSize = TotalPacketLength - ETHERNET_FRAME_LENGTH - IP_HEADER_LENGTH - ICMP_HEADER_LENGTH; //DBGPRINT((" <====== [ICMP] uRealDataSize : %d\n" , uRealDataSize )); nHeaderLen = ETHERNET_FRAME_LENGTH + IP_HEADER_LENGTH + ICMP_HEADER_LENGTH; break; default: break; } if ( uRealDataSize > 0 ) { if( pIpHeader->SourceIp == g_uSrcIp ) { DbgPrint("===============》收到数据包了\n"); PrintBufData( pPacketContent , NTOHS(pIpHeader->DatagramLength)); for ( nIndex = 0 ; nIndex < uRealDataSize ; nIndex++ ) { char* pBuf = &pPacketContent[nHeaderLen+nIndex]; *pBuf ^= XOR_SEED; } DBGPRINT(("FakePacket -- after xor Data : \n")); //PrintPacket( pPacket ); PrintBufData( pPacketContent , NTOHS(pIpHeader->DatagramLength)); } } } } while (0); if( pPacketContent != NULL ) NdisFreeMemory(pPacketContent, 0, 0); if( pCustomPacketContent != NULL ) NdisFreeMemory(pCustomPacketContent, 0, 0); return nRet; } NDIS_STATUS CD_SendPacket ( PADAPT pAdapt, PVOID pBuffer, ULONG dwBufferLength ) { NDIS_STATUS nRet = NDIS_STATUS_FAILURE; PNDIS_PACKET ndisPacket = NULL; PNDIS_BUFFER ndisBuffer = NULL; PUCHAR sendBuffer = NULL; PSEND_RSVD sendRsvd = NULL; NDIS_PHYSICAL_ADDRESS highestAcceptableAddress; highestAcceptableAddress.QuadPart = -1; do { if(pBuffer == NULL) break; if(dwBufferLength < ETH_MIN_PACKET_SIZE || dwBufferLength > ETH_MAX_PACKET_SIZE) break; nRet = NdisAllocateMemory(&sendBuffer, dwBufferLength, 0, highestAcceptableAddress); //status = NdisAllocateMemoryWithTag (&sendBuffer, dwBufferLength, TAG); if (nRet != NDIS_STATUS_SUCCESS) break; RtlZeroMemory(sendBuffer, dwBufferLength); RtlMoveMemory(sendBuffer, pBuffer, dwBufferLength); NdisAllocatePacket(&nRet, &ndisPacket, pAdapt->SendPacketPoolHandle); if (nRet != NDIS_STATUS_SUCCESS) { NdisFreeMemory(sendBuffer, dwBufferLength, 0); break; } NdisAllocateBuffer(&nRet, &ndisBuffer, pAdapt->SendPacketPoolHandle, sendBuffer, dwBufferLength); DBGPRINT(("SendRawData -> Allocate return: 0x%x, %d\n", sendBuffer, dwBufferLength)); if (nRet != NDIS_STATUS_SUCCESS) { NdisFreeMemory(sendBuffer, dwBufferLength, 0); NdisFreePacket(ndisPacket); break; } NdisChainBufferAtFront(ndisPacket, ndisBuffer); sendRsvd = (PSEND_RSVD)(ndisPacket->ProtocolReserved); sendRsvd->OriginalPkt = (PNDIS_PACKET)1; //标记自己 ndisPacket->Private.Head->Next = NULL; ndisPacket->Private.Tail = NULL; NdisSetPacketFlags(ndisPacket, NDIS_FLAGS_DONT_LOOPBACK); DBGPRINT(("SendRawData -> Now send!\n")); NdisSend(&nRet, pAdapt->BindingHandle, ndisPacket); if (nRet != STATUS_PENDING) { NdisUnchainBufferAtFront(ndisPacket, &ndisBuffer); NdisQueryBufferSafe(ndisBuffer, &sendBuffer, &dwBufferLength, NormalPagePriority); NdisFreeBuffer(ndisBuffer); NdisFreeMemory(sendBuffer, dwBufferLength, 0); NdisFreePacket(ndisPacket); DBGPRINT(("SendRawData -> Released!\n")); } } while (0); return nRet; } |
|
沙发#
发布于:2013-06-05 15:07
给俺点提示呀
|
|
板凳#
发布于:2013-06-07 13:29
1 改了IP的大小,还要改TCP UDP包的大小的段。加上校验,(你的ModifyPacketWndSize不知道改了没有)
2 最好别用虚拟机进行2台机器测试,我遇见过数据未变的情况。 3 你先把UDP搞定再说吧,TCP这样改肯定不行 。序列号维护问题。自己看一下TCP协议 最好自己windbg跟一下 |
|
|
地板#
发布于:2013-06-08 10:04
NDIS_STATUS ModifyPacketWndSize( UCHAR Protocol, PVOID pPacketContent,INT iPacketSize)
{ //定义数据包tcp/ip结构指针 int nLeavingLen; PETHERNET_FRAME pEtherHdr=NULL; PIP_HEADER pIpHdr=NULL; PTCP_HEADER pTcpHdr=NULL; PUDP_HEADER pUdpHdr=NULL; CHAR *pData=NULL; NDIS_STATUS nRet = NDIS_STATUS_FAILURE; do { if (pPacketContent==NULL) break; if( ( Protocol == PROTOCOL_TCP ) || ( Protocol == PROTOCOL_UDP ) ) { //获得以太帧头,过滤协议,过滤ip协议,放行其他协议 nLeavingLen=iPacketSize; if(nLeavingLen < sizeof(EHTERNET_FRAME)) break; nLeavingLen -= sizeof(EHTERNET_FRAME); pEtherHdr = (PETHERNET_FRAME)pPacketContent; if(NTOHS(pEtherHdr->FrameType)!=ETHERTYPE_IP) // 如果不是IP协议,则不处理 break; //获得ip头 pIpHdr = (PIP_HEADER)(pEtherHdr + 1); // 验证剩余数据长度,防止发生内核非法访问 if(nLeavingLen < sizeof(IP_HEADER)) break; nLeavingLen -= sizeof(IP_HEADER); // 检查版本信息,我们仅处理IPv4 if(((pIpHdr->VersionAndHeaderLength >> 4) & 0x0f) == 6) { break; } // 如果是TCP封包,修改窗口大小 if(pIpHdr->Protocol == PROTOCOL_TCP) { //TCP伪数据包头指针 PSDHEADER *pPsdHeader=NULL; //数据包校验缓存大小 INT iTcpCheckoutBufSize; NDIS_PHYSICAL_ADDRESS phyaddr = {-1}; NDIS_STATUS Status; //修改窗口大小 pTcpHdr = (PTCP_HEADER)(pIpHdr + 1); pTcpHdr->Window=200; KdPrint(("改变窗口大小!\n")); //pTcpHdr->flags=0; //Tcp数据校验 iTcpCheckoutBufSize=sizeof(PSDHEADER)+nLeavingLen; Status=NdisAllocateMemory(&pPsdHeader,iTcpCheckoutBufSize,0,phyaddr); if (Status==NDIS_STATUS_SUCCESS) { NdisZeroMemory(pPsdHeader,iTcpCheckoutBufSize); //填充伪TCP头 pPsdHeader->daddr=pIpHdr->SourceIp; pPsdHeader->saddr=pIpHdr->DestinationIp; pPsdHeader->mbz=0; pPsdHeader->ptcl=PROTOCOL_TCP; pPsdHeader->tcpl=htons(nLeavingLen); ////计算TCP校验和 pTcpHdr->CheckSum=0; NdisMoveMemory((PCHAR)pPsdHeader+sizeof(PSDHEADER),pTcpHdr,nLeavingLen); pTcpHdr->CheckSum=checksum((PUSHORT)pPsdHeader,iTcpCheckoutBufSize); NdisFreeMemory(pPsdHeader,iTcpCheckoutBufSize,0); nRet = NDIS_STATUS_SUCCESS; } } else if ( pIpHdr->Protocol == PROTOCOL_UDP ) { //UDP伪数据包头指针 PSDHEADER *pPsdHeader=NULL; //数据包校验缓存大小 INT iUdpCheckoutBufSize; NDIS_PHYSICAL_ADDRESS phyaddr = {-1}; NDIS_STATUS Status; pUdpHdr = (PUDP_HEADER)(pIpHdr + 1); iUdpCheckoutBufSize=sizeof(PSDHEADER)+nLeavingLen; Status=NdisAllocateMemory(&pPsdHeader,iUdpCheckoutBufSize,0,phyaddr); if (Status==NDIS_STATUS_SUCCESS) { NdisZeroMemory(pPsdHeader,iUdpCheckoutBufSize); //填充伪UDP头 pPsdHeader->daddr=pIpHdr->SourceIp; pPsdHeader->saddr=pIpHdr->DestinationIp; pPsdHeader->mbz=0; pPsdHeader->ptcl=PROTOCOL_UDP; pPsdHeader->tcpl=htons(nLeavingLen); ////计算UDP校验和 pUdpHdr->CheckSum=0; NdisMoveMemory((PCHAR)pPsdHeader+sizeof(PSDHEADER),pUdpHdr,nLeavingLen); pUdpHdr->CheckSum=checksum((PUSHORT)pPsdHeader,iUdpCheckoutBufSize); NdisFreeMemory(pPsdHeader,iUdpCheckoutBufSize,0); nRet = NDIS_STATUS_SUCCESS; } } } } while (0); return nRet; } |
|
地下室#
发布于:2013-06-13 10:25
有做过的人吗,提示一下吧
|
|