实践三 网络嗅探与协议分析

网络嗅探与协议分析

1. 每个人找一个抓包软件,分析其功能,设计的模块等,着重使用和分析,不建议用wireshark,编译过程可能比较难,也可挑战

(1)首先我们要清楚抓包的原理。

  • 网络数据包捕获的原理:以太网(Ethernet)具有共享介质的特征,信息是以明文的形式在网络上传输,当网络适配器设置为监听模式(混杂模式,Promiscuous)时,由于采用以太网广播信道争用的方式,使得监听系统与正常通信的网络能够并 联连接,并可以捕获任何一个在同一冲突域上传输的数据包。

  • winpcap抓包原理:WinPcap 包括三个部分:NPF(Netgroup Packet Filter)、packet.dll和Wpcap.dll。packet.dll直接映射了内核的调用。 Wpcap.dll提供了更加友好、功能更加强大的函数调 用。WinPcap的优势是提供了一套标准的抓包接口,与libpcap兼容,可使得原来许多UNIX平台下的网络分析工具快速移植过来便于开发各种网络分析工具,充分考虑了各种性能和效率的优化,包括对于NPF内核层次上的过滤器支持,支持内核态的统计模式,提供了发送数据包的能力。

(2)其次,我们需要清楚经典的ISO/OSI参考模型与TCP/IP模型

实践三 网络嗅探与协议分析_第1张图片

(3)最后我们来分析我找到的一个基于winpcap的抓包工具

winpcap(windows packet capture)是windows平台下一个免费,公共的网络访问系统。我们常用的wireshark软件是基于winpcap的,winpcap可直接开发基于网络底层协议的应用程序。

  • 本程序设计流程

    1、由于winpcap是基于网卡的数据获取,所以先获取正确的网卡

    2、打开选择的网卡设备

    3、启动抓包

  • 相关接口介绍

    1、int pcap_findalldevs(pcap_if_t **, char *);//获取所有网络设备,保存于pcap_if_t 指向的内存空间
    
    2、void pcap_freealldevs(pcap_if_t *); // 清空所有网络设备
    
    3、pcap_t *pcap_open(const char *source, // 获取的设备名
    
    int snaplen, //要捕捉的数据包的部分
    
    int flags, // 模式
    
    int read_timeout,// 超时时间
    
    struct pcap_rmtauth *auth, // 远程机器验证
    
    char *errbuf);// 错误缓冲池
    
    4、void pcap_close(pcap_t *);//关闭设备
    
    5、pcap_compile(pCap, &fcode, filter, 1, NetMask)
    
    6、pcap_setfilter(pCap, &fcode)// 设置过滤规则
    
    7、int pcap_next_ex(// 从interface或离线记录文件获取一个报文
    
    pcap_t *,
    
    struct pcap_pkthdr **, // 报文头,包含mac地址
    
    const u_char **);//报文内容
    
  • 具体分析

    • 网卡选择

      AdapaterSelection.cpp 文件中OnInitDialog()用于选择网卡功能的实现

      m_pDev 变量定位获取到的网卡名称,如下

      pcap_if_t* CAdapaterSelection::getDevice()
      
      {
           if(m_pDev == NULL)
                return NULL;
           return m_pDev;
      }
      

      HTREEITEM是树中节点的句柄,也就是一个DWORD值,在树中唯一标识一个节点。下面以树形结构显示本机所有网络适配器,包括IP地址、广播地址、子网掩码、目的地址。写好网络适配器显示功能开始选择,在CapturePacketDlg.cpp 文件中

      OnMenuNetworkconfiguration() 函数用于选择网卡信息,

      m_pDevice 指针变量,定义所选中的网卡地址:m_pDevice = dlg.getDevice();

    以下分析抓包的过程

    先介绍几个函数:

    pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) 
    函数功能:获得用于捕获网络数据包的数据包捕获描述字。 
    参数说明:device参数为指定打开的网络设备名。snaplen参数定义捕获数据的最大字节数。promisc指定是否将网络接口置于混杂模式。to_ms参数指*定超时时间(毫秒)。ebuf参数则仅在pcap_open_live()函数出错返回NULL时用于传递错误消息。
    文件中定义为pCap=pcap_open_live(pDlg->getDevice()->name,65536,1,1000,strErrorBuf)
    
    
    用于过滤数据包的两个函数:
    pcap_compile(pCap, &fcode, filter, 1, NetMask)函数是将过滤字符串filter编译进过滤程序fcode,程序(fcode)是一个指向 bpf_program结构体并被pcap_compile()赋值的指针。
    pcap_setfilter(pCap, &fcode) 函数是把一个过滤器同一次抓包关联起来。
    
    
    函数名称:int pcap_loop(pcap_t * p,int cnt, pcap_handler callback, uchar * user);
    函数功能:捕获数据包,不会响应pcap_open_live()函数设置的超时时间
    参数说明:p 是由pcap_open_live()返回的所打的网卡的指针;cnt用于设置所捕获数据包的个数;pcap_handler 是与void packet_handler()使用的一个参数,即回调函数的名称;user值一般为NULL
    
    
    以上信息的代码如下:
    
    DWORD WINAPI CapturePacket(LPVOID lpParam)
    {
    CCapturePacketDlg *pDlg = (CCapturePacketDlg *)lpParam;
       pcap_t *pCap;
       char    strErrorBuf[PCAP_ERRBUF_SIZE];
    
      if((pCap=pcap_open_live(pDlg->getDevice()->name,65536,1,1000,strErrorBuf))==NULL)
      {         
           return -1;
      }
    
      if (pDlg->m_strFilterString.GetLength() > 0)
      {
           struct bpf_program fcode;
     bpf_u_int32 NetMask;
           NetMask=0xffffff;  //如果接口没有地址,那么我们假设一个C类的掩码 
    
           char filter[1024];        
           strcpy(filter, pDlg->m_strFilterString.GetBuffer(pDlg->m_strFilterString.GetLength()));
           pDlg->m_strFilterString.ReleaseBuffer();     
           
           //compile the filter
           if(pcap_compile(pCap, &fcode, filter, 1, NetMask) < 0)
           {
               //fprintf(stderr,"\nError compiling filter: wrong syntax.\n");
               AfxMessageBox("编译字符串失败,程序无法启动进行抓包,请确认规则的正确性");
               return -1;
           }
    
           //set the filter
           if(pcap_setfilter(pCap, &fcode)<0)
           {
               //fprintf(stderr,"\nError setting the filter\n");
               AfxMessageBox("设置过滤串失败");
               return -1;
           }
      }
    
    do
      {
           pcap_loop(pCap,1,pcap_handle,NULL);
      }while(pDlg->getFlag());
    
      pcap_close(pCap);
      pDlg = NULL;
      return 1;  
    }
    ShowPacketForTree() 
    
    • 统计抓到的网络数据包

      用于统计抓到的网络数据包,具体代码在void CCapturePacketDlg::processPacket(const pcap_pkthdr *pkt_header, const u_char *pkt_data) 中,因代码过长,这里不再粘贴,其中定义了m_lUdpCountm_lTcpCountm_lArpCount变量以统计每次抓到的相应的包的数量。功能实现截图如下:

      实践三 网络嗅探与协议分析_第2张图片

    • 显示选中数据包的信息

      用于显示选中的某个数据包的具体信息,代码在void CCapturePacketDlg::ShowPacketForTree(const pcap_pkthdr *pkt_header, const u_char *pkt_data,long index)中,同样以树形结构显示,链路层数据通过FramePacket.cpp文件定义,故MAC地址通过pFramePacket->GetMacSrcAddr()pFramePacket->GetMacDestAddr()得到,网络层信息由IPPacket.cpp定义,传输层数据由UDPPacket.cppTCPPacket.cppARPPacket.cppRARPPacket.cpp定义,故使用响应的函数获取IP地址、操作类型、数据长度等内容,下面仅以传输层数据为例展示如下:

      HTREEITEM hSubItem = m_treeSingerPacket.InsertItem("链路层数据",hRoot);   
        CFramePacket *pFramePacket = new CFramePacket(pkt_data,14);  
        HTREEITEM hItem = m_treeSingerPacket.InsertItem("源MAC地址 : "+pFramePacket->GetMacSrcAddr(),hSubItem);  
      ​     hItem = m_treeSingerPacket.InsertItem("目的MAC地址 : "+pFramePacket->GetMacDestAddr(),hSubItem);   
      ​     CString strType;   
      ​     strType.Format("类型 : 0X%x",pFramePacket->GetType());  
      ​     hItem = m_treeSingerPacket.InsertItem(strType,hSubItem);
      

      其中,如何判断是哪种类型的protocol呢?通过FramePacket.cpp中的GetType()函数获得协议类型,这里的协议类型都是十六进制表示的,如ARP协议的判断:

      else if(pFramePacket->GetType() == 0x0806)  
      ​     {  
      ​          CARPPacket *pARPPacket = new CARPPacket(pkt_data+14,pkt_header->len-14);  
      ​          hItem = m_treeSingerPacket.InsertItem("协议 : ARP",hSubItem);  
      ​          hItem = m_treeSingerPacket.InsertItem("源IP : "+pARPPacket->GetSPAddr(),hSubItem);  
      ​          hItem = m_treeSingerPacket.InsertItem("目的IP: "+pARPPacket->GetDPAddr(),hSubItem);  
      ​          hItem = m_treeSingerPacket.InsertItem("硬件地址类型: "+pARPPacket->GetHaddrtype(),hSubItem); 
      ​          hItem = m_treeSingerPacket.InsertItem("协议地址类型: "+pARPPacket->GetPaddrtype(),hSubItem);   
      ​          hItem = m_treeSingerPacket.InsertItem("硬件地址长度: "+pARPPacket->GetHaddrlen(),hSubItem);  
      ​          hItem = m_treeSingerPacket.InsertItem("协议地址长度: "+pARPPacket->GetPaddrlen(),hSubItem);   
      ​          hItem = m_treeSingerPacket.InsertItem("操作类型: "+pARPPacket->GetOperation(),hSubItem);   
      ​          hItem = m_treeSingerPacket.InsertItem("发送站点硬件地址: "+pARPPacket->GetSHaddr(),hSubItem);  
      ​          hItem = m_treeSingerPacket.InsertItem("目的站点硬件地址: "+pARPPacket->GetDHaddr(),hSubItem);   
      ​       delete pARPPacket;  
      ​          pARPPacket = NULL;  
      ​     }
      

      传输层判断是TCP还是UDP协议,使用ipPacket.GetProtocol()函数。

      单个数据包的分析截图如下:

    实践三 网络嗅探与协议分析_第3张图片

    本程序还有将数据导出到文件,查看具体使用帮助等功能,这里不再详述。

2. 找一个网站或者搭建一个本地网站,登录网站,并嗅探,分析出账号和密码,结果截图1-2张。(3分)可以用邮箱、各类博客、云班课,只能分析自己的账号,严禁做各类攻击,否则后果自负。

这里,我访问了天翼快递的网页(www.tykd.com),访问前先注册一个用户,并打开抓包工具。

经查询,上述域名对应的IP地址为47.56.157.205,如图:

实践三 网络嗅探与协议分析_第4张图片

ip.dst==47.56.157.205 进行过滤,查找到登录的数据包,可明显发现我的登录用户名和密码,如图:

实践三 网络嗅探与协议分析_第5张图片

可见,不加ssh加密协议的网址登录是多么不安全,用户名和密码轻松就被搞到手。

3. 加分项2分:注意本次加分项不加到额外10分里,加到本次实验中。例如,本次实验7分,算上加分可得9分。抓取手机App的登录过程数据包,分析账号和密码。可以用邮箱、各类博客、云班课,只能分析自己的账号,严禁做各类攻击,否则后果自负。

本来想电脑开启共享网络,但是总遇不到解决不了的问题,最后安装了WiFi大师,本地连接2的IP:192.168.155.1,手机连接到热点的IP:192.168.155.2 ,打开抓包工具,这里我几乎登录了手机所有APP进行抓包,失望的是很多APP抓不到,我尝试了用云班课登录,抓到的post包如下:

可见用户名和密码都是密文传输的,我尝试用解密工具解密,仍未得到正确结果。最后一点希望寄托在大学常用的一款用于党员学习APP(e支部),APP关联了QQ、微信,没想到用户名和密码都是明文传输的,截图如下:

实践三 网络嗅探与协议分析_第6张图片

轻松捕获到用户名和密码。

4. 问题及解决方法

  • 问题1:无法启动承载网络。

    解决方法:尝试用百度到的开启服务,开启托管网络等方法都无法解决问题,最后还是选择直接安装WiFi大师吧,省去了很多麻烦。

  • 问题2:抓包软件搜索不到电脑WiFi的网卡。

    解决方法:网络和共享中心->更改适配器设置->本地连接2->属性->开启Ncap Packet Driver项目,如图:

    实践三 网络嗅探与协议分析_第7张图片

5. 参考文献

winpcap抓包原理

使用winpcap开发网络抓包工具

https://www.jianshu.com/p/4a554f55fe9c

你可能感兴趣的:(实践三 网络嗅探与协议分析)