加载中...
返回

PcapPlusPlus使用记录(一、环境搭建&简单使用)

简介

由于项目的需要,近期产生了一个需求:将一个 pacp 文件解析出来,然后尝试提取每个连接的各种统计数据,例如提取一个完整的TCP会话中的源IP、目的IP、源端口、目的端口、会话开始时间、会话结束时间、发送的数据包数量、发送的数据包总大小等等。

能够实现这一需求的库有很多,如python中的 scapydpkt ,C++中的 PcapPlusPlus 等,考虑到将来可能需要处理较大的 pcap 文件,以及C++相比于python在执行速度上的优势,我决定使用C++作为流量处理的语言;简单翻阅了一下 PcapPlusPlus的文档 ,我认为这个库的易用性能够满足我较低的水平,因此决定先实践一下再说。

预装依赖

从这里开始,我想将 PcapPlusPlus 简称为 PCPP ,方便文章的撰写之用

本文使用的环境是:Win10 + VisualStudio2019

要使用这个库,我们需要先安装一些依赖。

个人建议将这些依赖下载到同一个地方,方便管理!

  • 安装 WinPcap开发者工具Npcap SDK 。下载解压而已,很简单!我这边使用的是WinPcap 。
  • 安装 pthread-win32工具 ,注意这里的链接跟PCPP文档里面的链接是不一样的!文档里面的URL协议是 ftp ,我下载的时候好像打不开的样子,就改为使用 https 了!
  • 可能还需要一个 Microsoft Visual C++ Redistributable 工具,从这里下下来的是个 exe 文件,我在后面的过程中 暂时没有用到 !也就是说我还没运行过这个EXE,先下载下来而已!

下载PcapPlusPlus

直接从 PcapPlusPlus v21.11 页面上把示例代码下载下来!我这边选用的是 windows-vs2019 这个压缩包!

到这一步,算上我们之前下载 并解压 的依赖,文件夹里面应该有这么多东西:

All right?进入刚才下载的VS2019文件夹里面,有个 ExampleProject ,打开之:

没问题的话,就准备运行示例程序了!

运行示例程序

熟悉VS的朋友可能要迫不及待地把那个 .sln 文件给打开了~不要心急!

首先我们应该修改 .props 文件,这个文件是用来指定项目里面的一些属性的;具体地说,其实就是指定刚才下载的几个依赖的路径而已!如果不修改这个文件,贸然打开 .sln ,那必然是要报错的!

最原始的 .props 文件内容如下:

<?xml version="1.0" encoding="utf-8"?> 
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ImportGroup Label="PropertySheets" />
  <PropertyGroup Label="UserMacros">
    <PcapPlusPlusHome>Drive:\your\PcapPlusPlus\folder</PcapPlusPlusHome>
    <PcapSdkHome>Drive:\WpdPack\folder</PcapSdkHome>
    <PThreadWin32Home>Drive:\pthread-win32\folder</PThreadWin32Home>
  </PropertyGroup>
  <PropertyGroup />
  <ItemDefinitionGroup />
  <ItemGroup />
</Project>

看到吗?这个文件指定三个关键路径:

  • PcapPlusPlusHome :就是刚才解压出来的PCPP目录,也就是现在这个 ExampleProject 的上级目录!
  • PcapSdkHome :用于处理 pcap 文件的SDK工具的目录,在 预装依赖 小节里面我们下载了WinPcap,还记得吗?把它的路径写在这里即可!如果你选用的是Npcap,道理也一样~
  • PThreadWin32Home :多线程库!把pthread路径填进去吧 😀

在我的PC上,修改完成之后这个文件差不多是这样:

<?xml version="1.0" encoding="utf-8"?> 
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ImportGroup Label="PropertySheets" />
  <PropertyGroup Label="UserMacros">
    <PcapPlusPlusHome>E:\PcapPlusPlus\pcapplusplus-21.11-windows-vs2019</PcapPlusPlusHome>
    <PcapSdkHome>E:\PcapPlusPlus\WpdPack</PcapSdkHome>
    <PThreadWin32Home>E:\PcapPlusPlus\pthreads-w32-2-9-1-release</PThreadWin32Home>
  </PropertyGroup>
  <PropertyGroup />
  <ItemDefinitionGroup />
  <ItemGroup />
</Project>

之后,就可以打开 .sln 文件了!示例项目即刻出现!

main.cpp 简单使用PcapPlusPlus解析了一下示例项目里面的 1_packet.pcap 文件,这个文件只有一个数据包,程序把源IP和目的IP输出了一下而已!

直接编译运行即可:

简单使用PCPP处理pcap文件

刚才运行的示例未免太简单,很难体现出咱们这个库的潜力!

在这一小节,我希望使用这个库简单处理一下我之前捕获的一个 pcap 文件,里面包含两万多条数据,其实也还不算很大。

先把代码贴出来,再慢慢解释吧~

#include <iostream>
#include <IPv4Layer.h>
#include <Packet.h>
#include <PcapFileDevice.h>
#include <set>
#include <ctime>

int main(int argc, char* argv[])
{
    // Part 1
	// open a pcap file for reading
	pcpp::IFileReaderDevice* reader = pcpp::IFileReaderDevice::getReader("test_file_1.pcap");
	if (!reader)
	{
		std::cerr << "Cannot determine reader for file type" << std::endl;
		return 1;
	}
	if (!reader->open())
	{
		std::cerr << "Cannot open input.pcap for reading" << std::endl;
		return 1;
	}
    // Part 2
	if (!reader->setFilter("tcp and port 80"))
	{
		std::cerr << "Cannot set filter for file reader" << std::endl;
		return 1;
	}
	// Part 3
	pcpp::RawPacket rawPacket;
	std::set<std::string> dstIPSet;
	clock_t BEGIN = clock();
	while (reader->getNextPacket(rawPacket))
	{
		pcpp::Packet parsedPacket(&rawPacket);
		if (parsedPacket.isPacketOfType(pcpp::IPv4))
		{
			pcpp::IPv4Address dstIP = parsedPacket.getLayerOfType<pcpp::IPv4Layer>()->getDstIPv4Address();
			if (dstIPSet.count(dstIP.toString()) == 0)
				dstIPSet.insert(dstIP.toString());
		}
	}
	clock_t END = clock();
	// Part 4
	std::cout << "There are total " << dstIPSet.size() << " destination IP address.\n";
	std::cout << "Total time: " << double(END - BEGIN) / CLK_TCK * 1000 << " ms.\n";
	// Part 5
	reader->close();
	delete reader;

	return 0;
}

根据 参考资料[4] ,我们这次使用的 reader 跟刚才示例代码使用的不太一样,用的是 IFileReaderDevice 里面的 getReader() API,它会根据文件名来为我们返回合适的Reader!代码里面的 Part 1 就是在干这个事情而已,创建一个合适的Reader,然后打开它,准备读取文件了!

紧接着,我为这个Reader设置了一个过滤器。 reader->setFilter("tcp and port 80") 表明我只希望读取协议为TCP的、且端口为 80 的数据包,其它的数据包(如ICMP、UDP等等)我就不关心了。这个 setFilter 在将来的场景里面应该是蛮有用的,它使用的是 Berkeley Packet Filter (BPF) syntax

来到 Part 3 之后,开始分析我们读到的数据。过滤器是TCP协议和 80 端口,其实我们读取的就是发往某个Web服务的请求而已!我用了一个集合 dstIPSet 来记录目的IP,打算待会看看总共有多少不同的目的主机 😹 使用 while 循环来读取数据包,使用 parsedPacket 来解析数据包,然后获取数据包里面的IPv4地址,把它放到集合里面!

Part 3 有个小点缀,就是在循环外面设置了两个 clock_t ,目的是测试一下整个循环要花多长时间!

Part 4 就是我们的输出啦:

Part 5 还是比较重要的,要把劳苦功高的Reader关掉、还要释放它的空间啊!刚开始编写这个程序的时候我给忘了,罪过罪过~由于PCPP的这个 IFileReaderDevice 是动态分配的,如果不把它 delete 掉的话会发生内存泄露呀!

参考资料

[1] Quick Start - Visual Studio - PcapPlusPlus

[2] Build on Windows (VS) - PcapPlusPlus

[3] 《PCAP》第1期(1):PcapPlusPlus示例程序VS2015配置 - 知乎 (zhihu.com)

[4] 2. Read/Write Pcap Files - PcapPlusPlus

9 comments
Anonymous
Markdown is supported
@mpv945
mpv945commentedover 2 years ago

添加图片,如果使用外部图床的http链接 。图片无法点击放大,你那边怎么解决的?

@SGS4ever
SGS4evercommentedover 2 years ago

@mpv945
添加图片,如果使用外部图床的http链接 。图片无法点击放大,你那边怎么解决的?

我的博客没有使用图床,所以没办法帮到你~

@Celetherin
Celetherincommentedover 2 years ago

您好,我也是使用的stack主题,我在照着您的方法添加返回顶部按钮时,遇到了按钮虽然出现、也能够点击,但无法实现实际上的返回顶部功能的问题,我没有任何的代码知识,不知道您有没有解决方法?
另外,也是想提醒一下其他需要这篇教程的朋友,最新版的stack主题,添加返回按钮的组件应该在layouts/partials/sidebar/right.html, 在layouts/_default/single.html中添加代码会导致出现两个右边栏。

@jsjcjsjc
jsjcjsjccommentedabout 2 years ago

请教一下博主,如何优雅的给stack主题添加广告哈?
我只想在左或者右侧边栏底部,或者每篇文章底部添加一个小小的广告,但是默认似乎的满屏广告哈~~
感谢

@SGS4ever
SGS4evercommentedabout 2 years ago
@ClimbingMouse
ClimbingMousecommentedalmost 2 years ago

你好,按照你的方法设置页面载入动画,这个动画不会停止咋办啊

@46fafa
46fafacommentedover 1 year ago

博主你好,请问一下主页布局修改哪里的代码如何作用于整个网页,我发现修改后的布局只存在主页和前两篇文章,其他部分还是没修改的样子

@4kohakunushi
4kohakunushicommentedabout 1 year ago

你好,关于左侧栏图标高亮我这里存在一些问题想请教你。我取消了原本主页直接抓取post的内容在中间显示的版块,这个部分改成了其他东西,与此同时新增了一个抓取post信息的与links、search等目录并列的一个目录,现在的问题是这些部分虽然都能正常显示,但是对应的抓取post的那个目录无法选中以后高亮,应该修改增加什么才能让它也可以选中后高亮呢?

@SGS4ever
SGS4evercommentedabout 1 year ago

首先我只能基于本文使用的Stack版本来尝试解答,因为没看过当前的Stack主题的代码~
我重新翻了下此前写的关于高亮的内容,理论上只要你的post页面的标题在menu配置中即可高亮。如果post页面是你站点的根路径,那应该可以参考我的文章里写的方法,修改下active的触发逻辑~

@4kohakunushi
你好,关于左侧栏图标高亮我这里存在一些问题想请教你。我取消了原本主页直接抓取post的内容在中间显示的版块,这个部分改成了其他东西,与此同时新增了一个抓取post信息的与links、search等目录并列的一个目录,现在的问题是这些部分虽然都能正常显示,但是对应的抓取post的那个目录无法选中以后高亮,应该修改增加什么才能让它也可以选中后高亮呢?

有朋自远方来,不亦说乎?