|
![]() | 作者: cdeee [cdeee]
![]() |
登录 |
如果有一个本地程序正在网络上进行通讯,现在我想把这些正在传递的数据(包括发送的和接收的)先拦截,进行处理后在送出去(发送到网络或者发送到程序),请问应该怎么办,要用到那些函数。 [此贴被 cdeee(cdeee) 在 04月02日15时13分 编辑过] |
地主 发表时间: 04-03-29 16:14 |
![]() | 回复: 286 [unique] ![]() |
登录 |
raw socket |
B1层 发表时间: 04-03-29 17:54 |
![]() | 回复: ghame [ghame] ![]() |
登录 |
IOCTL |
B2层 发表时间: 04-03-29 18:46 |
![]() | 回复: TomyChen [quest] ![]() |
登录 |
用winpcap吧。。。可以省很多事,raw_socket也不错,但就复杂一些:) |
B3层 发表时间: 04-03-29 21:12 |
![]() | 回复: yingzike [yingzike] ![]() |
登录 |
我最近也正想这方面的资料,那位老大贴源代码一下?![]() ![]() ![]() ![]() ![]() |
B4层 发表时间: 04-03-30 14:01 |
![]() | 回复: cdeee [cdeee] ![]() |
登录 |
我找到一个使用RAW SOCKET嗅探的范例,可以接收到所有数据包,但有点不明白,不知道这些包是被拦截了呢还是依然会发送到目的地,当然,如果已经被拦截了,那就好办,只要将收到的包在发一次就可以了,但如果依然发送到目的地,不知道有什么方法可以拦截。 |
B5层 发表时间: 04-04-01 01:38 |
![]() | 回复: TomyChen [quest] ![]() |
登录 |
只是复制一份,拦截的话那就是FW了 |
B6层 发表时间: 04-04-01 08:21 |
![]() | 回复: 286 [unique] ![]() |
登录 |
RAW socket有以下几点不足: 1 只能在windows 2000/xp/2003上使用,不能在windows 95/98/97/me上使用。 2 对于本机对本机的操作大部分无法得到。比如http://localhost/。 3 数据量大时,有丢包现象。比如看流媒体,一般就没效果。 但总得来说,比没有强。 ![]() |
B7层 发表时间: 04-04-01 09:23 |
![]() | 回复: cdeee [cdeee] ![]() |
登录 |
前面的TomyChen朋友,你所说的我有些不清楚(什么是FW啊,看不懂),能说清楚些吗?还有,在拦截了数据进行分析后,我还要将原来的数据发送出去,可我新发送的数据也会被拦截啊,请问有什么办法解决? 另外,我在网络上找到的范例存在一些不足,大家帮我看一看吧。 我找到的范例在这个位置: http://www.sron.net/art/article.php?articleid=941 这个范例采用死循环以便接收较多的数据,虽然程序中用Application->ProcessMessages();避免程序程序独占系统资源,但这种方式存在致命弱点: 1、占用资源太多,影响本机效率; 2、虽然采用死循环,但未必就能接收所有数据; 3、一经启动便无法结束。从表面看来,该程序在第二次按下按钮即可结束,但对VCL有过研究的人就会发现,Application->ProcessMessages();可以使Windows处理其他消息,但本程序的循环却不会结束,而本程序不结束,则VCL不会在当前消息未处理完的时候处理其他消息(因为程序只有一个线程,也就是主线程,而VCL的消息处理程序正是在主线程中),即第二次按键消息始终无法处理,也就构成了死循环。 4、就纯粹的编程风格来说,对于Windows这种基于消息的系统,使用循环处理事情本身就是一种不明智的选择。 现在我的想法是,采用Windows的消息机制,使用事件处理的方法来接收数据,也就是说,在有数据到达的时候工作,在没数据时则空闲,我使用WSAAsyncSelect函数为窗口设置网络通知消息(自定义的消息),但运行的时候却不对,请问是我使用的函数不对呢还是有其他要求。 本来准备用MFC提供的CSocket类了(MSDN中有范例嘛),可看了MSDN,才发现MFC不支持WinSock2,呜呜,看来只有用API了。 |
B8层 发表时间: 04-04-01 16:53 |
![]() | 回复: 286 [unique] ![]() |
登录 |
你的问题我来回答吧,回答的不对,陈汤米再补充。 FW应该是转发吧?forward。 实际上你这里不叫拦截,而叫嗅探,就象A,B在说话你在偷听一样,并不影响你可以听到双方说的话,AB也能互相听到对方的话。 另外,在嗅探时有阻塞型和非阻塞型,后者不存在你说的问题。前者在死循环中加入消息处理后也应该不存在你说的问题,但如果主线程处理的话可能效果不会太好。 MFC支持win sock2,在向导中不要选择MFC提供的socket支持,而是自己手工地把静态库导入。 即使是使用winsock2,也是很多地方使用API。 |
B9层 发表时间: 04-04-01 17:47 |
![]() | 回复: xiean [xiean] ![]() |
登录 |
再补充一下 陈汤米 ![]() ![]() ![]() ![]() ![]() 说的 fw 应该是 firewall,forward 很少有人缩写成 fw 的,另外,上下文中“不知道这些包是被拦截了呢还是依然会。。。。。” |
B10层 发表时间: 04-04-01 18:52 |
![]() | 回复: cdeee [cdeee] ![]() |
登录 |
286大哥,我说的是类似嗅探啊,再说,我要的是拦截原来的数据,分析数据后可能要更改内容的啊,我现在要发送的是改变后的内容而不让原来的内容送到程序中去,又怎么叫转发呢?因为被操作的程序就在本地计算机上,这样做也应该可以做得到吧,把自己计算机想外发送的数据修改一下再发送,或者把外部来的数据先分析修改一下再使用,这样也不会过分吧![]() |
B11层 发表时间: 04-04-01 19:04 |
![]() | 回复: yingzike [yingzike] ![]() |
登录 |
最近想找这方面的东东,关注中,顶上来![]() ![]() ![]() |
B12层 发表时间: 04-04-01 20:06 |
![]() | 回复: kailangq [kailangq] ![]() |
登录 |
![]() |
B13层 发表时间: 04-04-02 03:24 |
![]() | 回复: cdeee [cdeee] ![]() |
登录 |
我用VC写了个程序,可我在打开网页的时候程序无反应,现把程序(主要部分)贴上来,大家帮我看看错在那里。 // 消息定义 // 网络消息,接受网络事件 #define SOCKMESSAGE WM_USER + 1 // 消息映射,提供消息处理函数 BEGIN_MESSAGE_MAP(CMainForm, CDialog) ON_MESSAGE(SOCKMESSAGE, OnSocket) END_MESSAGE_MAP() // CMainForm为主程序界面,从CDialog继承 // 以下是主要数据成员: // CListCtrl m_List; // 回显数据的列表框 // SOCKET m_Socket; // Socket句柄 // SOCKADDR_IN m_Address; // 地址结构,在分析地址时使用 // CString m_HostName; // 主机名 // CString m_HostAddr; // 主机地址 // 以下是按钮ID // IDC_START // 启动按钮 // IDC_END // 结束按钮 // IDC_CLEAR // 清空列表框内容按钮 // 以下是主要函数成员 int CMainForm::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CDialog::OnCreate(lpCreateStruct) == -1) return -1; // TODO: 在此添加您专用的创建代码 // 启动 WinSock WSADATA vWSAData; if( WSAStartup(MAKEWORD(2,2), &vWSAData) != 0 ) return -1; this->m_Socket = WSASocket(AF_INET, SOCK_RAW, IPPROTO_RAW, NULL, 0, WSA_FLAG_OVERLAPPED); if( this->m_Socket == INVALID_SOCKET) return -1; BOOL flag = TRUE; if( setsockopt(this->m_Socket, IPPROTO_IP, IP_HDRINCL, (char *)&flag, sizeof(flag)) != 0 ) return -1; // 获取主机名 char hostname[512]; if( gethostname(hostname, sizeof(hostname)) != 0 ) return -1; this->m_HostName = hostname; // 获取主机地址 struct hostent * phost = gethostbyname(hostname); if( phost == NULL ) return -1; this->m_HostAddr = inet_ntoa(*(in_addr*)phost->h_addr_list[0]); this->m_Address.sin_addr = *(in_addr*)phost->h_addr_list[0]; this->m_Address.sin_family = AF_INET; this->m_Address.sin_port = htons(57274); // 绑定主机 if( bind(this->m_Socket, (sockaddr*)&this->m_Address, sizeof(this->m_Address)) != 0 ) return -1; return 0; } void CMainForm::OnDestroy() { CDialog::OnDestroy(); // TODO: 在此添加消息处理程序代码 closesocket(this->m_Socket); WSACleanup(); } // 启动 void CMainForm::OnBnClickedStart() { // 接受所有数据包 DWORD f = 1; if( ioctlsocket(this->m_Socket, SIO_RCVALL, &f) != 0) MessageBox("设置接受所有包模式失败"); if( WSAAsyncSelect(this->m_Socket, this->m_hWnd, SOCKMESSAGE,FD_READ) != 0 )// | FD_WRITE | FD_ACCEPT | FD_ADDRESS_LIST_CHANGE | FD_GROUP_QOS | FD_OOB | FD_QOS MessageBox("WSAAsyncSelect调用失败"); this->GetDlgItem(IDC_START)->EnableWindow(FALSE); this->GetDlgItem(IDC_END)->EnableWindow(); } // 结束 void CMainForm::OnBnClickedEnd() { if( WSAAsyncSelect(this->m_Socket, this->m_hWnd, 0, 0 ) != 0 ) MessageBox("WSAAsyncSelect调用失败"); DWORD f = 0; if( ioctlsocket(this->m_Socket, SIO_RCVALL, &f) ) MessageBox("取消接受所有包模式失败"); this->m_List.DeleteAllItems(); this->GetDlgItem(IDC_START)->EnableWindow(); this->GetDlgItem(IDC_END)->EnableWindow(FALSE); } // 响应网络事件,因为是示范程序,这里只为发现有无网络事件发生,是以较简单 LRESULT CMainForm::OnSocket(WPARAM w, LPARAM l) { CString s; switch(LOWORD(l)) { case FD_READ: s = "read"; break; case FD_WRITE: s = "write"; break; case FD_ACCEPT: s = "accept"; break; case FD_ADDRESS_LIST_CHANGE: s = "address list change"; break; case FD_GROUP_QOS: s = "group qos"; break; case FD_OOB: s = "oob"; break; case FD_QOS: s = "qos"; break; default: break; } this->m_List.InsertItem(7, s); return 0; } [此贴被 cdeee(cdeee) 在 04月02日20时35分 编辑过] |
B14层 发表时间: 04-04-02 15:50 |
![]() | 回复: cdeee [cdeee] ![]() |
登录 |
怎么没人来啦,286大哥,TomyChen大哥,说句话啊![]() |
B15层 发表时间: 04-04-03 13:00 |
![]() | 回复: TomyChen [quest] ![]() |
登录 |
上面的代码我没细看,但大概看了个思路。 先把我早先的答案再完整点: sniffer只是对发出去的包做一个copy,而原包还是会正常到达。FW如xiean说的,是Firewall的意思。如果是包拦截那就是属于Firewall型的东西了。 另外我的一个建议是学习的时候,尽量不要去用MFC封装过的socket类,因为那样会让你失去学习socket的很多机会,比如上文你用到的异步类。自己尝试一下。而且最好是多线程...。 另外你可以到vckbase去看一下有这方面的源代码http://www.vckbase.com。 你还可以下载一份winpcap SDK来看看,把整体思路理清,再动手写...^_^ |
B16层 发表时间: 04-04-04 11:54 |
![]() | 回复: TomyChen [quest] ![]() |
登录 |
最近太忙了,不然就给你写一个例子![]() |
B17层 发表时间: 04-04-04 11:55 |
![]() | 回复: 286 [unique] ![]() |
登录 |
是我理解错了,FW就是防火墙了。 接收部分请参阅recvfrom函数。 放弃CSocket类。 |
B18层 发表时间: 04-04-05 17:14 |
![]() | 回复: sinister [sinister] ![]() |
登录 |
你应该自己 DECODE IP HEADER 分解出上层协议, TCP/UDP,然后再分解出 PORT, 再进一步 的就是 PACKET 内容了。 如果你想把协议详细解析,这里调用 WSAAsyncSelect 本就是错误的。 还有如果不发送 PACKET 的话, IP_HDRINCL 没有必要设置。 再有上面已经提到过了,这种方法你拿到的只是 PACKET 的一份 COPY。要想拦截要用其他方法, 如果想在 APP 层实现拦截,参考一下 SPI。 关于拦截 PACKET 和 FW 去看下面这个帖子,里面 我有一些论述。 http://www.20cn.net/cgi-bin/club/show.pl?key=sJGbrnlrwfcU&cat=org&forum=develop&page=1&position=3&id=1074267914 |
B19层 发表时间: 04-04-05 20:01 |
![]() | 回复: cdeee [cdeee] ![]() |
登录 |
粗略看了一下sinister大哥的论述,挺不错的,晚上再来仔细看看。 对了,你说我使用WSAAsyncSelect不对,那请问该用什么实现对所有包的查询啊?是专门建立一个线程来接收吗?这样做会不会漏过部分数据包呢 ![]() |
B20层 发表时间: 04-04-06 12:05 |
![]() | 回复: TomyChen [quest] ![]() |
登录 |
常用的方法就是做一个线程来接收,可以用work thread也可以用UI Thread具体得看你的线程参数,如果参数比较少,容易处理,用work就够了,如果参数比较多的话那就用 UI线程吧。 至于丢包的问题,我想不明白...为什么会丢包呢? |
B21层 发表时间: 04-04-06 13:12 |
![]() | 回复: cdeee [cdeee] ![]() |
登录 |
这么多人回帖子,还是只有sinister的最有用,谢谢了哟。![]() 现在我终于找到办法啦,原来要实现这样的功能竟然有如此多的办法,但归纳起来都是一个原理,那就是“钩子”,不论是用SPI还是拦截驱动,基本都是这样,不过话说回来,也只有这样才能保证所有包都被处理而不致产生漏网之鱼,怎么我早先没想到呢,郁闷。 ![]() |
B22层 发表时间: 04-04-06 22:12 |
|
20CN网络安全小组版权所有
Copyright © 2000-2010 20CN Security Group. All Rights Reserved.
论坛程序编写:NetDemon
粤ICP备05087286号