使用libpcap tcpdump wireshark抓包

作者

QQ群:852283276
微信:arm80x86
微信公众号:青儿创客基地
B站:主页 https://space.bilibili.com/208826118

参考

tcpdump & libpcap官网
使用PCAP获取数据包纳秒(ns)级精度的时间戳(timestamp)
tcpdump/libpcap中捕获数据包的时间戳
基于libpcap多网卡抓包编程心得
在LINUX系统下使用libpcap,一些流程
Python-对Pcap文件进行处理,获取指定TCP流
PCAP文件格式分析(做抓包软件之必备)
tcpdump使用方法总结

pcap文件格式

pcap文件包含两个部分,pcap文件头和pcap数据,每一包数据都包含包头和码流数据,如下图所示,
130

pcap文件头24B各字段说明

  • Magic:4B:0x1A 2B 3C 4D:用来标示文件的开始
  • Major:2B,0x02 00:当前文件主要的版本号
  • Minor:2B,0x04 00当前文件次要的版本号
  • ThisZone:4B当地的标准时间;全零
  • SigFigs:4B时间戳的精度;全零
  • SnapLen:4B最大的存储长度
  • LinkType:4B链路类型

常用类型:

  • 0 BSD loopback devices, except for later OpenBSD
  • 1 Ethernet, and Linux loopback devices
  • 6 802.5 Token Ring
  • 7 ARCnet
  • 8 SLIP
  • 9 PPP
  • 10 FDDI
  • 100 LLC/SNAP-encapsulated ATM
  • 101 “raw IP”, with no link
  • 102 BSD/OS SLIP
  • 103 BSD/OS PPP
  • 104 Cisco HDLC
  • 105 802.11
  • 108 later OpenBSD loopback devices (with the AF_value in network byte order)
  • 113 special Linux “cooked” capture
  • 114 LocalTalk

Packet 包头和Packet数据组成

字段说明:

字段说明
Timestamp 4B时间戳高位,精确到seconds
Timestamp 4B时间戳低位,精确到microseconds或nanoseconds
Caplen 4B当前数据区的长度,即抓取到的数据帧长度,由此可以得到下一个数据帧的位置
Len 4B离线数据长度,即网络中实际数据帧的长度,一般不大于caplen,多数情况下和Caplen数值相等
Packet n*BPacket(通常就是链路层的数据帧)具体内容,长度就是Caplen,这个长度的后面,就是当前PCAP文件中存放的下一个Packet数据包,PCAP文件里面并没有规定捕获的Packet数据包之间有什么间隔字符串,下一组数据在文件中的起始位置,我们需要靠第一个Packet包确定

tcpdump使用

ubuntu

$ sudo apt install tcpdump
$ sudo apt install libpcap-dev

编译

先编译libpcap,这里交叉编译,用于arm平台,

./configure --host=arm-xilinx-linux-gnueabi --prefix=$cur_path/zynq-$PETALINUX_VER

同样方法,交叉编译tcpdump,可以自动发现libpcap,采用静态编译的库,可直接拷贝到板卡运行,

...
checking for local pcap library... ../libpcap-1.9.0/libpcap.a
checking for pcap-config... ../libpcap-1.9.0/pcap-config
...

wireshark

wireshark命名管道实现捕获
嵌入式设备端的网络报文在wireshark显示
通过串口抓取设备端网络报文,然后显示在wireshark中

包格式

pcap文件的包格式,caplen为捕获到长度,len为数据包原始长度,也就是说caplen可能比len小,struct timeval在这里长度为64字节。

/*
 * Generic per-packet information, as supplied by libpcap.
 *
 * The time stamp can and should be a "struct timeval", regardless of
 * whether your system supports 32-bit tv_sec in "struct timeval",
 * 64-bit tv_sec in "struct timeval", or both if it supports both 32-bit
 * and 64-bit applications.  The on-disk format of savefiles uses 32-bit
 * tv_sec (and tv_usec); this structure is irrelevant to that.  32-bit
 * and 64-bit versions of libpcap, even if they're on the same platform,
 * should supply the appropriate version of "struct timeval", even if
 * that's not what the underlying packet capture mechanism supplies.
 */
struct pcap_pkthdr {
	struct timeval ts;	/* time stamp */
	bpf_u_int32 caplen;	/* length of portion present */
	bpf_u_int32 len;	/* length this packet (off wire) */
};

libpcap-1.9.0tcpdump-4.9.2支持设置时间精度为毫秒或者纳秒,左边毫秒,右边纳秒,
181
代码,

// libpcap-1.9.0\pcap\pcap.h line404
/*
 * Time stamp resolution types.
 * Not all systems and interfaces will necessarily support all of these
 * resolutions when doing live captures; all of them can be requested
 * when reading a savefile.
 */
#define PCAP_TSTAMP_PRECISION_MICRO	0	/* use timestamps with microsecond precision, default */
#define PCAP_TSTAMP_PRECISION_NANO	1	/* use timestamps with nanosecond precision */

// tcpdump-4.9.2\tcpdump.c line945
static pcap_t *
open_interface(const char *device, netdissect_options *ndo, char *ebuf)
{
...
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
	status = pcap_set_tstamp_precision(pc, ndo->ndo_tstamp_precision);
	if (status != 0)
		error("%s: Can't set %ssecond time stamp precision: %s",
			device,
			tstamp_precision_to_string(ndo->ndo_tstamp_precision),
			pcap_statustostr(status));
#endif
...
}
// tcpdump-4.9.2\tcpdump.c line1495 main
#ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
		case OPTION_TSTAMP_PRECISION:
			ndo->ndo_tstamp_precision = tstamp_precision_from_string(optarg);
			if (ndo->ndo_tstamp_precision < 0)
				error("unsupported time stamp precision");
			break;
#endif

遍历网卡

代码,

	char errbuf[PCAP_ERRBUF_SIZE];//存放错误信息的缓冲
	pcap_if_t *it;
	int r;
	
	r=pcap_findalldevs(&it,errbuf);
 	if(r < 0) {
	  printf("err:%s\n",errbuf);
	  return r;
	}
	
	while(it) {
	  printf(":%s\n",it->name);
	  it=it->next;
	}

	pcap_freealldevs(it);

其中pcap_if_tname成员用于pcap_open_live函数,

/*
 * Item in a list of interfaces.
 */
struct pcap_if {
	struct pcap_if *next;
	char *name;		/* name to hand to "pcap_open_live()" */
	char *description;	/* textual description of interface, or NULL */
	struct pcap_addr *addresses;
	bpf_u_int32 flags;	/* PCAP_IF_ interface flags */
};

过滤

只抓数据部分:src host 192.168.6.6 and src port 8080 and tcp[tcpflags] & (tcp-push) != 0

int pcap_compile(pcap_t *p, struct bpf_program *fp,char *str, int optimize, bpf_u_int32 netmask)

字符串str是过滤参数,program参数是一个指向bpf_program结构体的指针,optimize参数用于控制是否采用最优化的结果,netmask用于指定IPv4的网络子网掩码,这个参数仅仅在检查过滤程序中的IPv4广播地址时才会使用。

struct bpf_program filter;
pcap_compile(fip->nic, &filter, fip->filter, 1, 0);
pcap_setfilter(fip->nic, &filter);

只抓取网卡接收到的包,不抓取发出去的包,0xac是本机的mac地址,过滤源mac地址不等于0xac就达到效果了。

$ sudo tcpdump -i enp1s0 -v "ether[6] != 0xac" -w a.pcap

抓取报文后隔指定的时间保存一次,

  • G 选项后面接时间,单位为秒
  • Z (大写) 表示下面的新文件也是用root权限来执行的
  • w 抓包的名字以时间戳命名 %Y_%m%d_%H%M_%S.cap
  • s 指定数据包截断的长度,0表示不截断,tcpdump默认截断68字节
$ sudo tcpdump -s 0 -G 60 -Z root -w %Y_%m%d_%H%M_%S.cap

抓取报文后达到指定的大小保存一次,

  • C(大写)表示每当文件达到指定大小时进行重新保存一个新文件,单位是MB(1 000 000 B)
  • Z (大写) 表示下面的新文件也是用root权限来执行的,如果用 - C 时必须配合-Z(大写Z)
  • w 直接将分组写入文件中
  • W 限制文件的个数,达到个数后开始从最早的文件覆盖
$ sudo tcpdump -s 0 -C 1 -Z root -W 1 -w test.cap
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值