网络攻击与防范实验报告

网络攻击与防范实验报告

姓名:_ __ _  学号:____200948300108005  _所在班级:  702  

实验名称:         编写自己的网络嗅探器          实验日期:_2009__10__25_

指导老师:             张玉清、宋               实验评分:                 

验收评语:                                                                    

                                                                              

参与人员:

实验目的:

? 开发一个Windows平台上的网络嗅探工具

? 通过开发基于WinPcap的嗅探器,掌握嗅探器的工作原理,熟悉WinPcap的使用,掌握基于WinPcap网络嗅探器的开发过程

实验内容:

? 能列出监测主机的所有网卡。

? 能选择其中一个网卡进行监听

? 能捕获并显示流经网卡的数据包,并做相应的分析和统计

? 能设置捕获过滤规则(按协议类型、端口、地址等)

? 在TCP、UDP、ARP、ICMP、IGMP等协议中选择至少三种进行重点分析,

? 选择至少一种应用层协议如http、ftp等进行分析

? 能按照协议格式进行格式化显示。

? 有可视化操作界面,易于使用

实验环境:

Ø  硬件环境:

²  处理器:PentiumIII 800 以上

²  内存:1G

²  硬盘:40G

²  网卡:100M以上

²  网速:ISDN128K以上

Ø  软件环境:

²   操作系统:Windows XP with SP3 or Vista or Windows 7

²   开发工具:Visual Studio 20## with SP1

²   开发语言:C++

实验设计:

本实验的目标主要是利用WinPcap开发包工具,独立开发出一个网络嗅探器。因此可以首先根据WinPcap开发包提供的网络接口获取到底层的网卡信息及其数据包;然后再根据TCP/IP协议栈的结构,依次在数据链路层、网络层、数据传输层和应用层,分别进行数据包的分拆与解析,获取相应协议层的数据信息;再次经过几个最常用的协议,如针对Mac、ARP、IP、TCP、UDP、ICMP、HTTP等协议,进行测试;最后,对程序的结构框架、界面设计等不断地进行修正、改进,使自己开发的作品日臻完善。

详细过程(本文所有程序源码,均摘自于本人源程序):

Ø  利用WinPcap开发包工具

²   获取本机所有网卡列表信息

pcap_if_t *  MyWinPcap::GetAdapterList(void )

{

   /* Retrieve the device list from the local machine */

   char errbuf[PCAP_ERRBUF_SIZE];

   pcap_if_t * m_alldevs = new pcap_if_t();  // ?????? allocate memory to sava temp all-devs ?????

    if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL /* auth is not needed */, &m_alldevs, errbuf) == -1) // if error

    {

       CString errmsg;

       USES_CONVERSION;

       errmsg.Format(TEXT("Error in cap_finalldevs_ex(): %s\n"),A2W(errbuf));

       AfxMessageBox(errmsg);

      

       return NULL;

   }

   else if(NULL == m_alldevs)

   {

       AfxMessageBox(TEXT("No interfaces found! Make sure WinPcap is installed..."));

       return NULL;

   }

   else

       return m_alldevs;

}

²   打开选中的网卡,获取数据包信息

pcap_if_t* CYGSnifferDlg::GetSelectedAdapter(int iSelectAdapterNo,int iTotalAdapter)

{

   int i;

   pcap_if_t* tmpAllDevs = tmpMyWinPcap.GetAdapterList();

   pcap_if_t* pSeletedAdapter = new pcap_if_t;

   pSeletedAdapter = NULL;

   /* Jump to the selected adapter */

   for(pSeletedAdapter = tmpAllDevs,i = 0;i < iSelectAdapterNo;pSeletedAdapter = pSeletedAdapter->next,i++); //********* turn to next piont *********

  

   return pSeletedAdapter;

   if(pSeletedAdapter)

   {

       delete pSeletedAdapter;

       pSeletedAdapter = NULL;

   }

}

DWORD WINAPI Thread_GetFilterData(LPVOID param)

{

   pcap_if_t* pSelectedAdapter = (pcap_if_t*)param; // Get SelectedAdapter

   char errbuf[PCAP_ERRBUF_SIZE];

   CString errmsg;

   pcap_t* adhandle;

   /* Open the device */

   if((adhandle = pcap_open(pSelectedAdapter->name,65536,PCAP_OPENFLAG_PROMISCUOUS,1000,NULL,errbuf)) == NULL)

   {

       USES_CONVERSION;

       errmsg.Format(TEXT("Unable to open the adapter. %s is not supported by WinPcap"),pSelectedAdapter->name);

       AfxMessageBox(errmsg);

       /* At this point, we don't need any more the device list. Free it */

       pcap_freealldevs(pSelectedAdapter);

       return -1;

   }

   // filter packet data(protocol)

   u_int netmask;

  

   struct bpf_program fcode;

   // get netmask

   if(NULL != pSelectedAdapter->addresses)

       netmask = ((struct sockaddr_in *)(pSelectedAdapter->addresses->netmask))->sin_addr.S_un.S_addr;

   else

       netmask = 0xffffff;

   // comppile the filter

   if(pcap_compile(adhandle,&fcode,packet_filter,1,netmask) < 0)

   {

       AfxMessageBox(TEXT("Unable to compile the packet filter. Check the syntax."));

       /* Free the device list */

        pcap_freealldevs(pSelectedAdapter);

       return -1;

   }

   // set the filter

   if(pcap_setfilter(adhandle,&fcode) < 0)

   {

       AfxMessageBox(TEXT("Error setting the filter."));

       /* Free the device list */

        pcap_freealldevs(pSelectedAdapter);

       return -1;

   }

   pcap_freealldevs(pSelectedAdapter);

   pcap_loop(adhandle, 0, packet_handler, NULL);

   pcap_close(adhandle);

   

    return 0;

}

²   调用WinPcap提供的回调函数

void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)

{

    pcap_pkthdr *header2 = new pcap_pkthdr;

    u_char *pkt_data2 = new u_char[header->len];

    memcpy(header2,header,sizeof(pcap_pkthdr));

    memcpy(pkt_data2,pkt_data,header->len);

   

    //PostMessage 只是把消息放入队列,不管其他程序是否处理都返回,然后继续执行;

    //而SendMessage 必须等待其他程序处理消息后才返回,继续执行

    ::PostMessage(hDlgHandle, M_MESSAGEWINPCAP, (WPARAM)header2, (LPARAM)pkt_data2); // == ** Post Message ** ==

}

Ø  解析TCP/IP协议栈的结构

²   各层协议的头信息声明

// i386 is little_endian.

#ifndef LITTLE_ENDIAN

#define LITTLE_ENDIAN   (1)   //BYTE ORDER

#else

#error Redefine LITTLE_ORDER

#endif

//Mac头部,总长度字节

typedef struct ethernet_header

{

u_char dstmac[6]; //目标mac地址

u_char srcmac[6]; //源mac地址

u_short eth_type; //以太网类型

}ethernet_header;

/* 4 bytes IP address */

typedef struct ip_address{

    u_char byte1; //IP地址第个字段

    u_char byte2; //IP地址第个字段

    u_char byte3; //IP地址第个字段

    u_char byte4; //IP地址第个字段

}ip_address;

//IP头部,总长度字节

typedef struct ip_header

{

#if LITTLE_ENDIAN

u_char ihl:4;    //首部长度

u_char version:4;//版本

#else

u_char version:4;//版本

u_char ihl:4;    //首部长度

#endif

u_char tos;       //服务类型

u_short tot_len; //总长度

u_short id;      //标识号

#if LITTLE_ENDIAN

u_short frag_off:13;//分片偏移

u_short flag:3;     //标志

#else

u_short flag:3;     //标志

u_short frag_off:13;//分片偏移

#endif

u_char ttl;      //生存时间

u_char protocol; //协议

u_short chk_sum; //检验和

struct ip_address srcaddr; //源IP地址

struct ip_address dstaddr; //目的IP地址

}ip_header;

//TCP头部,总长度字节

typedef struct tcp_header

{

u_short src_port;   //源端口号

u_short dst_port;   //目的端口号

u_int seq_no;       //序列号

u_int ack_no;       //确认号

#if LITTLE_ENDIAN

u_char reserved_1:4; //保留位中的位首部长度

u_char offset:4;     //tcp头部长度

u_char flag:6;       //6位标志

u_char reserved_2:2; //保留位中的位

#else

u_char offset:4;     //tcp头部长度

u_char reserved_1:4; //保留位中的位首部长度

u_char reserved_2:2; //保留位中的位

u_char flag:6;    //6位标志

#endif

u_short wnd_size;   //16位窗口大小

u_short chk_sum;    //16位TCP检验和

u_short urgt_p;     //16为紧急指针

}tcp_header;

//UDP头部,总长度字节

typedef struct udp_header

{

u_short src_port; //远端口号

u_short dst_port; //目的端口号

u_short uhl;      //udp头部长度

u_short chk_sum;  //16位udp检验和

}udp_header;

//ICMP头部,总长度字节

typedef struct icmp_header

{

u_char type;    //类型

u_char code;      //代码

u_short chk_sum;  //16位检验和

}icmp_header;

²   解析数据链路层的Mac协议

void CYGSnifferDlg::ShowMacDetail(HTREEITEM & hItem, const u_char * pkt_data)

{

    ethernet_header *mac_hdr = (ethernet_header *)pkt_data;

    hItem = m_treeDetailInfo.InsertItem(TEXT("MAC LAYER"));

    CString str = NULL;

    TCHAR mac_dstAddr[18];

    TCHAR mac_srcAddr[18];

    CString mac_strType = NULL;

    GetMacType(mac_strType,ntohs(mac_hdr->eth_type),false); // 16-bit == u_short ==  ntohs() is to swap network to host

    str.Format(TEXT("Mac Type = %s"),mac_strType);

    m_treeDetailInfo.InsertItem(str,hItem);

    GetMacAddress(mac_srcAddr,mac_hdr->srcmac);

    str.Format(TEXT("Source Mac = %s"),mac_srcAddr);

    m_treeDetailInfo.InsertItem(str,hItem);

    GetMacAddress(mac_dstAddr,mac_hdr->dstmac);

    str.Format(TEXT("Dest Mac = %s"),mac_dstAddr);

    m_treeDetailInfo.InsertItem(str,hItem);

}

²   解析网络层的IPARPRARP等协议

void CYGSnifferDlg::GetMacType(CString &eth_strType, u_short eth_Type, bool isFirst) //& is to pass address

{

    if(isFirst)

       iStatistic_TotalProtocol++;

    switch(eth_Type)

    {

       case 0x0800:

           eth_strType = TEXT("IP");

           if(isFirst)

              iStatistic_TotalIP++;

           break;

       case 0x0806:

           eth_strType = TEXT("ARP");

           if(isFirst)

              iStatistic_TotalARP++;

           break;

       case 0x8035:

           eth_strType = TEXT("RARP");

           break;

       case 0x880B:

           eth_strType = TEXT("PPP");

           break;

       case 0x814C:

           eth_strType = TEXT("SNMP");

           break;

       default:

           eth_strType = TEXT("other");

           break;

    }

}

²   解析数据传输层的TCPUDPICMP等协议

void CYGSnifferDlg::GetIPType(CString &ip_strIP, u_short ip_Type, bool isFirst)

{

    switch(ip_Type)

    {

       case 1:

           ip_strIP = TEXT("ICMP");

           if(isFirst)

              iStatistic_TotalICMP++;

           break;

       case 6:

           ip_strIP = TEXT("TCP");

           if(isFirst)

              iStatistic_TotalTCP++;

           break;

       case 17:

           ip_strIP = TEXT("UDP");

           if(isFirst)

              iStatistic_TotalUDP++;

           break;

       default:

           ip_strIP = TEXT("other");

           break;

    }

}

²   解析应用层的HTTP协议(基于传输层的TCP协议)

bool CYGSnifferDlg::IsHTTP(const u_char *pkt_data)

{

    ip_header *ip_hdr = (ip_header *)(pkt_data+14);

    u_short ip_hdrLen = ip_hdr->ihl*4;

    tcp_header * tcp_hdr = (tcp_header *)(pkt_data+14+ip_hdrLen);

    u_short tcp_hdrLen = tcp_hdr->offset*4;

    u_char *http_pkt = (u_char *)(pkt_data+14+ip_hdrLen+tcp_hdrLen);  

    u_short http_pktLen = ntohs(ip_hdr->tot_len) - (ip_hdrLen+tcp_hdrLen); //u_short httpLen2 = header->len - (14+ip_hdrLen+tcp_hdrLen);

   

    CString chrTmp = NULL;

    CString strTmp = NULL;

    CString strHttp = NULL;

    int httpPos = 0;

    if(ip_hdr->protocol == 6)

    {

       for(int i=0;i<http_pktLen;i++) // 仅提取第一行是否含有HTTP字符串

       {

           chrTmp.Format(TEXT("%c"),http_pkt[i]);

           strTmp += chrTmp;

           if(i>2 && http_pkt[i-1]==13 && http_pkt[i]==10)

              break;

       }

       //AfxMessageBox(strTmp);

       httpPos = strTmp.Find(TEXT("HTTP"),0);

       if(httpPos != -1 && httpPos != 65535) // 如果第一行含有字符串HTTP,则为HTTP协议

       {

           iStatistic_TotalHTTP++;

           return true;

       }

          

       else

           return false;

      

    }

    return false;

}

Ø  测试各个协议层的数据信息

MacIPUDPTCPHTTP等协议及其统计信息

MacIPARPTCPUDPICMP等协议及其统计信息

Ø  修正与改进,使之日臻完善

²   运用了多线程技术,进行抓包处理,使其速度、性能得到了有效改善

例如:  m_hdlThread = CreateThread(NULL,0,Thread_GetFilterData,(LPVOID)pSelectAdapter,0,&dwThread);

²   运用了消息传递技术,使其能够在主线程(即主对话框线程)与子线程(即自己新创建的抓包线程)进行通信

例如:::PostMessage(hDlgHandle, M_MESSAGEWINPCAP, (WPARAM)header2, (LPARAM)pkt_data2); // == ** Post Message ** ==

²   运用了文件的存储与读取方法,节省了内存的消耗

// Append packet

void MyWinPcap::AppendPacket(packet *pkt)

{

   const pcap_pkthdr *header = pkt->header;

    const u_char *data = pkt->pkt_data;

   ++m_iCurNo;

  

   packet_index index;

   index.no = m_iCurNo;

   index.pos = m_pfileData->GetPosition();

   index.len = sizeof(pcap_pkthdr) + header->len;

   m_pfileIndex->SeekToEnd();

   m_pfileIndex->Write(&index,sizeof(packet_index));

   m_pfileData->SeekToEnd();

   m_pfileData->Write(header,sizeof(pcap_pkthdr));

   m_pfileData->Write(data,header->len);

   m_pfileIndex->Flush(); // write from memory to disk immediatly

   m_pfileData->Flush();

}

// Get packet

packet * MyWinPcap::GetPacket(int m_iNo)

{

   int iPos = (m_iNo-1)*sizeof(packet_index);

   packet_index pIndex;

   m_pfileIndex->Seek(iPos,CFile::begin);

   m_pfileIndex->Read(&pIndex,sizeof(packet_index));

   m_pfileData->Seek(pIndex.pos,CFile::begin);

   byte *buffer = new byte[pIndex.len];

   m_pfileData->Read(buffer,pIndex.len);

   packet *pkt = new packet();

   pkt->header = (pcap_pkthdr *)buffer;

   pkt->pkt_data = (u_char *)(buffer+sizeof(pcap_pkthdr));

   return pkt;

}

²   增加了版本、作者等信息显示说明,详见请点击“版本信息”按钮

²   优化了界面布局,使其更加的紧促,但又不足之处,例如没有菜单,只有按钮,这尚需要进一步的优化界面布局

实验结论:

通过了近一个月的努力学习与实践运用,终于制作出了一个实现网络嗅探的基本功能的网络嗅探器,较为合理、圆满的完成了本实验的各项实验要求,取得了应有的实验效果。

²  能列出监测主机的所有网卡,并显示在网卡列表框中。

²  能选择其中的一个网卡进行监听,并记录器数据信息

²  能捕获并显示流经网卡的数据包,并做相应的分析和统计

²  能设置捕获过滤规则(按协议类型、端口、地址等,但是仍然不够完善,尚需改进)

²  在TCP、UDP、ARP、ICMP、IGMP等协议都能进行重点分析

²  选择了一种应用层协议如http进行分析

²  能按照协议格式进行格式化显示

²  有可视化操作界面,易于使用

实验体会:(碰到的问题、如何解决、有何体会)

通过自学,亲自动手,一点一滴的积累并实现,完成了一个具备了基本功能的网络嗅探器,受益良多。

Ø  学习了WinPcap开发工具包,对其在网络底层实现和接口运用的方面,有了更加清楚、较为深入的认识与掌握,熟练学会了如何利用WinPcap工具开发上实现网络协议编程

Ø  通过实现了一个基于WinPcap的网络嗅探器,我对网络协议栈有了更加深入的了解与认识,并懂得了基本的网络协议栈的实现与应用,对以后网络学习和网络编程,将会大有裨益。

Ø  通过自己制作网络嗅探器,我对网络嗅探器的开发流程、基本原理和应用领域,有了大体的认识与掌握,知道制作网络嗅探器的基本方法与步骤,并知道如何利用网络嗅探器应用于自己所关心的网络领域。

Ø  通过近一个月的学习、理解、实践、掌握、应用WinPcap和网络嗅探器,我对新知识、新事物的学习、实践与应用的方法与途径,有了更加深入的认识与掌握,能够较为快速的汲取新知识、运用新概念、应用于新领域,这种能力的培养,才是最重要的,也将是对我以后的学习和工作,会产生很好的引导与启发作用。

学生签名:       

期:     2009.10.25           

相关推荐