Linux.网络抓包库libpcap

来源:互联网 发布:光学字符识别软件 编辑:程序博客网 时间:2024/06/07 04:01
  • TCPDUMP & Libpcap
$ uname -aLinux niugenen 4.4.0-66-generic #87-Ubuntu SMP Fri Mar 3 15:29:05 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

DownLoad Libpcap

  • download link

这里写图片描述

  • click “libpcap-1.8.1.tar.gz” to download source code
  • then “./configure” & “make” & “sudo make install” to install libpcap

Official tutorials

  • Programming with pcap by Tim Carstens.

Data Structure

  • pcap_pkthdr
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) */};

as for struct timeval, found that in “/usr/include/x86_64-linux-gnu/bits/time.h”

#if defined __need_timeval || defined __USE_GNU# ifndef _STRUCT_TIMEVAL#  define _STRUCT_TIMEVAL   1#  include <bits/types.h>/* A time value that is accurate to the nearest   microsecond but also has a range of years.  */struct timeval  {    __time_t tv_sec;        /* Seconds.  */    __suseconds_t tv_usec;  /* Microseconds.  */  };# endif /* struct timeval */#endif

but in “/usr/inlcude/time.h”, only found this one

#if (!defined __timespec_defined                    \     && ((defined _TIME_H                       \      && (defined __USE_POSIX199309                 \          || defined __USE_ISOC11))                 \     || defined __need_timespec))# define __timespec_defined 1# include <bits/types.h>    /* This defines __time_t for us.  *//* POSIX.1b structure for a time value.  This is like a `struct timeval' but   has nanoseconds instead of microseconds.  */struct timespec  {    __time_t tv_sec;        /* Seconds.  */    __syscall_slong_t tv_nsec;  /* Nanoseconds.  */  };#endif /* timespec not defined and <time.h> or need timespec.  */

then I came to look for “__time_t”, found in “/usr/include/x86_64-linux-gnu/bits/types.h”

__STD_TYPE __TIME_T_TYPE __time_t;  /* Seconds since the Epoch.  */

“__STD_TYPE” is just a “#define” of “typedef”, but what is “__TIME_T_TYPE”, it is defined in “/usr/include/x86_64-linux-gnu/bits/typesizes.h”

#if defined __x86_64__ && defined __ILP32__# define __SYSCALL_SLONG_TYPE   __SQUAD_TYPE# define __SYSCALL_ULONG_TYPE   __UQUAD_TYPE#else# define __SYSCALL_SLONG_TYPE   __SLONGWORD_TYPE# define __SYSCALL_ULONG_TYPE   __ULONGWORD_TYPE#endif...#define __TIME_T_TYPE       __SYSCALL_SLONG_TYPE

then what is “__SQUAD_TYPE” or “__SLONGWORD_TYPE”, go back to “/usr/include/x86_64-linux-gnu/bits/types.h”

...#define __SLONGWORD_TYPE    long int#define __ULONGWORD_TYPE    unsigned long int...#if __WORDSIZE == 32# define __SQUAD_TYPE       __quad_t# define __UQUAD_TYPE       __u_quad_t...# define __S64_TYPE     __quad_t# define __U64_TYPE     __u_quad_t# define __STD_TYPE     __extension__ typedef#elif __WORDSIZE == 64# define __SQUAD_TYPE       long int# define __UQUAD_TYPE       unsigned long int.../* No need to mark the typedef with __extension__.   */# define __STD_TYPE     typedef#else# error#endif

so, __time_t is defined as __TIME_T_TYPE, which is defined as __SYSCALL_SLONG_TYPE, which is defined as __SQUAD_TYPE, which is defined as long int

and __syscall_slong_t is defined as __SYSCALL_SLONG_TYPE, which is long int according to my pc

time type

  • struct tm

in “/usr/include/time.h”

struct tm{  int tm_sec;           /* Seconds. [0-60] (1 leap second) */  int tm_min;           /* Minutes. [0-59] */  int tm_hour;          /* Hours.   [0-23] */  int tm_mday;          /* Day.     [1-31] */  int tm_mon;           /* Month.   [0-11] */  int tm_year;          /* Year - 1900.  */  int tm_wday;          /* Day of week. [0-6] */  int tm_yday;          /* Days in year.[0-365] */  int tm_isdst;         /* DST.     [-1/0/1]*/# ifdef __USE_MISC  long int tm_gmtoff;       /* Seconds east of UTC.  */  const char *tm_zone;      /* Timezone abbreviation.  */# else  long int __tm_gmtoff;     /* Seconds east of UTC.  */  const char *__tm_zone;    /* Timezone abbreviation.  */# endif};
  • struct sniff_ethernet

defined by Tim Carstens according to the offical tutorials

#define ETHER_ADDR_LEN  6/* Ethernet header */struct sniff_ethernet {    /* Destination host address */    u_char ether_dhost[ETHER_ADDR_LEN];    /* Source host address */    u_char ether_shost[ETHER_ADDR_LEN];    /* IP? ARP? RARP? etc */    u_short ether_type; };
  • struct sniff_ip
/* 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)
  • struct sniff_tcp
/* 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 */};
  • struct in_addr

found in “/usr/inlcude/netinet/in.h”

/* Internet address.  */typedef uint32_t in_addr_t;struct in_addr  {    in_addr_t s_addr;  };

Programming with libpcap

  • get device
char errBuf[PCAP_ERRBUF_SIZE], * devStr;  /* get a device */  devStr = pcap_lookupdev(errBuf);  if(devStr){    printf("success: device: %s\n", devStr);  }else{    printf("error: %s\n", errBuf);    exit(1);  }
  • open device
/* open a device, wait until a packet arrives */pcap_t * device = pcap_open_live(devStr, 65535, 1, 0, errBuf);  if(!device){    printf("error: pcap_open_live(): %s\n", errBuf);    exit(1);}
  • loop with callback function “getPacket”
/* wait loop forever */int id = 0;pcap_loop(device, -1, getPacket, (u_char*)&id);
  • getPacket
/* size of ETHERNET header = 6+6+2 = 14 */#define SIZE_ETHERNET 14/* The ethernet header */const struct sniff_ethernet *ethernet;/* The IP header */const struct sniff_ip *ip;/* The TCP header */const struct sniff_tcp *tcp;/* Packet payload */const u_char *payload;/* getPacket callback function */void getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet){    int * id = (int *)arg;    //count    printf("id = %d\n",++(*id));    //time    printf("time = %s\n", ctime((const time_t *)&pkthdr->ts.tv_sec));    ethernet = (struct sniff_ethernet*)(packet);    ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);    //source mac    printf("smac = %x-%x-%x-%x-%x-%x,",ethernet->ether_shost[0],ethernet->ether_shost[1],ethernet->ether_shost[2],ethernet->ether_shost[3],ethernet->ether_shost[4],ethernet->ether_shost[5]);    //source ip    printf("sip = %s,",inet_ntoa(ip->ip_src));    //destination mac    printf("dmac = %x-%x-%x-%x-%x-%x\n",ethernet->ether_dhost[0],ethernet->ether_dhost[1],ethernet->ether_dhost[2],ethernet->ether_dhost[3],ethernet->ether_dhost[4],ethernet->ether_dhost[5]);    //destination ip    printf("dip = %s\n",inet_ntoa(ip->ip_dst));    //packet length    printf("len = %d\n",pkthdr->len);    //get payload    u_int size_ip = IP_HL(ip)*4;    if (size_ip < 20) {        printf("   * Invalid IP header length: %u bytes\n", size_ip);        return;    }    u_int size_tcp = TH_OFF(tcp)*4;    if (size_tcp < 20) {        printf("   * Invalid TCP header length: %u bytes\n", size_tcp);        return;    }    payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp);    //end    printf("\n");}

Using Libpacp to analysis FTP

  • apply filter “port 21 or port 20”
/* The compiled filter expression */struct bpf_program fp;/* The filter expression */char filter_exp[] = "port 21 or port 20";/* The netmask of our sniffing device */bpf_u_int32 mask;/* The IP of our sniffing device */bpf_u_int32 net;if (pcap_lookupnet(devStr, &net, &mask, errBuf) == -1) {    fprintf(stderr, "Can't get netmask for device %s\n", devStr);    net = 0;    mask = 0;}if (pcap_compile(device, &fp, filter_exp, 0, net) == -1) {    fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(device));    exit(2);}if (pcap_setfilter(device, &fp) == -1) {    fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(device));    exit(2);}
  • print payload to check FTP data ( TCP data first )
if( ip->ip_p | 8 == 8){ //tcp data    printf("Get one TCP data\n");    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;    }*/    payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp);    int i = 0;    for(; i < ip->ip_len; ++i){        printf("%c", payload[i]);    }}
  • here is the result

这里写图片描述

这里写图片描述

这里写图片描述

  • can find UER and password in payload data
0 0