压缩的 pcap 数据包索引程序(cpio压缩)
suiw9 2024-11-17 01:40 40 浏览 0 评论
序言
压缩 pcap 数据包索引程序 (cppip) 是一种工具,可以从压缩的 pcap 文件中极快地提取数据包。此工具适用于处理大型 pcap 文件的安全和网络人员。本文提供了该工具的完整讨论,分为两部分。第一部分面向最终用户,将详细解释如何构建和使用该工具。第二部分面向C程序员,涵盖了cppip的内部工作原理。
简介
Cppip 是一个命令行实用程序,旨在非常快速地从大型 pcap 文件中提取数据包,而无需解压缩整个文件。它依赖于使用免费提供的 bgzip 压缩的 pcap 文件,bgzip 是一种向后兼容的 gzip 实用程序,拥有特殊的添加剂——能够快速、廉价地动态解压缩文件的特定区域。如果您使用大型 pcap 文件并需要提取一个或多个数据包以进行后续检查,您会发现 cpip 非常有用。如您所见,准备 pcap 文件以与 cpip 一起使用是一个两步过程,即使用 bgzip 压缩 pcap 文件,然后使用 cpppp 对其进行索引。但在使用 cpppp 之前,您首先必须安装它。
安装
Cppip 与 GNU autoconf 脚本一起分发,旨在让您的生活更轻松。那些熟悉自动配置基架工具的人熟悉用于配置和构建此类软件包的命令序列“./configure && make”。然而,在 cppip 的情况下,核心依赖项之一 tabix 库不会在没有一些干预的情况下将自己整齐地安装在主机操作系统上。因为 tabix 维护者没有使用 GNU 强大的 autoconf 框架,所以在构建和安装 cpip 之前,你必须做一些准备工作。为此,请按照以下简单步骤操作:
- 下载 cppip:Cppip 住在 GitHub,可以在这里找到。
- 下载并构建 tabixtools: 下载最新版本的 tabix 工具包(在撰写本文时为 0.2.6):
- [sb:~]$ curl -O http://superb-dca2.dl.sourceforge.net/project/samtools/tabix/tabix-0.2.6.tar.bz2
- 它包含bgzip实用程序以及libtabix.a,一个简单的静态C库,包含所有bgzip函数。要构建和使用 cppip,您需要两者(bgzip 将用于压缩您的 pcap 文件,并且您需要链接 cpip 工具的库)。解压缩和取消存档后,继续运行“./configure && make”来构建工具和库。不幸的是,tabix 维护者没有在他们的 Makefile 中包含安装目标,因此您不能只运行“make install”并将所有内容存放在您需要的地方。因此,建议您在$PATH的某个地方复制 bgzip,以便于使用(/usr/local/bin 或 /opt/local/bin 可能是不错的选择)。也是因为缺少安装目标,您必须执行以下两个步骤:
- 告诉 cpipp 的配置脚本 libtabix.a 库所在的位置:这里有两个简单的选项:将libtabix.a复制到类似/usr/local/lib的东西,配置脚本可以在其中找到它:
[sb:tabix-0.2.6]$ sudo cp libtabix.a /usr/local/lib
- 或者,如果您没有 root 权限或不打算再次使用 libtabix.a,则可以将构建 libtabix.a 的完全限定路径(通常类似于“tabix-0.2.6”)传递给 cppip 的配置脚本。例如,如果您在 cpip 旁边的目录中构建了 tabixtools,如下所示:
- [sb:cppip]$ ls cppip tabix-0.2.6
- 然后,您将调用类似以下内容的配置:
- [sb:cppip]$ ./configure LDFLAGS=-L/Users/mike/Code/cppip/tabix-0.2.6/
- 通知配置 bgzf.h 的保存位置: 与上面大致相同,如果您打算再次使用 libtabix.a,您可以将其复制到 /usr/local/include 配置可以找到它的位置:
- [sb:tabix-0.2.6]$ sudo cp bgzf.h /usr/local/include
- 否则,您可以传递另一个参数进行配置,以告诉它在哪里可以找到头文件:
- [sb:cppip]$ ./configure CPPFLAGS=-I/Users/mike/Code/cppip/tabix-0.2.6/
- 使用添加的选项调用配置:您可以使用以下内容指示两组标志:
- [sb:cppip]$ ./configure CPPFLAGS=-I/Users/mike/Code/cppip/tabix-0.2.6/ LDFLAGS=-L/Users/mike/Code/cppip/tabix-0.2.6/
- 构建 cppip:现在运行“制作”。
工具:CPPIP
您将使用 cpppp 的第一个正式版本 1.3。在深入了解一些示例之前,让我们首先探索一下使用该工具时可以指定的所有选项,为此,请使用 -h 开关调用 cppip:
[sb:cppip] $ ./src/cppip -h
Compressed Pcap Packet Indexing Program
(c) Cisco Systems 2013, Inc
Mike Schiffman
Fast compressed pcap indexing and extraction, made easy
see http://blogs.cisco.com/tag/cppip for complete documentation
Usage: cppip [options] [file(s)...]
Indexing:
-i index_mode:index_level index.cppip pcap.gz
index a bgzip compressed pcap.gz file using `index_mode`
index.cppip will be created or overwritten and packets
will be indexed at every `index_level` mark.
invoke with -I for more information/help on indexing
-I print supported index/extract modes/format guidelines
-v index.cppip verify index file
-d index.cppip dump index file
Extracting:
-e index_mode:n|n-m index.cppip pcap.gz new.pcap
extract using `index_mode` the nth packet or n-m packets
from pcap.gz into new.pcap
invoke with -I for more information/help on extracting
-f enable fuzzy matching (timestamp extraction only)
General Options:
-D enable debug messages
-V program version
-h this message
让我们谈谈一些主要选项:
- -i (索引)通常,这是第一步 — 您将为每个 pcap 创建一个索引文件.gz
- -e (摘录)当您要从 pcap 中提取一个或多个数据包时,使用此模式.gz
- -I (打印模式)此选项显示支持的索引模式
- -v (验证)此选项用于验证索引文件是否已正确生成、检查其版本以及查看它有多少条记录
- -d (转储)此选项转储整个索引文件
- -f(模糊匹配)此选项允许在时间戳模式下提取时进行模糊匹配(稍后会详细介绍)
- -D (调试)启用调试消息
压缩 pcap
首先要做的事。我们需要使用 bgzip 压缩您的 pcap 文件。 在以下示例中,为了获取有关 pcap 文件(压缩或非压缩)内内容的信息,我们将使用 Wireshark 的 capinfos 工具。对于以下所有示例,我们将使用包含超过 7.5M 数据包的 5GB pcap 文件:
[sb:cppip]$ ls -l *.pcap
-rw-r--r-- 1 mike staff 2000000101 Apr 19 20:43 pktdump.pcap
[sb:cppip]$ capinfos -cuae pktdump.pcap.gz
File name: pktdump.pcap.gz
Number of packets: 7552072
Capture duration: 411 seconds
Start time: Fri Apr 19 16:56:44 2013
End time: Fri Apr 19 17:03:35 2013
作为参考,您会注意到 pcap 使用普通的旧 gzip 压缩到大约 892M:
[sb:cppip]$ ls -l *.pcap*
-rw-r--r-- 1 mike staff 838087510 Apr 19 20:43 pktdump.pcap.gz
使用 bgzip 压缩文件会带来一些开销,在我们的例子中,在 7M 时只有大约 838%:
[sb:cppip]$ bgzip pktdump.pcap
[sb:cppip]$ ls -l *.pcap*
-rw-r--r-- 1 mike staff 892089319 Apr 19 20:43 pktdump.pcap.gz
数据包索引 压缩文件
后,需要使用 cpppp 对其进行索引。编制索引时,cppip 将创建一个配套文件,其中包含 pcap.gz 中数据包的 bgzip 偏移量。换句话说,索引文件将保存位于压缩 pcap 中的数据包的地址。这些地址随后将用于稍后快速提取数据包。
目前,cppip 支持两种索引模式:数据包编号和时间戳。数据包编号模式通过数据包在 pcap 文件中的序号位置对数据包进行索引,而时间戳模式则通过数据包的 pcap 标头时间戳为数据包编制索引。决定使用哪种模式来构建索引将与您期望如何提取数据包有关。我们将在接下来的几节中了解有关两者的更多信息。
确定索引模式后,需要选择索引级别。这是一个值,指示 cppip 将存储地址的数据包数。在理想情况下,您可以选择尽可能小的索引级别,并在某些情况下存储每个数据包的地址,并具有近乎即时的查找。这也会导致索引文件非常大。实际上,索引级别将是一个较大的值,可在索引文件大小和查找速度之间提供良好的平衡。要查看 cpip 期望如何指定索引级别,请使用 -I 选项调用 cppip:
[sb:cppip] $ ./src/cppip -I
pkt-num: index_level should be a single integer from:
1 - (total number of packets - 1)
To index every 1000 packets: -i pkt-num:1000
timestamp: index_level should be a number indicating the index
followed by a time range specifier which can be one of
following:
d - days
h - hours
m - minutes
s - seconds
To index every 100 seconds: -i timestamp:100s
通过数据包编号进行数据包索引 选择数据包编号
索引级别时,需要考虑 pcap 中的数据包数量.gz并确定哪个更重要:磁盘空间或执行速度。较小的索引级别转换为更多的数据包被索引,并导致更大的索引文件。对于具有大量数据包的 pcap 文件,这将导致一个非常大的索引文件。这样做的好处是寻道时间越快,因为索引越细,平均而言,cppip 就越接近您的目标提取(我们很快就会看到这一点)。如果您选择尽可能小的索引级别 1,则告诉 cppip “请将每个数据包的地址存储在我的索引文件中”,它将尽职尽责地为 pcap 中的每个数据包写入索引记录。这将导致尽可能大的索引文件和尽可能快的提取,因为 cpip 将知道每个数据包的地址,并可以直接查找包含所需数据包的 BGZF 偏移量的索引记录。在实践中,您可能希望选择在索引文件大小方面提供平衡的东西。
在以下示例中,我们将使用合理的索引级别 1,000 为 pcap.gz 文件编制索引,这将生成 120K 的索引文件:
[sb:cppip]$ ./src/cppip -i pkt-num:1000 index-pn-1000.cppip pktdump.pcap.gz
indexing pktdump.pcap.gz...
wrote 7552072 records to index-pn-01.cppip
[sb:cppip]$ ls -l index-pn-1000.cppip
-rw-r--r-- 1 mike staff 120876 Apr 15 12:03 index-pn-1000.cppip
通过数据包编号
提取数据包 现在您已经构建了索引文件,您实际上可以完成一些工作了!假设您迫切需要来自该 pcap.gz 内部的数据包 3,480,123 到 4,080,012。下面的信息图描述了这个典型的工作流方案:
- Cppip 在索引文件中查询:使用指定的数据包范围,cppip 在索引文件内部查找起始数据包的最近 BGZF 偏移量。如果 cpppip 足够幸运地直接登陆数据包索引,它将知道您想要的数据包范围在 pcap.gz 中开始的确切地址。如果没有,就像上面的情况一样,它将尽可能接近。这是有效的,因为数据包以顺序、单调递增的方式存储。因此,cppip 知道数据包编号 3,473,920 是它知道所需起始数据包 3,480,123 的地址的最接近的前置邻居。
- Cppip 索引直接到 pcap.gz:使用从索引文件查询中获得的 BGZF 偏移量,cpip 将直接在 pcap 中查找该地址.gz并进行线性搜索以查找所需的起始数据包。
- Cppip 将数据包写入 new.pcap:找到起始数据包后,cppip 将复制原始的 24 字节 pcap 文件头,然后将指定范围内的每个数据包写入 new.pcap。
让我们看看这在命令行上是什么样子的,这样你就知道这需要多长时间,让我们计时:
[sb:cppip] $ time ./src/cppip -e pkt-num:3480123-4080012 index-pn-1000.cppip pktdump.pcap.gz new.pcap
wrote 599890 packets to new.pcap
1.42 real 0.56 user 0.84 sys
甜。在我公认的速度很快的MacBook Pro上使用每7,552个数据包记录的数据包编号索引文件,cppip花了不到一秒半的时间来定位,读取和写入近600,000个数据包。为了更好地衡量,让我们检查一下cppip的工作:
[sb:cppip] $ capinfos -c new.pcap
File name: new.pcap
Number of packets: 599890
看起来不错!使用数据包编号索引,cppip 可以从压缩的 pcap 文件中提取单个数据包或一系列数据包。接下来,我们将继续介绍 cpipp 的时间戳索引和提取功能。
通过时间戳进行数据包索引 时间戳
索引根据数据包在 pcap 文件中的捕获时间戳对数据包进行索引。Cppip 将根据数据包到达 pcap.gz 文件的时间而不是它们在文件中的相对位置来对数据包进行密钥。虽然数据包时间戳几乎总是会增加,但我们不能依赖它们单调地这样做。选择时间戳索引级别时,需要了解捕获文件的持续时间。
目前,从版本 1.3 开始,可以为时间戳索引级别选择的最小值为 1 秒。让我们看一下基于时间戳的索引和提取的标准工作流程:
由于我们知道 pcap.gz 文件跨越相对较短的 411 秒时间范围,让我们使用 1 秒的最小索引级别创建一个索引文件,这将产生一个包含 411 条记录的微小索引文件:
[sb:cppip]$ ./src/cppip -i timestamp:1s index-ts-1s.cppip pktdump.pcap.gz
indexing ../pktdump.pcap.gz...
wrote 411 records to index-ts-1s.cppip
[sb:cppip]$ ls -l index-ts-1s.cppip
-rw-r--r-- 1 mike staff 9920 Apr 20 16:21 index-ts-1s.cppip
通过时间戳提取数据包
虽然无法为数据包索引指定微秒分辨率,但可以选择提取。您可以指定带或不带微秒的时间戳:
- 以微秒为单位:YYYY-MM-DD:HH:MM:SS.uuuuuu
- 无微秒: YYYY-MM-DD:HH:MM:SS
让我们来看看另一个典型的 cppip 用例。在这种情况下,您的坚定的思科 IPS 已通知您当地时间下午 5:00 发生了一次闯入尝试。内部取证团队需要从下午 4:59 到下午 5:02 的所有网络流量。由于您之前已设置了一个 bgzip 压缩和索引所有外围 pcap 文件的自动化过程,因此您已准备好处理此请求。让我们抓取事件发生前一分钟和事件发生后两分钟的所有数据包:
此操作的命令行如下所示:
[sb:cppip] $ ./src/cppip -e timestamp:2012-10-07:16:59:00-2012-10-07:17:02:00 index-ts:1s pktdump_20121008000335.pcap.gz new2.pcap
extracting from pktdump.pcap.gz using index-ts:1s...
extract(): 2013-04-19 16:59:00.000000 not found, closest is 2013-04-19 16:59:00.000102 (try -f)
wrote 0 packets to new2.pcap.
这里发生了什么?显然,我们没有为 cpppp 指定一个特定的足够时间戳来匹配相应的起始数据包。要解决此问题,您有两种选择:
- 指定特定时间戳:Cppip 很好心地告诉您与您的请求最接近的匹配时间戳,因此您可以使用该时间戳。但是,您可能会遇到关闭时间戳的相同问题(但是,这是捕获从开始时间戳到pcap.gz结束的所有数据包的有用方法)。
- 使用模糊匹配:有了这个方便的选项,cppip 将查找指定的时间戳,但如果找不到它,cpip 将在最接近命令行指定的时间戳上开始和停止匹配。让我们试试看。
[sb:cppip] $ ./src/cppip -f -e timestamp:2012-10-07:16:59:00-2012-10-07:17:02:00 index-ts:1s pktdump_20121008000335.pcap.gz new2.pcap
extracting from pktdump_20121008000335.pcap.gz using index-ts:1s...
start ts: 2012-10-07 16:59:00.000000 not found, instead fuzzy matched on 2012-10-07 16:59:00.000102
stop ts: 2012-10-07 17:02:00.000000 not found, instead fuzzy matched on 2012-10-07 17:02:00.000046
wrote 3461342 packets to new2.pcap.
棒!您已经拿到了数据包,是时候进行一些取证分析了。
最后,让我们探讨一下 cppip 的一些诊断功能。
数据包验证和索引转储
Cppip 提供了一些诊断功能,让您有机会查看索引文件以确保其有效性并浏览其内容。第一个是验证索引文件并显示其一些元数据的简单命令:
[sb:cppip] mike% ./src/cppip -v index-pn-1000.cppip
valid cppip index file
version: 1.3
created: 2013-04-19 20:03:17.463926
packets in pcap:7552072
indexing mode: packet-number
index level: 1000
record count: 7552
我们看到我们的索引文件几乎符合预期。这里的一个要点是确保您使用的索引文件的版本与 cpppp 的版本一致。我可以保证我会尝试使未来的版本向后兼容,但与所有事情一样,您的里程可能会有所不同。
cppip 公开的另一个漂亮的诊断功能是转储索引文件内容的选项。如果您想查看数据包在 pcap 中的物理布局方式,这将非常有用.gz:
[sjc-vpn5-288:~/Code/cppip/cppip] mike% ./src/cppip -d index-pn-1000.cppip |& more
valid cppip index file
version: 1.3
created: 2013-04-19 20:03:17.463926
packets in pcap:7552072
indexing mode: packet-number
index level: 1000
record count: 7552
pkt num:1000
offset: 153b9d4c5
pkt num:2000
offset: 30e3bae9f
pkt num:3000
offset: 4dadb7482
pkt num:4000
...
用户手册到此结束,所以让我们继续看看cppip是如何做到的。
正如我过去所做的那样,在我发布代码的所有技术博客中,我喜欢选择一些关键的代码块并讨论它。那么cppip是如何做到的呢?让我们来了解一下!我们将深入了解索引文件头、索引记录和一些用于提取索引的函数。
数据包编号索引记录 由于我们将探索数据包编号模式的索引和提取过程,因此我们最好先查看数据包编号索引记录
。如您所料,这是一个非常简单的结构。它有一个无符号的 32 位计数器用于数据包编号,并在 pcap 中有一个 64 位地址.gz:
/*
* Packet Number Index Record:
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Packet Number |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Virtual BGZF Virtual Record Locator |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
struct cppip_record_pn
{
uint32_t pkt_num; /** the packet number */
uint64_t bgzf_offset; /** its offset into bgzf file */
};
typedef struct cppip_record_pn cppip_record_pn_t;
#define CPPIP_REC_PN_SIZ sizeof(struct cppip_record_pn)
数据包编号索引 下一个块是用于构建索引
文件的主事件循环。你会注意到 cpipp 做的第一件事是获取文件指针的当前地址到 pcap.gz。未显示的是已经读取并写出 pcap 文件头的代码块,因此对于循环的第一次迭代,对 bgzf_tell() 的调用将反映 cppip 已经读取这些字节的事实。在读取数据包并确保它没有遇到错误或文件末尾后,cppip 会检查它是否在 pcap 中获得了第一个数据包,或者(通过模运算符)一个是索引级别的倍数。如果任一状态为 true,cppip 将写入数据包编号、偏移量到索引文件,并增加几个计数器。如果启用了调试,您将收到一条很好的消息,通知您刚刚发生的事情。下一个块只是跳过数据包的内容——cppip 在索引时不关心它们。此过程将重复,直到遇到错误或 cpip 到达 pcap.gz 的末尾。
for (rec_cnt = 0, pkt_cnt = 1, done = 0; !done; pkt_cnt++)
{
/** ...[pcap packet header][packet]...
* ^
* bgzf fp is pointing here, the BGZF offset to this
* packet.. This is
* the offset we will record in our index
*/
offset = bgzf_tell(c->pcap);
switch (bgzf_read(c->pcap, buf, PCAP_PKTH_SIZ))
{
case -1:
snprintf(c->errbuf, BUFSIZ, "bgzf_read() error\n");
return (-1);
case 0:
/* all done */
done = 1;
break;
default:
pcap_h = (pcap_offline_pkthdr_t *)buf;
/** write first packet then write as per index_level */
if (pkt_cnt == 1 || pkt_cnt % c->index_level.num == 0)
{
cppip_rec.pkt_num = pkt_cnt;
cppip_rec.bgzf_offset = offset;
if (write(c->index, &cppip_rec, CPPIP_REC_PN_SIZ) == -1)
{
snprintf(c->errbuf, BUFSIZ, "write(): %s",
strerror(errno));
return (-1);
}
rec_cnt++;
if (c->flags & CPPIP_CTRL_DEBUG)
{
fprintf(stderr, "DBG: add> [%d]: %d @ %llx\n",
rec_cnt, pkt_cnt, offset);
}
}
/**
* we don't care about the contents -- we skip past the
* packet
*/
if (bgzf_skip(c->pcap, pcap_h->caplen) == -1)
{
snprintf(c->errbuf, BUFSIZ, "bgzf_skip() error\n");
return (-1);
}
}
}
数据包编号提取 提取
逻辑负责获取数据包。
让我们看看它是如何工作的。
首先,cppip 希望确保您没有在命令行上搞砸,并指定一个超过 pcap.gz 中数据包总数的停止数据包。如果您的输入通过了该测试,cppip 将自行设置为查找起始数据包。
如果起始数据包小于索引级别,cppip 将从第一个数据包发出线性搜索,直到到达指定的起始数据包。如果起始数据包大于索引级别,cppip 会将第一个数据包除以索引级别以获得最接近的索引记录,然后 lseek() 到索引文件中的该位置。
接下来,cppip 读取该记录,在 pcap.gz 中寻找适当的位置,然后再次执行线性搜索,直到找到起始数据包。然后,Cppip 下降到提取循环中,读取 pcap 标头以获取数据包捕获长度,然后读取数据包本身。然后,它将 pcap 标头和数据包复制到内存缓冲区,并将该缓冲区写入新的 pcap 文件。Cppip 继续此过程,直到它命中停止数据包或遇到错误。
/** sanity check only checks stop, we verified earlier stop > start */
if (c->e_pkts.pkt_stop > c->cppip_h.pkt_cnt)
{
snprintf(c->errbuf, BUFSIZ,
"extraction would exceed packet count, %d and/or %d > %d\n",
c->e_pkts.pkt_start, c->e_pkts.pkt_stop, c->cppip_h.pkt_cnt);
return (-1);
}
/**
* We need to locate the offset of pkt_start and then we can
* extract in a linear fashion until we hit pkt_last.
*
* If the indexing is too coarse the pkt_start will lie before the
* first index. If this is the case we have to do a linear search from
* the very first packet until we find pkt_first...
*/
if (c->e_pkts.pkt_start < c->cppip_index_pn_hdr.index_level)
{
if (linear_search(c, 1, c->e_pkts.pkt_start) == -1)
{
return (-1);
}
}
/** seek to index, obtain closest offset, linear search from there */
else
{
/**
* pkt_start / index_level will give us the closest index record to our
* starting packet. We lseek to 1 before this location so we don't
* step past the record we need.
*/
if (lseek(c->index,
(((c->e_pkts.pkt_start / c->cppip_index_pn_hdr.index_level) - 1)
* CPPIP_REC_PN_SIZ) + CPPIP_FH_SIZ + CPPIP_INDEX_PN_H_SIZ,
SEEK_SET) == -1)
{
snprintf(c->errbuf, BUFSIZ, "lseek() error: %s\n", strerror(errno));
return (-1);
}
if (read(c->index, (cppip_record_pn_t *)&rec, CPPIP_REC_PN_SIZ)
!= CPPIP_REC_PN_SIZ)
{
snprintf(c->errbuf, BUFSIZ, "read() error: %s\n", strerror(errno));
return (-1);
}
if (bgzf_seek(c->pcap, rec.bgzf_offset, SEEK_SET) == -1)
{
snprintf(c->errbuf, BUFSIZ, "bgzf_seek() error.\n");
return (-1);
}
if (linear_search(c, rec.pkt_num, c->e_pkts.pkt_start) == -1)
{
return (-1);
}
}
/** we've got pkt_first, do extraction until we hit pkt_last */
for (c->e_pkts.pkts_w = 0, i = c->e_pkts.pkt_start;
i < (c->e_pkts.pkt_stop + 1); i++, c->e_pkts.pkts_w++)
{
if (bgzf_read(c->pcap, (pcap_offline_pkthdr_t *)&pcap_h, PCAP_PKTH_SIZ)
!= PCAP_PKTH_SIZ)
{
snprintf(c->errbuf, BUFSIZ,
"bgzf_read() error: cant read pcap hdr\n");
return (-1);
}
pkt_caplen = pcap_h.caplen;
if (bgzf_read(c->pcap, buf, pkt_caplen) != pkt_caplen)
{
snprintf(c->errbuf, BUFSIZ,
"bgzf_read() error: can't read packet\n");
return (-1);
}
memcpy(&buf2, &pcap_h, PCAP_PKTH_SIZ);
memcpy(&buf2[PCAP_PKTH_SIZ], &buf, pkt_caplen);
if (write(c->pcap_new, buf2, PCAP_PKTH_SIZ + pkt_caplen) !=
PCAP_PKTH_SIZ + pkt_caplen)
{
snprintf(c->errbuf, BUFSIZ, "write() error: %s\n", strerror(errno));
return (-1);
}
}
return (1);
结论与未来
在本文中,您了解了压缩 pcap 数据包索引和提取 (cpppip) 的最新热潮。我们探讨了如何安装和使用该工具,并偷看了它的一些内部结构。将来,我计划进行相当数量的代码清理和优化。我还计划在文件头中添加微秒级时间戳索引、字节序信息、创建 C 库,可能还有一些基于协议的新索引方法。一如既往,欢迎拉取请求。感谢您抽出宝贵时间,请随时发表评论!
地址:https://blogs.cisco.com/security/tools-of-the-trade-the-compressed-pcap-packet-indexing-program
相关推荐
- 5款Syslog集中系统日志常用工具对比推荐
-
一、为何要集中管理Syslog?Syslog由Linux/Unix系统及其他网络设备生成,广泛分布于整个网络。因其包含关键信息,可用于识别网络中的恶意活动,所以必须对其进行持续监控。将Sys...
- 跨平台、多数据库支持的开源数据库管理工具——DBeaver
-
简介今天给大家推荐一个开源的数据库管理工具——DBeaver。它支持多种数据库系统,包括Mysql、Oracle、PostgreSQL、SLQLite、SQLServer等。DBeaver的界面友好...
- 强烈推荐!数据库管理工具:Navicat Premium 16.3.2 (64位)
-
NavicatPremium,一款集数据迁移、数据库管理、SQL/查询编辑、智能设计、高效协作于一体的全能数据库开发工具。无论你是MySQL、MariaDB、MongoDB、SQLServer、O...
- 3 年 Java 程序员还玩不转 MongoDB,网友:失望
-
一、什么场景使用MongoDB?...
- 拯救MongoDB管理员的GUI工具大赏:从菜鸟到极客的生存指南
-
作为一名在NoSQL丛林中披荆斩棘的数据猎人,没有比GUI工具更称手的瑞士军刀了。本文将带你围观五款主流MongoDB管理神器的特性与暗坑,附赠精准到扎心的吐槽指南一、MongoDBCompass:...
- mongodb/redis/neo4j 如何自己打造一个 web 数据库可视化客户端?
-
前言最近在做neo4j相关的同步处理,因为产线的可视化工具短暂不可用,发现写起来各种脚本非常麻烦。...
- solidworks使用心得,纯干货!建议大家收藏
-
SolidWorks常见问题...
- 统一规约-关乎数字化的真正实现(规范统一性)
-
尽管数字化转型的浪潮如此深入人心,但是,对于OPCUA和TSN的了解却又甚少,这难免让人质疑其可实现性,因为,如果缺乏统一的语义互操作规范,以及更为具有广泛适用的网络与通信,则数字化实际上几乎难以具...
- Elasticsearch节点角色配置详解(Node)
-
本篇文章将介绍如下内容:节点角色简介...
- 产前母婴用品分享 篇一:我的母婴购物清单及单品推荐
-
作者:DaisyH8746在张大妈上已经混迹很久了,有事没事看看“什么值得买”已渐渐成了一种生活习惯,然而却从来没有想过自己要写篇文章发布上来,直到由于我产前功课做得“太过认真”(认真到都有点过了,...
- 比任何人都光彩照人的假期!水润、紧致的肌肤护理程序
-
图片来源:谜尚愉快的假期临近了。身心振奋的休假季节。但是不能因为这种心情而失去珍贵的东西,那就是皮肤健康。炙热的阳光和强烈的紫外线是使我们皮肤老化的主犯。因此,如果怀着快乐的心情对皮肤置之不理,就会使...
- Arm发布Armv9边缘AI计算平台,支持运行超10亿参数端侧AI模型
-
中关村在线2月27日消息,Arm正式发布Armv9边缘人工智能(AI)计算平台。据悉,该平台以全新的ArmCortex-A320CPU和领先的边缘AI加速器ArmEthos-U85NPU为核心...
- 柔性——面向大规模定制生产的数字化实现的基本特征
-
大规模定制生产模式的核心是柔性,尤其是体现在其对定制的要求方面。既然是定制,并且是大规模的定制,对于制造系统的柔性以及借助于数字化手段实现的柔性,就提出了更高的要求。面向大规模定制生产的数字化业务管控...
- 创建PLC内部标准——企业前进的道路
-
作者:FrankBurger...
- 标准化编程之 ----------- 西门子LPMLV30测试总结
-
PackML乃是由OMAC开发且被ISA所采用的自动化标准TR88.00.02,能够更为便捷地传输与检索一致的机器数据。PackML的主要宗旨在于于整个工厂车间倡导通用的“外观和感觉”,...
你 发表评论:
欢迎- 一周热门
-
-
Linux:Ubuntu22.04上安装python3.11,简单易上手
-
宝马阿布达比分公司推出独特M4升级套件,整套升级约在20万
-
MATLAB中图片保存的五种方法(一)(matlab中保存图片命令)
-
别再傻傻搞不清楚Workstation Player和Workstation Pro的区别了
-
Linux上使用tinyproxy快速搭建HTTP/HTTPS代理器
-
如何提取、修改、强刷A卡bios a卡刷bios工具
-
Element Plus 的 Dialog 组件实现点击遮罩层不关闭对话框
-
日本组合“岚”将于2020年12月31日停止团体活动
-
SpringCloud OpenFeign 使用 okhttp 发送 HTTP 请求与 HTTP/2 探索
-
tinymce 号称富文本编辑器世界第一,大家同意么?
-
- 最近发表
-
- 5款Syslog集中系统日志常用工具对比推荐
- 跨平台、多数据库支持的开源数据库管理工具——DBeaver
- 强烈推荐!数据库管理工具:Navicat Premium 16.3.2 (64位)
- 3 年 Java 程序员还玩不转 MongoDB,网友:失望
- 拯救MongoDB管理员的GUI工具大赏:从菜鸟到极客的生存指南
- mongodb/redis/neo4j 如何自己打造一个 web 数据库可视化客户端?
- solidworks使用心得,纯干货!建议大家收藏
- 统一规约-关乎数字化的真正实现(规范统一性)
- Elasticsearch节点角色配置详解(Node)
- 产前母婴用品分享 篇一:我的母婴购物清单及单品推荐
- 标签列表
-
- dialog.js (57)
- importnew (44)
- windows93网页版 (44)
- yii2框架的优缺点 (45)
- tinyeditor (45)
- qt5.5 (60)
- windowsserver2016镜像下载 (52)
- okhttputils (51)
- android-gif-drawable (53)
- 时间轴插件 (56)
- docker systemd (65)
- slider.js (47)
- android webview缓存 (46)
- pagination.js (59)
- loadjs (62)
- openssl1.0.2 (48)
- velocity模板引擎 (48)
- pcre library (47)
- zabbix微信报警脚本 (63)
- jnetpcap (49)
- pdfrenderer (43)
- fastutil (48)
- uinavigationcontroller (53)
- bitbucket.org (44)
- python websocket-client (47)