네트워크 및 보안/pcap 라이브러리

[pcap 라이브러리] 4. libpcap으로 패킷 해석하기 뼈대 만들기

언제나휴일 2016. 4. 29. 18:03
반응형

libpcap으로 패킷 해석

단계: 프로토콜 헤더를 정의한다.

단계: 스니핑 코드 작성

  pcap_loop을 이용

단계: 패킷 캡쳐 핸들러를 작성

  각 계층별로 패킷 해석 정보를 출력하는 함수 호출


 

core_ehp.h


pc_dec.c


단계: 프로토콜 헤더 작성

//core_ehp.h

#ifndef __core_ehp_h

#define __core_ehp_h

 

 

#define ETH_ADDR_LEN 6

 

#include <pcap.h>

#include <netinet/ip.h>

typedef const struct pcap_pkthdr cp_pkthdr;

typedef const u_char cu_char;

typedef struct pcap_pkthdr p_pkthr;

 

 

typedef struct _eth_hdr eth_hdr;

struct _eth_hdr{

  u_char   src[ETH_ADDR_LEN];

  u_char   dst[ETH_ADDR_LEN];

  u_short  type;

};

#define SIZE_ETH (sizeof(eth_hdr))

typedef struct _ip_hdr ip_hdr;

struct _ip_hdr{

  #if __BYTE_ORDER == __LITTLE_ENDIAN

  u_char hd_len:4;

  u_char version:4;

  #elif __BYTE__ORDER == __BIG_ENDIAN

  u_char version:4;

  u_char hd_len:4;

  #endif

  u_char tos;

  u_short tot_len;

 

 

  u_short id;

  #if __BYTE_ORDER == __LITTLE_ENDIAN

  u_short offset:15;//per 8byte

  u_short m_flag:1;//more fragment

  u_short d_flag:1;//don't fragment

  u_short r_flag:1;//reserved

  #endif

  #if __BYTE_ORDER == __BIG_ENDIAN

  u_short r_flag:1;//reserved

  u_short d_flag:1;//don't fragment

  u_short m_flag:1;//more fragment

  u_short offset:15;//per 8byte

  #endif 

 

  u_char ttl;

  u_char type;

  u_short check;

  u_int src_addr;

  u_int dst_addr;

};

#define SIZE_IP (sizeof(ip_hdr))

 

typedef struct _tcp_hdr tcp_hdr;

struct _tcp_hdr{

  u_short sport;

  u_short dport;

  u_int seq;

  u_int ack;

  #if __BYTE_ORDER == __LITTLE_ENDIAN

  u_short reserved:4;

  u_short doff:4;//data offset per 4byte;

  #endif

  #if __BYTE_ORDER == __BIG_ENDIAN

  u_short doff:4;

  u_short reserved:4;

  #endif

  u_char flags;

  #define TCP_FIN   0x01

  #define TCP_SYN   0x02

  #define TCP_RST   0x04

  #define TCP_PUSH  0x08

  #define TCP_ACK   0x10

  #define TCP_URG   0x20

  u_short window;

  u_short check;

  u_short urgent;

};

//to do - define udp header

//to do - define icmp header

//to do - define ip6 header

//to do - define icmp6 header

//to do - define igmp header

 

#endif


단계: 스니핑

반복해서 패킷을 캡쳐하고 캡쳐하면 패킷 캡쳐 핸들러를 호출함

pcap_loop(pcap_handle,3,catch_handler,0);

int pcap_loop(pcap_t *pcap_handle, int cnt, pcap_handler cb_handler, u_char *user);

int pcap_dispath(pcap_t *pcap_handle, int cnt, pcap_handler cb_handler, u_char *user);

/*pcap_loop 대신 pcap_dispatch를 사용할 수도 있다. */

콜백 핸들러는 다음과 같은 시그니쳐를 갖는 함수 포인터(함수 이름)

void catch_handler(u_char *args,cp_pkthdr *handle,cu_char *packet);

//pc_dec.c

#include "core_ehp.h"

 

void catch_handler(u_char *args,cp_pkthdr *handle,cu_char *packet);

void decode_eth(cu_char *base);

int decode_ip(cu_char *base);

int decode_tcp(cu_char *base);

void decode_data(cu_char *packet,u_int len);

void view_ether_addr(const char *pre,cu_char *base);

 

int main(){

  cu_char *packet;

  char errbuf[PCAP_ERRBUF_SIZE];

  char *device;

  pcap_t *pcap_handle;

 

  device = pcap_lookupdev(errbuf);

  if(device == 0){ printf("fail lookupdev...%s\n",errbuf); }

  printf("find device: %s sniffing\n",device);

 

  pcap_handle = pcap_open_live(device, 4096, 1, 0, errbuf);

  if(pcap_handle == 0){ printf("fail pcap_open_live...%s\n",errbuf); }

 

  pcap_loop(pcap_handle,3,catch_handler,0);

  pcap_close(pcap_handle);

  return 0;

}


 

단계: 프로토콜 해석하여 출력

void decode_eth(cu_char *base){

  eth_hdr *ethhd = (eth_hdr *)base;

  printf("======layer 2: ehternet header =====\n");

  view_ether_addr("src:",ethhd->src);

  view_ether_addr("\tdst:",ethhd->dst);

  printf("\ntype:%u\n",ethhd->type); 

}

void view_ether_addr(const char *pre,cu_char *base){

  printf("%s: %2x",pre,base);

  int i = 0;

  for(i=1;i<ETH_ADDR_LEN; ++i){

    printf(":%02x",base[i]);

  }//for

}

int decode_ip(cu_char *base){

  printf("\n*****layer 3: ip header *****\n");

ip_hdr *header = (ip_hdr *)base;

//to do

  return header->type;

}

int decode_tcp(cu_char *base){

  printf("\n*****layer 4: tcp header *****\n"); 

  tcp_hdr *header = (tcp_hdr *)base;

  //to do

  return header->doff*4;

}

void decode_data(cu_char *packet,u_int len){

  u_int i = 0;

  printf("--- body %d byte---\n",len);

  for(i=0; i<len; ++i){

    printf("%x ",*packet);

    packet++;

    if(i%25 == 24){ printf("\n"); }

  }//for

  printf("\n-----------------\n\n");

}


반응형