1. 在 N 秒内将捕获的数据包保存到一个 pcap 文件中 & 2. 从 Wireshark 中的程序打印输出

1. Saved in N-Seconds captured packets into one pcap-File & 2. Print output from program like in Wireshark

第一个问题

我尝试将在 N 秒内接收或捕获的所有 packet 保存到 pcap 文件中,其中 pcap_dump_open.

我只添加了这段代码:

if (access("../CapturePacket/DefaultCapture5.pcap", F_OK) != ERROR) {
        dumper = pcap_dump_open_append(capture, "../CapturePacket/DefaultCapture5.pcap");


    } else {
        dumper = pcap_dump_open(capture, "../CapturePacket/DefaultCapture5.pcap");

    }

pcap_dump((u_char *) dumper, header, packet);
pcap_dump_close(dumper);

got_packet方法。

因此,如果我启动程序,它会收到几个数据包并仅将 1 个数据包(从程序中捕获的第一个数据包)保存到 pcap 文件中。我想要的是,所有在 N 秒内捕获的数据包都将保存到一个 pcap 文件中。我该如何修复我的代码?

第二个问题:

实际上,在教程的帮助下,我有一个程序可以嗅探并在 hex_ascii 行中向我打印 paypload。

此程序在环回中捕获了 N 秒的数据包。我实际上有一个程序向我的环回地址发送一个 TCP - Packet

#include <signal.h>

#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>
#include <unistd.h> // notice this! you need it!


#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


#define TRUE 1
#define FALSE 0
#define ERROR -1
#define bool uint8_t

/* Ethernet addresses are 6 bytes */
#define ETHER_ADDR_LEN  6

/* ethernet headers are always exactly 14 bytes */
#define SIZE_ETHERNET 14


/* Ethernet header */
struct sniff_ethernet {
    u_char ether_dhost[ETHER_ADDR_LEN]; /* Destination host address */
    u_char ether_shost[ETHER_ADDR_LEN]; /* Source host address */
    u_short ether_type; /* IP? ARP? RARP? etc */
};

/* IP header */
struct sniff_ip {
    u_char ip_vhl; /* version << 4 | header length >> 2 */
    u_char ip_tos; /* type of service */
    u_short ip_len; /* total length */
    u_short ip_id; /* identification */
    u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000        /* reserved fragment flag */
#define IP_DF 0x4000        /* dont fragment flag */
#define IP_MF 0x2000        /* more fragments flag */
#define IP_OFFMASK 0x1fff   /* mask for fragmenting bits */
    u_char ip_ttl; /* time to live */
    u_char ip_p; /* protocol */
    u_short ip_sum; /* checksum */
    struct in_addr ip_src, ip_dst; /* source and dest address */
};
#define IP_HL(ip)       (((ip)->ip_vhl) & 0x0f)
#define IP_V(ip)        (((ip)->ip_vhl) >> 4)

/* TCP header */
typedef u_int tcp_seq;

struct sniff_tcp {
    u_short th_sport; /* source port */
    u_short th_dport; /* destination port */
    tcp_seq th_seq; /* sequence number */
    tcp_seq th_ack; /* acknowledgement number */
    u_char th_offx2; /* data offset, rsvd */
#define TH_OFF(th)  (((th)->th_offx2 & 0xf0) >> 4)
    u_char th_flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
    u_short th_win; /* window */
    u_short th_sum; /* checksum */
    u_short th_urp; /* urgent pointer */
};

const struct sniff_ethernet *ethernet; /* The ethernet header */
const struct sniff_ip *ip; /* The IP header */
const struct sniff_tcp *tcp; /* The TCP header */
const char *payload; /* Packet payload */

u_int size_ip;
u_int size_tcp;

int waitSec = 10;
pcap_t *capture;
int npackets;

volatile sig_atomic_t stop_while = FALSE;

void alarm_handler(int sig) {

    printf("%d seconds have passed \n", waitSec);
    stop_while = TRUE;
    pcap_breakloop(capture);
}



/*
 * print data in rows of 16 bytes: offset   hex   ascii
 *
 * 00000   47 45 54 20 2f 20 48 54  54 50 2f 31 2e 31 0d 0a   GET / HTTP/1.1..
 */
void
print_hex_ascii_line(const u_char *payload, int len, int offset)
{

    int i;
    int gap;
    const u_char *ch;

    /* offset */
    printf("%05d   ", offset);

    /* hex */
    ch = payload;
    for(i = 0; i < len; i++) {
        printf("%02x ", *ch);
        ch++;
        /* print extra space after 8th byte for visual aid */
        if (i == 7)
            printf(" ");
    }
    /* print space to handle line less than 8 bytes */
    if (len < 8)
        printf(" ");

    /* fill hex gap with spaces if not full line */
    if (len < 16) {
        gap = 16 - len;
        for (i = 0; i < gap; i++) {
            printf("   ");
        }
    }
    printf("   ");

    /* ascii (if printable) */
    ch = payload;
    for(i = 0; i < len; i++) {
        if (isprint(*ch))
            printf("%c", *ch);
        else
            printf(".");
        ch++;
    }

    printf("\n");

return;
}

/*
 * print packet payload data (avoid printing binary data)
 */
void
print_payload(const u_char *payload, int len)
{

    int len_rem = len;
    int line_width = 16;            /* number of bytes per line */
    int line_len;
    int offset = 0;                 /* zero-based offset counter */
    const u_char *ch = payload;

    if (len <= 0)
        return;

    /* data fits on one line */
    if (len <= line_width) {
        print_hex_ascii_line(ch, len, offset);
        return;
    }

    /* data spans multiple lines */
    for ( ;; ) {
        /* compute current line length */
        line_len = line_width % len_rem;
        /* print line */
        print_hex_ascii_line(ch, line_len, offset);
        /* compute total remaining */
        len_rem = len_rem - line_len;
        /* shift pointer to remaining bytes to print */
        ch = ch + line_len;
        /* add offset */
        offset = offset + line_width;
        /* check if we have line width chars or less */
        if (len_rem <= line_width) {
            /* print last line and get out */
            print_hex_ascii_line(ch, len_rem, offset);
            break;
        }
    }

return;
}

void got_packet(u_char *args, const struct pcap_pkthdr *header,
        const u_char *packet) {
    static int count = 1;                   /* packet counter */

        /* declare pointers to packet headers */
        const struct sniff_ethernet *ethernet;  /* The ethernet header [1] */
        const struct sniff_ip *ip;              /* The IP header */
        const struct sniff_tcp *tcp;            /* The TCP header */
        const char *payload;                    /* Packet payload */

        int size_ip;
        int size_tcp;
        int size_payload;

        printf("\nPacket number %d:\n", count);
        count++;

        /* define ethernet header */
        ethernet = (struct sniff_ethernet*)(packet);

        /* define/compute ip header offset */
        ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);
        size_ip = IP_HL(ip)*4;
        if (size_ip < 20) {
            printf("   * Invalid IP header length: %u bytes\n", size_ip);
            return;
        }

        /* print source and destination IP addresses */
        printf("       From: %d\n", (ip->ip_src));
        printf("         To: %d\n", (ip->ip_dst));

        /* determine protocol */
        switch(ip->ip_p) {
            case IPPROTO_TCP:
                printf("   Protocol: TCP\n");
                break;
            case IPPROTO_UDP:
                printf("   Protocol: UDP\n");
                return;
            case IPPROTO_ICMP:
                printf("   Protocol: ICMP\n");
                return;
            case IPPROTO_IP:
                printf("   Protocol: IP\n");
                return;
            default:
                printf("   Protocol: unknown\n");
                return;
        }

        /*
         *  OK, this packet is TCP.
         */

        /* define/compute tcp header offset */
        tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);
        size_tcp = TH_OFF(tcp)*4;
        if (size_tcp < 20) {
            printf("   * Invalid TCP header length: %u bytes\n", size_tcp);
            return;
        }

        printf("   Src port: %d\n", ntohs(tcp->th_sport));
        printf("   Dst port: %d\n", ntohs(tcp->th_dport));

        /* define/compute tcp payload (segment) offset */
        payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp);

        /* compute tcp payload (segment) size */
        size_payload = ntohs(ip->ip_len) - (size_ip + size_tcp);

        /*
         * Print payload data; it might be binary, so don't just
         * treat it as a string.
         */
        if (size_payload > 0) {
            printf("   Payload (%d bytes):\n", size_payload);
//          print_payload(payload, size_payload);
        }
        printf("Packet capture length: %d\n", header->caplen);
        printf("Packet total length %d\n", header->len);


    return;
//  printf("Packet captured (delayed for %i second(s))\n",
//          (int) time(NULL) - (int) header->ts.tv_sec);
}


int main() {
    bpf_u_int32 network_mask, network_number;
    char error[PCAP_ERRBUF_SIZE];
    struct bpf_program filter;
    struct pcap_pkthdr header;
    struct pcap_stat statistic;

    if ((capture = pcap_create("lo", error)) == NULL) {
        printf("%s\n", error);
        return 1;
    }
//  pcap_set_timeout(capture, 500);
    pcap_activate(capture);
    if (pcap_lookupnet("lo", &network_number, &network_mask, error) == ERROR) {
        printf("%s\n", error);
        return 1;
    }
    if (pcap_compile(capture, &filter, "host 127.0.0.1", 1,
            network_mask) == ERROR) {
        printf("Error on compiling the filter: %s\n", pcap_geterr(capture));
        return 1;
    }
    if (pcap_setfilter(capture, &filter) == ERROR) {
        printf("Error on applying the filter: %s\n", pcap_geterr(capture));
        return 1;
    }

    printf("Waiting for a batch of packets\n");

    alarm(waitSec);
    signal(SIGALRM, alarm_handler);

    while (!stop_while) {
        npackets = pcap_dispatch(capture, 0, got_packet, NULL);

        if (!npackets) {
            pcap_stats(capture, &statistic);
            printf("PACKET: %s", npackets);
            printf("Timeout (%i packet(s) captured, %i packet(s) dropped)\n",
                    statistic.ps_recv, statistic.ps_drop + statistic.ps_ifdrop);
        }

        if (npackets == ERROR) {
            printf(error, "%s", pcap_geterr(capture));
            exit(1);
        }

    }
    pcap_freecode(&filter);
    pcap_close(capture);

    printf("Save in file  !!!!");
    return 0;

}

这个程序的输出是这样的:

Packet number 6:
       From: 1.2.3.4
         To: 127.0.0.1
   Protocol: TCP
   Src port: 1000
   Dst port: 1000
   Payload (10200 bytes):
00000   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ................
00016   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ................
00032   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  
......

我减少了Payload的输出。

所以我想要的是像 wireshark 一样的输出,对于有效载荷程序工作正常,但不是我的以太网 II 的信息,或 IP 和 TCP 信息。

Wireshark 中的输出是这样的:

0000   00 00 00 00 00 00 00 00 00 00 00 00 08 00          

->Information about the Ethernet II

0000   45 10 28 00 1c 56 00 00 40 06 b3 8b 01 02 03 04
0010   7f 00 00 01

Information about the IP - Header

0000   03 e8 03 e8 00 00 00 01 00 00 00 00 54 12 7f ff
0010   00 00 00 00

Information about the TCP - Header

我在Wireshark中也显示了有效载荷,但我没有在这里写下来,因为程序实际上是像Wireshark中一样打印有效载荷。

我程序的输出应该和Wireshark的输出一样。 您可能知道如何修复它吗?

第一个问题:

这段代码帮助了我。

void got_packet(u_char *args, const struct pcap_pkthdr *header,
        const u_char *packet) { 
   pcap_dumper_t *dumper;
    
    
        if (access("../CapturePacket/DefaultCapture5.pcap", F_OK) != ERROR) {
            dumper = pcap_dump_open_append(capture, "../CapturePacket/DefaultCapture5.pcap");
            pcap_dump((u_char *) dumper, header, packet);
    
        } else {
            dumper = pcap_dump_open(capture, "../CapturePacket/DefaultCapture5.pcap");
            pcap_dump((u_char *) dumper, header, packet);
        }
    
        pcap_dump_close(dumper);
return;
}