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

[pcap 라이브러리] 11. libpcap과 메모리 매핑 기술을 이용하여 지연 덤프 소스 코드

언제나휴일 2016. 4. 29. 22:13
반응형

libpcap과 메모리 매핑 기술을 이용하여 지연 덤프


현재의 게시글은 앞으로 pcap 라이브러리를 이용하여 tshark 유틸과 같은 네트워크 트래픽을 수집하고 분석하는 도구를 만드는 과정을 게시하기 위해 어떠한 순서로 진행할 지 결정하기 위한 더미 코드입니다.

2016년 6월 이후부터 다양한 프로그래밍 언어와 기술에 관한 글과 무료 동영상 강의를 제작할 계획이며 그 중에 하나가 네트워크 보안에 관한 사항입니다. 네트워크 보안에 관한 주제는 네트워크 프로토콜, 소켓 프로그래밍, 리눅스에서 tshark 흉내내기, 윈도우즈에서 tshark 흉내내기와 C#언어로 와이어샤크 흉내내기 등을 다룰 예정입니다.

많은 관심과 조언 바랍니다.

아직 입문하기 위한 더미 코드들만 올린 상태입니다.

참고로 네트워크 프로토콜은 어느정도 정리한 상태입니다.

void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);

int munmap(void *addr, size_t length);

td_core.h


tiny_dump.c



//tiny_dump.c

#include "td_core.h"

#include <stdlib.h>

#include <stdio.h>

#include <sys/mman.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <sys/io.h>

#include <memory.h>

#define MEM_SIZE    0xfffff

 

 

void db_init();

void db_release();

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);

pcap_if_t *select_interface(pcap_if_t *alldevs);

void dump_all(pcap_dumper_t *df,pcap_t *handle,char *path);

 

 

 

int main(int argc,char **argv){

 

  char errbuf[PCAP_ERRBUF_SIZE];

  pcap_if_t *alldevs;

  pcap_if_t *dev;

 

  if(pcap_findalldevs(&alldevs,errbuf)==-1){

    printf("fail findalldevs: %s\n", errbuf);

    return 1;

  }//if  

 

  dev = select_interface(alldevs); 

  if(dev == 0){

  printf("fail select_interface\n");

   return 2;

 }//if

  printf("select <%s> inteface\n",dev->name);

 

  pcap_t *handle;      

  handle = pcap_open_live(dev->name, 4096, 1, 0, errbuf);

  if(handle == 0){

    printf("fail pcap_open_live...%s\n",errbuf);

    return 3;

  }//if

  pcap_freealldevs(alldevs);

 

 

  db_init();

 

  pcap_dumper_t *df;

  df = pcap_dump_open(handle,argv[1]);

  if(df == 0){ printf("fail dump_open\n"); exit(4);}

 

  pcap_loop(handle,3,catch_handler,(u_char *)df);

 

  dump_all(df,handle,argv[1]);

 

  pcap_close(handle);

  

  return 0;

}

 

 

pcap_if_t *select_interface(pcap_if_t *alldevs){

  pcap_if_t *dev;

  pcap_if_t *base[100];    

  int i;

  printf("interface list...\n");

  for(dev = alldevs, i=0; dev ; dev = dev->next,i++){   

    base[i] = dev;

    printf("<%d> : %s\n",i+1, dev->name);

  }//for

 

  printf("select inteface:");

  int num_dev;

  scanf("%d",&num_dev);

  fflush(stdin);

  if((num_dev<1) || (num_dev>i)){

    printf("The number is not available...\n");

    return 0;

  }//if

  return base[num_dev-1];

}

 

#define MAX_PACKET  0xffff

typedef struct _hd_packet hd_packet;

typedef struct _td_db td_db;

struct _td_db{

  void *db_base;

  u_char *ptr;

  int pcnt;

  hd_packet *base[MAX_PACKET];

};

 

 

struct _hd_packet{

  p_pkthdr header;

  u_char packet[4096];

};

/////////////////////db/////////////////

 

td_db tdb;

void db_store_packet(cp_pkthdr *pheader,cu_char *packet){

  hd_packet *hp = (hd_packet *)tdb.ptr;

  hp->header = *pheader;

  memcpy(hp->packet,packet,pheader->len);

  tdb.ptr += sizeof(cp_pkthdr) + pheader->len; 

  tdb.base[tdb.pcnt] = hp;

  tdb.pcnt++; 

}

void db_init(){

  tdb.db_base = mmap(0,MEM_SIZE, PROT_READ|PROT_WRITE,

   MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); //메모리 매핑

  if(tdb.db_base == MAP_FAILED){ printf("error mmap\n"); exit(4);}

  tdb.ptr = tdb.db_base;

  tdb.pcnt = 0;

  memset(tdb.db_base, 0, MEM_SIZE);

}

void db_release(){

  munmap(tdb.db_base,MEM_SIZE); //메모리 매핑 해제

}

 

///////////////////dump//////////////////

void dump_all(pcap_dumper_t *df,pcap_t *handle,char *path){

 

  int i = 0;

  hd_packet *hp;

  for(i=0; i<tdb.pcnt; ++i){

    hp = tdb.base[i];

    pcap_dump((u_char *)df,&(hp->header),hp->packet);

 

  }//for

  pcap_dump_close(df);

}

 

 

//////////////////capture handle////////

void catch_handler(u_char *args, cp_pkthdr *header,cu_char *packet){ 

  printf("##### recved %d bytes #####\n",header->len); 

  db_store_packet(header,packet);

}

 

////////////////////decode/////////////

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;

  return header->hd_len;

}

int decode_tcp(cu_char *base){

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

  tcp_hdr *header = (tcp_hdr *)base;

  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");

}

 

//td_core.h

#ifndef __td_core_h

#define __td_core_h

 

 

#define ETH_ADDR_LEN 6

 

#include <stdio.h>

#include <pcap.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.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:13;//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:13;//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

 


관련 게시글

1. libpcap 패키지 전체 업데이트 및 설치, 테스트 코드

2. 자신의 Network IP와 Mask값 확인하기 소스

3. 패킷 스니핑 소스(pcap_lookupdev, pcap_open_live, pcap_next, pcap_close)

4. libpcap으로 패킷 해석하기 뼈대 만들기

5. 필터 적용하여 패킷 캡쳐하기(소스 포함)

6. 자신의 Network에 필터를 적용하여 패킷 캡쳐 소스 코드

7. 캡쳐한 패킷 파일로 덤프하기 소스 코드(pcap_dump_open, pcap_dump)

8. 저장한 파일을 이용하기 소스 코드 (pcap_open_offline)

9. 필터식 BSF 문법 확인 (pcap_compile, pcap_compile_nopcap)

10. 기타 함수들 사용 예제 코드(pcap_is_swapped, pcap_freecode ,pcap_set_datalink)


반응형