阅读:4402回复:29
问一个关于数据包分析、加密的处理问题。
对于防火墙或其他的VPN来说,如果不是在TDI层以上拦截的话,不管是Ndis Wrapper还是Passthru,通常拦截的到的都是用NDIS_PACKET结构来描述的数据包。而NDIS_PACKET是由一系列的NDIS_BUFFER串到一起形成的,每个NDIS_BUFFER是一个MDL(NT以上是这样的,95/98又有所不同了),那么我要问问做过防火墙的兄弟,对于一个IP包NDIS_PACKET,包含NDIS_BUFFER分别有A,B,C,D,去取IP地址的时候,一般是定义一个IP头的结构IpHead,然后定义一个指针IpHead pIpHdr,最后将pIpHdr指向IP头所在的内存,问题是那个内存不一定是连续的,可能IP头的前面部分在B,后面部分在C,那么pIpHdr后面的部分不是就无效了吗?
[编辑 - 11/27/02 by fracker] |
|
最新喜欢:myelan |
沙发#
发布于:2002-11-27 17:57
又,如果是要对整个包加密的话,应该不会说A,B,C,D四个NDIS_BUFFER分别加密,而A,B,C,D的地址又不连续,难道要先把他们拷贝到一个线性的缓冲区里面,然后才加密,加密完成以后再拷贝回去吗?
|
|
板凳#
发布于:2002-11-27 22:42
嘿嘿。。。
关注。 :D |
|
|
地板#
发布于:2002-11-27 23:26
我这两天正在跟这个问题,碰到了有的包是有几个buffer,如果是加密的化就是要构造新packet了,所以可以先copy到一个buffer中,然后加密,chain到一个新的packet中,发送的是新包,
|
|
|
地下室#
发布于:2002-11-27 23:37
对于一个IP包NDIS_PACKET,包含NDIS_BUFFER分别有A,B,C,D,去取IP地址的时候,一般是定义一个IP头的结构IpHead,然后定义一个指针IpHead pIpHdr,最后将pIpHdr指向IP头所在的内存,问题是那个内存不一定是连续的,可能IP头的前面部分在B,后面部分在C,那么pIpHdr后面的部分不是就无效了吗? 我觉得有两种方法: (1)做个函数读包数据,你只要给定偏移量,剩下的它来做,具体可以参考: http://www.pcausa.com/resources/readonpacket.htm (2)构造一个新包,将所有不连续的数据复制进去,这样就变连续了,具体可以参考 PCASUA 的 PIM 代码。 包描述符、缓冲区描述符等的关系可以参考: http://www.pcausa.com/resources/ndispacket.htm 呵呵,我是菜鸟,现学现卖 |
|
5楼#
发布于:2002-11-28 11:04
[quote
我觉得有两种方法: (1)做个函数读包数据,你只要给定偏移量,剩下的它来做,具体可以参考: http://www.pcausa.com/resources/readonpacket.htm (2)构造一个新包,将所有不连续的数据复制进去,这样就变连续了,具体可以参考 PCASUA 的 PIM 代码。 包描述符、缓冲区描述符等的关系可以参考: http://www.pcausa.com/resources/ndispacket.htm 呵呵,我是菜鸟,现学现卖 [/quote] 说到底,还是要Copy出来。 |
|
6楼#
发布于:2002-11-28 11:25
我没有做过防火墙,不过如果只是根据MAC头和IP头来判断的话可以去读,跟据长度去读buffer中的数据
|
|
|
7楼#
发布于:2002-11-28 14:14
如果有多个buffer的话,似乎都是第一个buffer是mac头,第二个是IP头,第三个是上层协议的头,然后是载荷,ping包是这样组织的,
|
|
|
8楼#
发布于:2002-11-28 14:17
????
|
|
|
9楼#
发布于:2002-11-28 14:21
如果有多个buffer的话,似乎都是第一个buffer是mac头,第二个是IP头,第三个是上层协议的头,然后是载荷 原来如此,我只知道一般情况下第一个 Buffer 是 MAC 头,有收获 |
|
10楼#
发布于:2002-11-28 14:23
如果有多个buffer的话,似乎都是第一个buffer是mac头,第二个是IP头,第三个是上层协议的头,然后是载荷,ping包是这样组织的, 呵呵,我就碰到过只有两个buffer的icmp包,第一个是mac,第二个就是带有playload的icmp/ip! |
|
11楼#
发布于:2002-11-28 14:39
我现在跟的都是4个buffer,不过都是ping的包
|
|
|
12楼#
发布于:2002-11-28 23:03
用户被禁言,该主题自动屏蔽! |
|
13楼#
发布于:2002-11-28 23:17
哈哈,mikeluo,你也换头像了
好啊,贴出来啊 |
|
14楼#
发布于:2002-11-29 11:15
都没有说到有意义的东西,其实我的想法是,是否存在这种可能,通过一些函数调用,使本来不连续的各段内存映射到同一个地址开始,从而变成连续的?我认为研究一下Windows的内存管理,也许可以实现呢?
|
|
15楼#
发布于:2002-11-29 14:43
都没有说到有意义的东西,其实我的想法是,是否存在这种可能,通过一些函数调用,使本来不连续的各段内存映射到同一个地址开始,从而变成连续的?我认为研究一下Windows的内存管理,也许可以实现呢? 这种情况必须把mdl那个内存链分别取出来放到一个大buf里面, 然后才能进行加密,例如调用 do_3des(buf,buflen); 这两个函数随便你用哪个。 ////////////////////////////////////////////////////////////////////////////// // 描述: // 把一个NDIS_PACKET结构中包含的数据拷贝到一个预先分配的缓冲区中,该 // 缓冲区必须足够大,否则会导致非法内存访问。调用者如果不能肯定包长度 // 可以调用NdisQueryPacket(Packet,NULL,NULL,&PacketSize)得到。或者分配 // 一个超过最大长度的内存。 // write by huyg // 参数: // Packet: // pPacketContent: // pPacketSize: /////////////////////////////////////////////////////////////////////////////// UINT CopyPacket2Buf( IN PNDIS_PACKET Packet, OUT PUCHAR pPacketContent, OUT UINT* pPacketSize) { UINT bufLength; MDL* pNext; UINT i; PUCHAR pbuf; NdisQueryPacket(Packet,NULL,NULL,NULL,pPacketSize); NdisQueryBufferSafe(Packet->Private.Head,&pbuf,&bufLength, 32 ); NdisMoveMemory(pPacketContent,pbuf,bufLength); i=bufLength; pNext=Packet->Private.Head; // next 是一个mdl for(;;) { // if(pNext==Packet->Private.Tail) // break; pNext=pNext->Next; // next 是一个mdl if (pNext==NULL) break; NdisQueryBufferSafe(pNext,&pbuf,&bufLength,32); NdisMoveMemory(pPacketContent+i,pbuf,bufLength); i+=bufLength; } ASSERT(*pPacketSize == i); return *pPacketSize; } ///////////////////////////////////// // just like CopyPacket2Buf,write by yq ///////////////////////////////////// UINT CopyPacketToBuffer( IN OUT PUCHAR Buf, // destination IN PNDIS_PACKET Packet, // source packet IN UINT Offset, // offset in packet IN UINT Length // number of bytes to copy ) /*++ Routine Description: Copies bytes from a packet into a buffer. Used to copy data out of a packet during loopback indications. Arguments: Buf - the destination buffer Packet - the source packet Offset - the offset in the packet to start copying at Length - the number of bytes to copy Return Value: The actual number of bytes copied; will be less than Length if the packet length is less than Offset+Length. --*/ { PNDIS_BUFFER CurBuffer; UINT BytesCopied; PUCHAR BufVA; UINT BufLen; UINT ToCopy; UINT CurOffset; BytesCopied = 0; // // First find a spot Offset bytes into the packet. // CurOffset = 0; NdisQueryPacket(Packet, NULL, NULL, &CurBuffer, NULL); while (CurBuffer != (PNDIS_BUFFER)NULL) { NdisQueryBuffer(CurBuffer, (PVOID *)&BufVA, &BufLen); if (CurOffset + BufLen > Offset) { break; } CurOffset += BufLen; NdisGetNextBuffer(CurBuffer, &CurBuffer); } // // See if the end of the packet has already been passed. // if (CurBuffer == (PNDIS_BUFFER)NULL) { return 0; } // // Now copy over Length bytes. // BufVA += (Offset - CurOffset); BufLen -= (Offset - CurOffset); for (;;) { ToCopy = (BytesCopied+BufLen > Length) ? Length - BytesCopied : BufLen; NdisMoveMemory(Buf+BytesCopied, BufVA, ToCopy); BytesCopied += ToCopy; if (BytesCopied == Length) { return BytesCopied; } NdisGetNextBuffer(CurBuffer, &CurBuffer); if (CurBuffer == (PNDIS_BUFFER)NULL) { break; } NdisQueryBuffer(CurBuffer, (PVOID *)&BufVA, &BufLen); } return BytesCopied; } |
|
|
16楼#
发布于:2002-11-29 14:46
ps:如果要在9x下使用,把QueryBufferSafe改为QueryBuffer。
在2k下也可以使用QueryBuffer。 [quote]都没有说到有意义的东西,其实我的想法是,是否存在这种可能,通过一些函数调用,使本来不连续的各段内存映射到同一个地址开始,从而变成连续的?我认为研究一下Windows的内存管理,也许可以实现呢? 这种情况必须把mdl那个内存链分别取出来放到一个大buf里面, 然后才能进行加密,例如调用 do_3des(buf,buflen); 这两个函数随便你用哪个。 ////////////////////////////////////////////////////////////////////////////// // 描述: // 把一个NDIS_PACKET结构中包含的数据拷贝到一个预先分配的缓冲区中,该 // 缓冲区必须足够大,否则会导致非法内存访问。调用者如果不能肯定包长度 // 可以调用NdisQueryPacket(Packet,NULL,NULL,&PacketSize)得到。或者分配 // 一个超过最大长度的内存。 // write by huyg // 参数: // Packet: // pPacketContent: // pPacketSize: /////////////////////////////////////////////////////////////////////////////// UINT CopyPacket2Buf( IN PNDIS_PACKET Packet, OUT PUCHAR pPacketContent, OUT UINT* pPacketSize) { UINT bufLength; MDL* pNext; UINT i; PUCHAR pbuf; NdisQueryPacket(Packet,NULL,NULL,NULL,pPacketSize); NdisQueryBufferSafe(Packet->Private.Head,&pbuf,&bufLength, 32 ); NdisMoveMemory(pPacketContent,pbuf,bufLength); i=bufLength; pNext=Packet->Private.Head; // next 是一个mdl for(;;) { // if(pNext==Packet->Private.Tail) // break; pNext=pNext->Next; // next 是一个mdl if (pNext==NULL) break; NdisQueryBufferSafe(pNext,&pbuf,&bufLength,32); NdisMoveMemory(pPacketContent+i,pbuf,bufLength); i+=bufLength; } ASSERT(*pPacketSize == i); return *pPacketSize; } ///////////////////////////////////// // just like CopyPacket2Buf,write by yq ///////////////////////////////////// UINT CopyPacketToBuffer( IN OUT PUCHAR Buf, // destination IN PNDIS_PACKET Packet, // source packet IN UINT Offset, // offset in packet IN UINT Length // number of bytes to copy ) /*++ Routine Description: Copies bytes from a packet into a buffer. Used to copy data out of a packet during loopback indications. Arguments: Buf - the destination buffer Packet - the source packet Offset - the offset in the packet to start copying at Length - the number of bytes to copy Return Value: The actual number of bytes copied; will be less than Length if the packet length is less than Offset+Length. --*/ { PNDIS_BUFFER CurBuffer; UINT BytesCopied; PUCHAR BufVA; UINT BufLen; UINT ToCopy; UINT CurOffset; BytesCopied = 0; // // First find a spot Offset bytes into the packet. // CurOffset = 0; NdisQueryPacket(Packet, NULL, NULL, &CurBuffer, NULL); while (CurBuffer != (PNDIS_BUFFER)NULL) { NdisQueryBuffer(CurBuffer, (PVOID *)&BufVA, &BufLen); if (CurOffset + BufLen > Offset) { break; } CurOffset += BufLen; NdisGetNextBuffer(CurBuffer, &CurBuffer); } // // See if the end of the packet has already been passed. // if (CurBuffer == (PNDIS_BUFFER)NULL) { return 0; } // // Now copy over Length bytes. // BufVA += (Offset - CurOffset); BufLen -= (Offset - CurOffset); for (;;) { ToCopy = (BytesCopied+BufLen > Length) ? Length - BytesCopied : BufLen; NdisMoveMemory(Buf+BytesCopied, BufVA, ToCopy); BytesCopied += ToCopy; if (BytesCopied == Length) { return BytesCopied; } NdisGetNextBuffer(CurBuffer, &CurBuffer); if (CurBuffer == (PNDIS_BUFFER)NULL) { break; } NdisQueryBuffer(CurBuffer, (PVOID *)&BufVA, &BufLen); } return BytesCopied; } [/quote] |
|
|
17楼#
发布于:2002-11-29 15:26
胡大侠都说了只能Copy出来,那看来是没什么办法了。话题结束,结账。
|
|
18楼#
发布于:2002-11-29 15:36
俺想了半天,没有发现什么蛛丝马迹可以解决fracker的想法,:(
既然胡版主已经发话了,俺就先不想了,免的浪费脑细胞, 改别人的程序真痛苦吖,尤其是这个程序还很大的时候, |
|
|
19楼#
发布于:2002-11-29 15:40
呵呵,想出来对你们有好处阿,对我是没有什么用处的,我的工作这些东西是用不上的。
|
|
上一页
下一页