编程实现局域网监听工具

在网络中,数据是以帧的形式进行传输的。以TCP协议为例,当用户发送数据时,在传输层,用户数据的前端会附加TCP首部,TCP首部包括源端口号、目的端口号、位序号、确认序号等信息。在网络层会附加IP首部,IP首部包括数据报的源地址和目标地址等信息,详细信息请参考本例实现过程中的HeadIP结构。在链路层附加地址解析协议和逆向地址解析协议,用于转换IP层和网络接口层使用的地址。
为了获得网络中传输的数据,首先需要创建一个原始套接字,该套接字获得的数据是IP层的数据报。包含IP首部、TCP或UDP首部、用户数据等信息。然后对获得的数据报去除IP首部,根据IP首部获得数据报的源地址、目的地址、采用的协议及数据报的长度等信息。接着根据不同的协议去除TCP或UDP首部,根据TCP或UDP首部确定源端口和目的端口。最后数据报剩余的部分即是用户数据
在APP类中加:
#include "winsock2.h"
#pragma comment (lib,"ws2_32.lib")
#include "AFXSOCK.H"
 
BOOL CSniffAppApp::InitInstance()
{
      AfxEnableControlContainer();
 
      // Standard initialization
      // If you are not using these features and wish to reduce the size
      //  of your final executable, you should remove from the following
      //  the specific initialization routines you do not need.
 
#ifdef _AFXDLL
      Enable3dControls();              // Call this when using MFC in a shared DLL
#else
      Enable3dControlsStatic();      // Call this when linking to MFC statically
#endif
      //初始化套接字
      WSADATA data;
      AfxSocketInit(&data);
      //WSAStartup(2,&data);
 
      CSniffAppDlg dlg;
      m_pMainWnd = &dlg;
      int nResponse = dlg.DoModal();
      if (nResponse == IDOK)
      {
            // TODO: Place code here to handle when the dialog is
            //  dismissed with OK
      }
      else if (nResponse == IDCANCEL)
      {
            // TODO: Place code here to handle when the dialog is
            //  dismissed with Cancel
      }
 
 
      // Since the dialog has been closed, return FALSE so that we exit the
      //  application, rather than start the application's message pump.
      return FALSE;
}

// CSniffAppDlg dialog
#define SIO_RCVALL            _WSAIOW(IOC_VENDOR,1)
#define SIO_RCVALL_MCAST      _WSAIOW(IOC_VENDOR,2)
#define SIO_RCVALL_IGMPMCAST  _WSAIOW(IOC_VENDOR,3)
#define SIO_KEEPALIVE_VALS    _WSAIOW(IOC_VENDOR,4)
#define SIO_ABSORB_RTRALERT   _WSAIOW(IOC_VENDOR,5)
#define SIO_UCAST_IF          _WSAIOW(IOC_VENDOR,6)
#define SIO_LIMIT_BROADCASTS  _WSAIOW(IOC_VENDOR,7)
#define SIO_INDEX_BIND        _WSAIOW(IOC_VENDOR,8)
#define SIO_INDEX_MCASTIF     _WSAIOW(IOC_VENDOR,9)
#define SIO_INDEX_ADD_MCAST   _WSAIOW(IOC_VENDOR,10)
#define SIO_INDEX_DEL_MCAST   _WSAIOW(IOC_VENDOR,11)
 
 
//定义Ip数据报头结构,20个字节
typedef struct HeadIP {
            unsigned char  headerlen:4;  //首部长度,占4位
        unsigned char  version:4;    //版本,占4位
 
        unsigned char  servertype;   //服务类型,占8位,即1个字节
        unsigned short totallen;     //总长度,占16位
        unsigned short id;           //与idoff构成标识 ,共占16位,前3位是标识,后13位是片偏移
        unsigned short idoff;       
        unsigned char  ttl;          //生存时间 ,占8位        
        unsigned char  proto;        //协议,占8位  
        unsigned short checksum;     //首部检验和,占16位 
        unsigned int   sourceIP;     //源IP地址,占32位
        unsigned int   destIP;       //目的IP地址,占32位
 
}HEADIP;
 
//定义TCP数据报首部
typedef struct HeadTCP {
            WORD   SourcePort;    //16位源端口号
            WORD   DePort;        //16位目的端口
            DWORD  SequenceNo;    //32位序号
            DWORD  ConfirmNo;     //32位确认序号
            BYTE   HeadLen;       //与Flag为一个组成部分, 首部长度,占4位,保留6位,6位标识,共16位  
            BYTE   Flag;
            WORD   WndSize;       //16位窗口大小
            WORD   CheckSum;      //16位校验和
            WORD   UrgPtr;        //16位紧急指针
} HEADTCP;
 
//定义UDP数据报首部
typedef struct HeadUDP {
            WORD SourcePort;  //16位源端口号
            WORD DePort;      //16位目的端口
            WORD Len;         //16为UDP长度
            WORD ChkSum;      //16位UDP校验和
} HEADUDP;
 
 
//定义ICMP数据报首部
typedef struct HeadICMP {
            BYTE Type;    //8位类型
            BYTE Code;    //8位代码
            WORD ChkSum;  //16位校验和
} HEADICMP;
 
//定义协议名称
struct  PROTONAME{
      int  value;
      char* protoname; 
};
 
 
在类.h中添加:
      SOCKET       m_Sock ;
      CWinThread*  m_pThread;

      CListCtrl     m_List;
 
 
// CSniffAppDlg dialog
PROTONAME protos[11] = {
      {IPPROTO_IP ,"IP"},
      {IPPROTO_ICMP,"ICMP"},
      {IPPROTO_IGMP,"IGMP"},
      {IPPROTO_GGP,"GGP"},
      {IPPROTO_TCP,"TCP"},
      {IPPROTO_PUP,"PUP"},
      {IPPROTO_UDP,"UDP"},
      {IPPROTO_IDP,"IDP"},
      {IPPROTO_ND,"ND"},
      {IPPROTO_RAW,"RAW"},
      {IPPROTO_MAX,"MAX"}
};
 
char* get_protoname(int protoID)
{
      for (int i= 0; i<11; i++)
            if (protoID == protos[i].value)
            {
                  return protos[i].protoname;
            }
      return "";
}
 
 
CSniffAppDlg::CSniffAppDlg(CWnd* pParent /*=NULL*/)
      : CDialog(CSniffAppDlg::IDD, pParent)
{
      //{{AFX_DATA_INIT(CSniffAppDlg)
      //}}AFX_DATA_INIT
      // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
      m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
      m_pThread = NULL;
}
 
BOOL CSniffAppDlg::OnInitDialog()
{
      CDialog::OnInitDialog();
      SetIcon(m_hIcon, TRUE);            // Set big icon
      SetIcon(m_hIcon, FALSE);         // Set small icon
     
      m_List.SetExtendedStyle(LVS_EX_FLATSB|LVS_EX_GRIDLINES|LVS_EX_TWOCLICKACTIVATE);
 
      m_List.InsertColumn(0,"协议",LVCFMT_LEFT,80);
      m_List.InsertColumn(1,"源IP地址",LVCFMT_LEFT,120);
      m_List.InsertColumn(2,"目的IP地址",LVCFMT_LEFT,120);
      m_List.InsertColumn(3,"通信端口",LVCFMT_LEFT,80);
      m_List.InsertColumn(4,"大小",LVCFMT_LEFT,100);
      m_List.InsertColumn(5,"数据",LVCFMT_LEFT,120);
      return TRUE;  // return TRUE  unless you set the focus to a control
}
 
void CSniffAppDlg::OnOK()
{
 
}
 
//线程函数
UINT ThreadFun( LPVOID pParam )
{
      CSniffAppDlg* pDlg = static_cast<CSniffAppDlg*>(pParam);
     
      MSG msg;
      char buffer[1000],sourceip[32] ,*tempbuf;
      char *ptemp;
 
      BYTE* pData = NULL; //实际数据报中的数据
     
 
      UINT  sourceport ;
 
      CString str;
 
      HEADIP*    pHeadIP;
      HEADICMP*  pHeadICMP;
      HEADUDP*   pHeadUDP;
      HEADTCP*   pHeadTCP;
     
      in_addr addr;
     
      int ret;
      while (TRUE)
      {
            pData = NULL;
            if (PeekMessage(&msg,pDlg->m_hWnd,WM_CLOSE,WM_CLOSE,PM_NOREMOVE ))
            {
                  closesocket(pDlg->m_Sock);
                  break;        
            }
            memset(buffer,0,1000);
 
 
            ret = recv(pDlg->m_Sock,buffer,1000,0);
           
            if (ret == SOCKET_ERROR)
            {
                  continue;
            }
            else //接收到数据
            {
                  tempbuf = buffer;
                 
                  pHeadIP = (HEADIP*)tempbuf;
                 
                  //获取数据报总长度
                  WORD len = ntohs(pHeadIP->totallen);
                 
                  //获取源IP
                  pDlg->m_List.InsertItem(pDlg->m_List.GetItemCount(),"");
                  addr.S_un.S_addr = pHeadIP->sourceIP;
                  ptemp = inet_ntoa(addr);
                 
                  pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,1,ptemp);
           
                  //获取目的IP
                  addr.S_un.S_addr = pHeadIP->destIP;
                  ptemp = inet_ntoa(addr);
                  pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,2,ptemp);
                 
                  //获取协议名称
                  ptemp = get_protoname(pHeadIP->proto);
                  strcpy(sourceip,ptemp);
                  pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,0,sourceip);
                 
                 
                  //获取IP数据报总长度
                  WORD ipSumLen  =  ntohs(pHeadIP->totallen);
                 
                  //IP数据报头总长度
                  int ipHeadLen = 20;
 
                  //获得去除IP层数据的长度
                  WORD  netlen = ipSumLen - ipHeadLen;
                 
                  //根据不同大协议获得不同协议的数据
                  switch (pHeadIP->proto)
                  {
                  case IPPROTO_ICMP:
                        {
                              pHeadICMP = (HEADICMP*)(tempbuf+20);
                             
                              pData = (BYTE*)(pHeadICMP)+4; //ICMP数据报头共4个字节                                
                              //获取数据的长度
                              netlen -= 4;
 
                              break;
                        }
                  case IPPROTO_UDP:
                        {
                              pHeadUDP = (HEADUDP*)(tempbuf+20);
                             
                             
 
                              pData = (BYTE*)pHeadUDP+8; //UDP数据报头共8个字节
                             
                              sourceport = ntohs(pHeadUDP->SourcePort);
                             
                              str.Format("%d",sourceport);
                              //设置源端口
                              pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,3,str);
                             
                              str.Empty();
 
                              netlen -= 8;                
                              break;
                        }
                  case IPPROTO_TCP:
                        {
                              pHeadTCP = (HEADTCP*)(tempbuf+20);
                              sourceport = ntohs(pHeadTCP->SourcePort);                              
 
                              pData = (BYTE*)pHeadTCP+20; //TCP数据报头共20个字节
                                                      
                              str.Format("%d",sourceport);
                              //设置源端口
                              pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,3,str);
                              str.Empty();
                              netlen-= 20;               
                              break;
                        }                                                  
                  }
                  //设置数据大小
                  str.Format("%d",netlen);
                  pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,4,str);
                  str.Empty();
                  //设置数据
                  if (pData != NULL)
                  {
                        str.Format(" %s",pData);
                        pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,5,str);
                  }
                  str.Empty();
            }
      }
      return 0;
}
 
 
void CSniffAppDlg::OnBeginlisten()
{
      //创建套接字
      m_Sock = socket(AF_INET,SOCK_RAW, IPPROTO_IP );
     
      char name[128];
      memset(name,0,128);
     
      hostent* phostent;
 
      phostent =  gethostbyname(name);
     
      DWORD ip;
     
      ip = inet_addr(inet_ntoa(*(in_addr*)phostent->h_addr_list[0]));
 
 
      int timeout = 4000; //超时4秒
 
      //设置接收数据的超时时间
      setsockopt(m_Sock,SOL_SOCKET,SO_RCVTIMEO,(const char*)&timeout,sizeof(timeout));
 
      sockaddr_in skaddr;
      skaddr.sin_family = AF_INET;
      skaddr.sin_port = htons(700);
      skaddr.sin_addr.S_un.S_addr  = ip;
      //绑定地址
      if ( bind(m_Sock,(sockaddr*)&skaddr,sizeof(skaddr))==SOCKET_ERROR)
      {
            MessageBox("地址绑定错误");
            return;
      }
     
      DWORD inBuffer=1;
      DWORD outBuffer[10];
      DWORD reValue = 0;
 
      if (WSAIoctl(m_Sock,SIO_RCVALL,&inBuffer,sizeof(inBuffer),&outBuffer,sizeof(outBuffer),&reValue,NULL,NULL)==SOCKET_ERROR)
      {
            MessageBox("设置缓冲区错误.");
            closesocket(m_Sock);
            return;
      }
      else
            m_pThread = AfxBeginThread(ThreadFun,(void*)this);
}
 
void CSniffAppDlg::OnCancel()
{
      if (m_pThread)
      {
            //m_pThread->ExitInstance();
            delete m_pThread;
      }
      closesocket( m_Sock) ;
      CDialog::OnCancel();
}


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/AIHANZI/archive/2010/05/25/5623739.aspx

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
winpcap(windows packet capture)是windows平台下一个免费,公共的网络访问系统。开发winpcap这个项目的目的在于为win32应用程序提供访问网络底层的能力。它提供了以下的各项功能:   1> 捕获原始数据报,包括在共享网络上各主机发送/接收的以及相互之间交换的数据报;   2> 在数据报发往应用程序之前,按照自定义的规则将某些特殊的数据报过滤掉;   3> 在网络上发送原始的数据报;   4> 收集网络通信过程中的统计信息。   winpcap的主要功能在于独立于主机协议(如TCP-IP)而发送和接收原始数据报。也就是说,winpcap不能阻塞,过滤或控制其他应用程序数据报的发收,它仅仅只是监听共享网络上传送的数据报。因此,它不能用于QoS调度程序或个人防火墙。目前,winpcap开发的主要对象是windows NT/2000/XP,这主要是因为在使用winpcap的用户中只有一小部分是仅使用windows 95/98/Me,并且M$也已经放弃了对win9x的开发。因此本文相关的程序T-ARP也是面向NT/2000/XP用户的。其实winpcap中的面向9x系统的概念和NT系统的非常相似,只是在某些实现上有点差异,比如说9x只支持ANSI编码,而NT系统则提倡使用Unicode编码。有个软件叫sniffer pro.可以作网管软件用,有很多功能,可监视网络运行情况,每台网内机器的数据流量,实时反映每台机器所访问IP以及它们之间的数据流通情况,可以抓包,可对过滤器进行设置,以便只抓取想要的包,比如POP3包,smtp包,ftp包等,并可从中找到邮箱用户名和密码,还有ftp用户名和密码.它还可以在使用交换机的网络上监听,不过要在交换机上装它的一个软件.还有一个简单的监听软件叫 Passwordsniffer,可截获邮箱用户名和密码,还有ftp用户名和密码,它只能用在用HUB网络上著名软件tcpdump及ids snort都是基于libpcap编写的,此外Nmap扫描器也是基于libpcap来捕获目标主机返回的数据包的。   winpcap提供给用户两个不同级别的编程接口:一个基于libpcap的wpcap.dll,另一个是较底层的packet.dll。对于一般的要与unix平台上libpcap兼容的开发来说,使用pacap.dll是当然的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值