论坛: 编程破解 标题: 求助(关于网络编程,数据拦截) 复制本贴地址    
作者: 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大哥,我说的是类似嗅探啊,再说,我要的是拦截原来的数据,分析数据后可能要更改内容的啊,我现在要发送的是改变后的内容而不让原来的内容送到程序中去,又怎么叫转发呢?因为被操作的程序就在本地计算机上,这样做也应该可以做得到吧,把自己计算机想外发送的数据修改一下再发送,或者把外部来的数据先分析修改一下再使用,这样也不会过分吧,还有,各位大哥不要只说理论,给点实际内容啊,比如要使用那些函数(WinSock2 API)?有些什么注意的地方,大家说详细点啊。

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号