构建tcpdump/wireshark pcap文件

 pcap文件格式是bpf保存原始数据包的格式,很多软件都在使用,比如tcpdump、wireshark等等,了解pcap格式可以加深对原始数据包的了解,自己也可以手工构造任意的数据包进行测试。

 
pcap文件的格式为:
  文件头    24字节
  数据包头 + 数据包  数据包头为16字节,后面紧跟数据包
  数据包头 + 数据包  ……
 
pcap.h里定义了文件头的格式

struct pcap_file_header {
        bpf_u_int32 magic;
        u_short version_major;
        u_short version_minor;
        bpf_int32 thiszone;     /* gmt to local correction */
        bpf_u_int32 sigfigs;    /* accuracy of timestamps */
        bpf_u_int32 snaplen;    /* max length saved portion of each pkt */
        bpf_u_int32 linktype;   /* data link type (LINKTYPE_*) */
};

看一下各字段的含义:
magic:   4字节 pcap文件标识 目前为“d4 c3 b2 a1”
major:   2字节 主版本号     #define PCAP_VERSION_MAJOR 2
minor:   2字节 次版本号     #define PCAP_VERSION_MINOR 4
thiszone:4字节 时区修正     并未使用,目前全为0
sigfigs: 4字节 精确时间戳   并未使用,目前全为0
snaplen: 4字节 抓包最大长度 如果要抓全,设为0x0000ffff(65535),
               tcpdump -s 0就是设置这个参数,缺省为68字节
linktype:4字节 链路类型    一般都是1:ethernet

常用链路类型:
      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

=======================================================================================
|    magic    |major  | minor |   thiszone  |   sigfigs   |   snaplen   |  linktype  
| d4 c3 b2 a1 | 02 00 | 04 00 | 00 00 00 00 | 00 00 00 00 | ff ff 00 00 | 01 00 00 00
=======================================================================================
 
 
数据包头的格式

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) */
};
struct timeval {
        long            tv_sec;         /* seconds (XXX should be time_t) */
        suseconds_t     tv_usec;        /* and microseconds */
};

ts:    8字节 抓包时间 4字节表示秒数,4字节表示微秒数
caplen:4字节 保存下来的包长度(最多是snaplen,比如68字节)
len:   4字节 数据包的真实长度,如果文件中保存的不是完整数据包,可能比caplen大

 

了解了pcap文件格式,就可以自己手工构造任意数据包了,可以以录好的包为基础,

构建pcap文件示例:

含有两套构建方法, 因起先不知道可以通过pcap_open_dead & pcap_dump_open 构建文件头, 所以开始是自己创建一个文件并写入文件头.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <errno.h>
#include <pcap.h>
#include "common.h"


#define TCPDUMP_MAGIC       0xa1b2c3d4
#ifndef PCAP_VERSION_MAJOR
#define PCAP_VERSION_MAJOR 2
#define 
#define PCAP_VERSION_MINOR 
#define PCAP_VERSION_MINOR 4
#endif


#define LINKTYPE_NULL       DLT_NULL
#define LINKTYPE_ETHERNET   DLT_EN10MB  /* also for 100Mb and up */
#define LINKTYPE_EXP_ETHERNET   DLT_EN3MB   /* 3Mb experimental Ethernet */
#define LINKTYPE_AX25       DLT_AX25
#define LINKTYPE_PRONET     DLT_PRONET
#define LINKTYPE_CHAOS      DLT_CHAOS
#define LINKTYPE_TOKEN_RING DLT_IEEE802 /* DLT_IEEE802 is used for Token Ring */
#define LINKTYPE_ARCNET     DLT_ARCNET  /* BSD-style headers */
#define LINKTYPE_SLIP       DLT_SLIP
#define LINKTYPE_PPP        DLT_PPP
#define LINKTYPE_FDDI       DLT_FDDI


static int
pcap_write_header(FILE *fp, int linktype, int thiszone, int snaplen)
{
    struct pcap_file_header hdr;

    hdr.magic = TCPDUMP_MAGIC;
    hdr.version_major = PCAP_VERSION_MAJOR;
    hdr.version_minor = PCAP_VERSION_MINOR;

    hdr.thiszone = thiszone;
    hdr.snaplen = snaplen;
    hdr.sigfigs = 0;
    hdr.linktype = linktype;

    if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1)
        return (-1);

    return (0);
}

#define FILE_SAVE "pcap_write.pcap"

uint8_t l2_data[] = {
0x00, 0x0c, 0x29, 0x99, 0xfc, 0xa6, 0x00, 0x0c, 0x29, 0xd7, 0xc1, 0xf2, 0x08, 0x00, 0x45, 0x00,
0x00, 0x46, 0x87, 0x8a, 0x00, 0x00, 0x40, 0x11, 0x6e, 0xa5, 0xc0, 0xa8, 0x01, 0x31, 0xc0, 0xa8,
0x01, 0xf6, 0x7e, 0x75, 0x00, 0x35, 0x00, 0x32, 0x89, 0x42, 0x0a, 0x5d, 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x6e, 0x73, 0x31, 0x05, 0x67, 0x75, 0x61, 0x72, 0x64,
0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x29, 0x10, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x00
};
int main(int argc, char **argv)
{

#if 0
	FILE *fp = NULL;
	struct pcap_pkthdr h;
	fp = fopen(FILE_SAVE, "wb");
	if (!fp){
		fprintf(stderr, "fopen %s for write failed. errno=%d desc=%s\n", 
			FILE_SAVE, errno, strerror(errno));
		return 1;
	}

	pcap_write_header(fp, LINKTYPE_ETHERNET, 0x0, 0x0000ffff);
	gettimeofday(&h.ts, NULL);
	h.caplen = sizeof(l2_data);
	h.len    = sizeof(l2_data);

	pcap_dump((uint8_t *)fp, &h, l2_data);
	fflush(fp);
	fclose(fp);	
#else
	pcap_t *p = NULL;	
	pcap_dumper_t *fp = NULL;
	struct pcap_pkthdr h;
	
	p = pcap_open_dead(LINKTYPE_ETHERNET, 0x0000ffff);
	if (NULL == p){
		fprintf(stderr, "pcap_open_dead failed.\n");
		return 1;
	}
	fp = pcap_dump_open(p, FILE_SAVE);
	if (NULL == fp){
		fprintf(stderr, "pcap_dump_open failed.\n");
		return 1;
	}
	gettimeofday(&h.ts, NULL);
	h.caplen = sizeof(l2_data);
	h.len    = sizeof(l2_data);

	pcap_dump((uint8_t *)fp, &h, l2_data);	
	pcap_dump_close(fp);
#endif

	return 0;
}

 

编译 & 链接

# gcc pcap_write.c -o pcap_write -lpcap


 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值