【初始化 WinPcap】
编写 Sniffer_initCap() 功能函数,通过调用 pcap_findalldevs() 函数获得网卡接口信息来初始化 WinPcap
1 2 3 4 5 6 7 8 9
| int CSnifferDlg::Sniffer_initCap(){ devCount = 0; if (pcap_findalldevs(&alldev, errorBufffer) == -1) return -1; for (dev = alldev; dev; dev = dev->next) devCount++; return 0; }
|
【捕获数据包】
编写 Sniffer_startCap() 功能函数,用于捕获数据包
该函数框架如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| int CSnifferDlg::Sniffer_startCap() { 步骤 1:网卡与过滤器设置 步骤 2:获取选中的网卡接口 步骤 3:打开网卡指定接口 步骤 4:检查是否为非以太网 步骤 5:设置子网掩码 步骤 6:编译过滤器 步骤 7:设置过滤器 步骤 8:设置时间 步骤 9:设置数据包存储路径 步骤 10:创建数据包接收线程 return 1; }
|
网卡与过滤器设置
通过控件的 GetCurSel() 函数获取下拉框的选项来进行网卡与过滤器设置
1 2 3 4 5 6 7 8 9 10 11
| int netCardIndex = this->m_comboBoxNetCard.GetCurSel(); int filterIndex = this->m_comboBoxFilterRule.GetCurSel(); if (netCardIndex == 0 || netCardIndex == CB_ERR) { MessageBox("请选择网卡接口"); return -1; } if (filterIndex == CB_ERR) { MessageBox("过滤器选择错误"); return -1; }
|
获取选中的网卡接口
1 2 3 4
| dev = allDevs; for (int i = 0; i < filterIndex - 1; i++) dev = dev->next;
|
打开网卡指定接口
利用 pcap_open_liive() 函数打开指定网卡接口,若无法打开则释放设备列表
1 2 3 4 5 6 7 8 9 10 11 12
| int dataPackageLen = 65536; int overtime = 1000; int flag = 1;
devHandle = pcap_open_live(dev->name, dataPackageLen, flag, overtime, errorBufffer); if (devHandle == NULL) { MessageBox("无法打开接口:" + CString(dev->description)); pcap_freealldevs(allDevs); return -1; }
|
检查是否为非以太网
利用 pcap_datalink() 方法检查是否为以太网,若为非以太网则释放设备列表
1 2 3 4 5 6
| if (pcap_datalink(devHandle) != DLT_EN10MB) { MessageBox("不适合非以太网的网络"); pcap_freealldevs(allDevs); return -1; }
|
设置子网掩码
1 2 3 4 5 6
| u_int netmask; if (dev->addresses != NULL) netmask = ((struct sockaddr_in *)(dev->addresses->netmask))->sin_addr.S_un.S_addr; else netmask = 0xffffff;
|
编译过滤器
利用 pcap_compile() 方法设置过滤器,若无法设置则释放设备列表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| struct bpf_program fcode; if (filterIndex == 0) { char filter[] = ""; if (pcap_compile(devHandle, &fcode, filter, 1, netmask) < 0) { MessageBox("语法错误,无法编译过滤器"); pcap_freealldevs(allDevs); return -1; } } else { CString str; this->m_comboBoxFilterRule.GetLBText(filterIndex, str); int len = str.GetLength() + 1; char *filter = (char*)malloc(len); for (int i = 0; i < len; i++) filter[i] = str.GetAt(i); if (pcap_compile(devHandle, &fcode, filter, 1, netmask) < 0) { MessageBox("语法错误,无法编译过滤器"); pcap_freealldevs(allDevs); return -1; } }
|
设置过滤器
利用 pcap_setfilter() 方法来设置过滤器,若无法设置则释放设备列表
1 2 3 4 5 6
| if (pcap_setfilter(devHandle, &fcode) < 0) { MessageBox("设置过滤器错误"); pcap_freealldevs(allDevs); return -1; }
|
设置时间
利用 struct tm 与 time_t 类型,获取当前时间,同时利用 strftime() 函数来格式化本地时间
1 2 3 4 5 6 7
| struct tm *localTime; time_t secondTime; time(&secondTime); localTime = localtime(&secondTime); char realTime[30]; strftime(realTime, sizeof(realTime), "%Y%m%d %H%M%S", localTime);
|
设置数据包存储路径
利用 pcap_dump_open() 函数创建一个临时文件,捕获的数据会暂时存放在该临时文件中,在捕获结束后,可选择将此文件存储于指定路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| CFileFind file; if (!file.FindFile("Data")) CreateDirectory("Data", NULL); memset(filePath, 0, sizeof(filePath)); memset(fileName, 0, sizeof(fileName)); strcpy(filePath, "Data\\"); strcat(fileName, realTime); strcat(fileName, ".lix"); strcat(filePath, fileName); dumpFile = pcap_dump_open(catchHandle, filePath); if (dumpFile == NULL){ MessageBox("文件创建错误!"); return -1; }
|
创建数据包接收线程
用 CreateThread() 函数创建接收数据包的线程
1 2 3 4 5 6 7 8 9
| LPDWORD threadCap = NULL; m_ThreadHandle = CreateThread(NULL, 0, Sniffer_capThread, this, 0, threadCap); if (m_ThreadHandle == NULL) { CString str; str.Format("创建线程错误,代码为:%d.", GetLastError()); MessageBox(str); return -1; }
|