阅读:3154回复:23
关于修改packet数据上传到协议栈被丢掉的问题,急(可以加分)
具体如下:
我在miniport(虚拟的)中的miniportsend例程中把收到的packet数据取到自己的缓冲区,然后修改目的和源MAC,ip地址信息,端口,校验和等信息,再回传到上层协议,用sniffer可以抓到发送和接收到的包,察看数据也没发现有啥情况,但应用程序增收不到包(应用程序没问题)。 再详细点,具体方案如下:我实现的是虚拟网卡,就是没有硬件的,现在再测试收发功能,本来收发要靠irp请求的。 安装两个网卡(为同样的虚拟网卡),设置通网段ip地址,简称a和b.现在通过a发udp包到一个不存在的c地址(之前做好arp欺骗,这样做是因为直接发到b会通过协议栈就转发了不经过miniport),然后在miniportsend中包packet中数据取出为(MAC头+IP头+UDP头+data)然后修改其相应地址信息,改为 c 到 b 的包,组建packet,上传到NDIS,sniffer能得到包,但应用程序的不到 请问,我这样实现测试其send和receive例程可行吗?可行的话,我哪里错了?不行的话,我该怎样测试阿!其各位多费心,帮帮忙,分少还可以在加? |
|
最新喜欢:lierli...
|
沙发#
发布于:2004-04-22 08:40
怎么没人回答啊!帮帮我吧
其实就是ARP包收发正常,而udp数据包再修改了mac头和ip头后应用层就收不到了,不知道是ip还udp协议给扔掉了,有没有什么方法可以查是什么原因,怎么解决啊? 救救我吧!!!!!! |
|
|
板凳#
发布于:2004-04-22 09:07
WINDOWS系统对UDP是检查校验的,修改IP地址后,IP头和UDP的校验和都要重新计算,不知道你做了吗,如果没有,肯定被仍掉。
|
|
地板#
发布于:2004-04-22 09:15
WINDOWS系统对UDP是检查校验的,修改IP地址后,IP头和UDP的校验和都要重新计算,不知道你做了吗,如果没有,肯定被仍掉。 我计算更新校验和,ip校验和只计算ip头部字节(一般是20字节吧),udp校验和为udp头加数据,对吧。 并且我只修改了MAC地址和ip地址,而mac头不需要校验,udp头和data我都没修改,所以之计算更新了ip校验和(我这里就是那20个字节),现把部分代码贴出: //校验和算法 unsigned short cal_chksum(unsigned short *addr,int len) { int nleft=len; int sum=0; unsigned short *w=addr; unsigned short answer=0; //把报头二进制数据以2字节为单位累加起来 while(nleft>1) { sum+=*w++; nleft-=2; } //若报头为奇数个字节,会剩下最后一字节。把最后一个字节视为一个2字节数据的高字节,这个2字节数据的低字节为0,继续累加* if( nleft==1) { *(unsigned char *)(&answer)=*(unsigned char *)w; sum+=answer; } sum=(sum>>16)+(sum&0xffff); sum+=(sum>>16); answer=~sum; return answer; } //计算IP包头的校验和 *((unsigned short *)(pChar + 24)) = 0; *((unsigned short *)(pChar + 24)) = cal_chksum((unsigned short *)(pChar + 14),20); 有什么问题吗? |
|
|
地下室#
发布于:2004-04-22 09:20
TCP和UDP的校验和都要加伪头,我看你没有的。
|
|
5楼#
发布于:2004-04-22 09:23
TCP和UDP的校验和都要加伪头,我看你没有的。 我没有修改udp头和数据啊! 还要重新校验吗?伪头是什么,怎么校验? 能否详细指教一下,或者网上那里有资料介绍 非常感谢asmsys! |
|
|
6楼#
发布于:2004-04-22 09:36
[quote]TCP和UDP的校验和都要加伪头,我看你没有的。 我没有修改udp头和数据啊! 还要重新校验吗?伪头是什么,怎么校验? 能否详细指教一下,或者网上那里有资料介绍 非常感谢asmsys! [/quote] udp,tcp包头进行校验和计算时,输入CheckSum的参数addr应该是udp(tcp)伪头部+udp(tcp)包头内容+数据,而且将其中 的checksum两个字节置0; 以下是伪头部的结构,tcp,udp是一样的 typedef struct pseudo_udp_hdr { ULONG pth_src; ULONG pth_dst; UCHAR pth_zero; UCHAR pth_protocol; USHORT pth_length; }pseudo_udp_hdr, * Ppseudo_udp_hdr; |
|
|
7楼#
发布于:2004-04-22 09:44
请问伪头部在mac包的那里啊! 我把包抓下来后只看到 MAC头(14) + ip头(20) + udp头(8) + data(n) 不清楚伪头在那里啊! 长度参数好说啊!加上sizeof(pseudo_udp_hdr)就行了吧 那地址怎样计算啊! |
|
|
8楼#
发布于:2004-04-22 09:49
伪头是虚的,你必须够找一个然后把他加进去,楼上说的那个结构就对,可以用。
|
|
9楼#
发布于:2004-04-22 09:52
void UdpCheckSum(PIP_HEADER buffer)
{ __ASM { pushad xor eax,eax xor edx,edx mov esi,buffer add esi,12 ;srcip mov ecx,4 lable1: lodsw add edx,eax loop lable1 add edx,1100h ;udp type mov [esi+6],cx ;clear old checksum to 0 mov cx,[esi+4] add edx,ecx ;udp length xchg cl,ch mov edi,esi mov ebx,ecx shr ecx,1 lable2: lodsw add edx,eax loop lable2 and ebx,1 jz lable3 xor eax,eax lodsb add edx,eax lable3: mov eax,edx shr eax,16 and edx,0ffffh add edx,eax mov eax,edx shr eax,16 add edx,eax not edx mov [edi+6],dx popad } } |
|
10楼#
发布于:2004-04-22 09:56
[quote] 请问伪头部在mac包的那里啊! 我把包抓下来后只看到 MAC头(14) + ip头(20) + udp头(8) + data(n) 不清楚伪头在那里啊! 长度参数好说啊!加上sizeof(pseudo_udp_hdr)就行了吧 那地址怎样计算啊! [/quote] 伪头部是要自己构造的!不在包里!构造好udp伪头部再加上udp包头内容再加上数据就可以用来计算udp的checksum了 |
|
|
11楼#
发布于:2004-04-22 09:57
void UdpCheckSum(PIP_HEADER buffer) 汇编啊!我的妈呀,忘完了,我直接调用就行吗? PIP_HEADER buffer 是否mac包中指向ip头的指针对吗? 谢了,两位 我试验一下先 :) |
|
|
12楼#
发布于:2004-04-22 09:58
USHORT checksum(USHORT *buffer, int size)
{ unsigned long cksum=0; while (size > 1) { cksum += *buffer++; size -= sizeof(USHORT); } if (size) { cksum += *(UCHAR*)buffer; } cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >>16); return (USHORT)(~cksum); } |
|
|
13楼#
发布于:2004-04-22 10:10
USHORT checksum(USHORT *buffer, int size) 我的算法也对吧?下面是我对伪头的理解(注释),你看对吗? typedef struct pseudo_udp_hdr { ULONG pth_src;//源ip地址 ULONG pth_dst;//目的ip地址 UCHAR pth_zero;//赋值为 0 UCHAR pth_protocol;//协议类型,这里为17 USHORT pth_length;//这儿不清楚了,***还得zxcasd 老大指教***! }pseudo_udp_hdr, * Ppseudo_udp_hdr; 那加上伪头是不又要开缓冲区把伪头和udp包复制到一起,在计算,那然后那?是把udp部分复制回去,还是只赋值校验和就好了? |
|
|
14楼#
发布于:2004-04-22 10:19
USHORT checksum(USHORT *buffer, int size) 你这没有处理伪头,我那代码是久经考验的,速度飞快,使用简单,只要把IP包的起使地址传进去就好了,你就只等着发送吧。 |
|
15楼#
发布于:2004-04-22 10:22
算了,发一个C版的吧,今天心情不好,发泄一下。
void UdpCheckSum(PIP_HEADER buffer) { //有可选数据时要做改动 //buffer是IP头的指针 unsigned short size; unsigned char * pSize; unsigned char tempchar; unsigned long cksum = 0; unsigned short * TempAddr; unsigned short * TempAddr1; int i = 0; //加伪首 TempAddr = (unsigned short *)(&(buffer->SrcIP)); for(i=0;i<4;i++) { cksum += *TempAddr; TempAddr++; } cksum += 0x1100; //类型 size = *(TempAddr + 2); //udp包长度 cksum += size; //转换网络字节 pSize = (unsigned char *)(&size); tempchar = pSize[0]; pSize[0] = pSize[1]; pSize[1] = tempchar; //校验和位置清0 *(TempAddr + 3) = 0; //size = udp size //buffer = udp packet addr TempAddr1 = TempAddr; while (size > 1) { cksum += *TempAddr++; size -= sizeof(unsigned short); } if (size) { cksum += *(unsigned char*)TempAddr; } cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >>16); *(TempAddr1 + 3) = (unsigned short)(~cksum); } |
|
16楼#
发布于:2004-04-22 10:22
[quote]USHORT checksum(USHORT *buffer, int size) 你这没有处理伪头,我那代码是久经考验的,速度飞快,使用简单,只要把IP包的起使地址传进去就好了,你就只等着发送吧。 [/quote] asmsys老大,你的汇编代码我编译不通过啊! 我是笨了点哈,这都搞不定了,还望你多加指教 2000ddk识别不了__ASM,pushad.xor等指令,要怎样设置啊! |
|
|
17楼#
发布于:2004-04-22 10:25
算了,发一个C版的吧,今天心情不好,发泄一下。 谢了!!!! :P |
|
|
18楼#
发布于:2004-04-22 10:26
[quote]USHORT checksum(USHORT *buffer, int size) 我的算法也对吧?下面是我对伪头的理解(注释),你看对吗? typedef struct pseudo_udp_hdr { ULONG pth_src;//源ip地址 ULONG pth_dst;//目的ip地址 UCHAR pth_zero;//赋值为 0 UCHAR pth_protocol;//协议类型,这里为17 USHORT pth_length;//这儿不清楚了,***还得zxcasd 老大指教***! }pseudo_udp_hdr, * Ppseudo_udp_hdr; 那加上伪头是不又要开缓冲区把伪头和udp包复制到一起,在计算,那然后那?是把udp部分复制回去,还是只赋值校验和就好了? [/quote] pth_length是包的总长度去掉以太网头长度和ip头长度,做法就差不多是那样了。感觉asmsys的代码很不错啊一次搞定 |
|
|
19楼#
发布于:2004-04-22 10:28
#define __ASM __asm
要不你就用C版的,一样,但我觉得太臃肿。 |
|
上一页
下一页