본문 바로가기

컴퓨터 공부/C

WinPcap 패킷캡쳐(임시)

귀찮아서 tcp만 했음

 

#include<WinSock2.h>

#include<stdio.h>

#include<windows.h>

#include<string.h>

#include<pcap.h>

#pragma comment(lib,"ws2_32.lib")

#pragma comment(lib,"wpcap.lib")

#define WEB "tcp"


typedef struct ether_addr
{

	unsigned char e_host[6];

}ETHER_ADDR;


typedef struct ethernet_header
{

	ETHER_ADDR src;

	ETHER_ADDR dst;

	unsigned short type;

}ETHERNET_HEADER;


//ip_header 
typedef struct ip_header

{



	unsigned char header_len : 4;

	unsigned char ver : 4;

	unsigned char tos;

	unsigned short total_len;

	unsigned short id;

	unsigned char frag_offset : 5;

	unsigned char mf : 1;

	unsigned char df : 1;

	unsigned char rz : 1;

	unsigned char frag_offset1;

	unsigned char ttl;

	unsigned char protocol;

	//1=ICMP, 2=IGMP, 6=TCP, 8= EGP, 17=UDP, 89=OSPF 등등.....

	unsigned char cksum;

	IN_ADDR src_ip;

	IN_ADDR dst_ip;

}IP_HEADER;

typedef struct tcp_header
{

	unsigned short src_port;

	unsigned short dst_port;

	unsigned int seq;

	unsigned int ack;

	unsigned char data_offset;

	unsigned char ns : 1;

	unsigned char reserved : 3;

	unsigned char flag_fin : 1;

	unsigned char flag_syn : 1;

	unsigned char flag_rst : 1;

	unsigned char flag_psh : 1;

	unsigned char flag_ack : 1;

	unsigned char flag_urg : 1;

	unsigned char flag_ece : 1;

	unsigned char flag_cwr : 1;

	unsigned short window;

	unsigned short cksum;

	unsigned short up;

}TCP_HEADER;


int PrintEtherNetHeader(unsigned const char* data);

int PrintIpHeader(unsigned const char* data);

int PrintTcpHeader(unsigned const char* data);

void PrintData(unsigned const char* data);

int total_len;


int main()
{

	pcap_t* pd;

	pcap_if_t* dev_info, * sub_info;

	char err[PCAP_ERRBUF_SIZE] = { 0, };

	struct bpf_program fcode;

	struct pcap_pkthdr* p;

	int i;

	unsigned char* data;

	int offset;

	int res;

	int select;

	pcap_findalldevs(&dev_info, err);

	sub_info = dev_info;



	for (i = 1; sub_info; i++) {

		printf("%d -> %s : %s\n", i, sub_info->name, sub_info->description);

		sub_info = sub_info->next;

	}

	sub_info = dev_info;

	scanf("%d", &select);

	for (i = 1; i < select; i++)

	{

		sub_info = sub_info->next;

	}

	pd = pcap_open_live(sub_info->name, 65536, 1, 20, err);

	pcap_compile(pd, &fcode, WEB, 1, NULL);

	pcap_setfilter(pd, &fcode);


	while ((res = pcap_next_ex(pd, &p, &data)) >= 0)
	{

		if (res == NULL)

			continue;

		offset = PrintEtherNetHeader(data);

		data = data + offset;

		offset = PrintIpHeader(data);

		data = data + offset;

		offset = PrintTcpHeader(data);

		data = data + offset;

		PrintData(data);

	}


}

int PrintEtherNetHeader(unsigned const char* data)

{

	ETHERNET_HEADER* ethernet;

	ethernet = (ETHERNET_HEADER*)data;

	printf("\n===============Ether Net==================\n");

	printf("\nsrc MAC : [%02x:%02x:%02x:%02x:%02x:%02x]\n",

		ethernet->src.e_host[0],

		ethernet->src.e_host[1],

		ethernet->src.e_host[2],

		ethernet->src.e_host[3],

		ethernet->src.e_host[4],

		ethernet->src.e_host[5]);

	printf("\ndst MAC : [%02:x%02x:%02x:%02x:%02x:%02x]\n",

		ethernet->src.e_host[0],

		ethernet->src.e_host[1],

		ethernet->src.e_host[2],

		ethernet->src.e_host[3],

		ethernet->src.e_host[4],

		ethernet->src.e_host[5]);

	printf("\nEthernet Type : %d\n", ntohs(ethernet->type));

	return sizeof(ETHERNET_HEADER);

}

int PrintIpHeader(unsigned const char* data)
{

	//1=ICMP, 2=IGMP, 6=TCP, 8= EGP, 17=UDP, 89=OSPF 등등등 

	IP_HEADER* ip;

	ip = (IP_HEADER*)data;

	printf("\n================IP HEADER===================\n");

	printf("IPv%d\n", ip->ver);

	printf("IP Header Total Len : %d\n", ntohs(ip->total_len) + 14);

	if (ip->protocol == 1)
		printf("TYPE : ICMP\n");

	else if (ip->protocol == 2)
		printf("TYPE : IGMP\n");

	else if (ip->protocol == 6)
		printf("TYPE : TCP\n");

	else if (ip->protocol == 17)
		printf("TYPE : UDP\n");

	else if (ip->protocol == 89)
		printf("TYPE : OSPF\n");

	total_len = ntohs(ip->total_len) - 40;

	printf("\nSrc IP : %s\n", inet_ntoa(ip->src_ip));

	printf("dst IP : %s\n", inet_ntoa(ip->dst_ip));

	return sizeof(IP_HEADER);

}


int PrintTcpHeader(unsigned const char* data)
{

	TCP_HEADER* tcp;
	tcp = (TCP_HEADER*)data;

	printf("src Port : %d\n", ntohs(tcp->src_port));

	printf("dst Port : %d\n", ntohs(tcp->dst_port));

	printf("seq Number : %d\n", ntohs(tcp->seq));

	printf("ack Number : %d\n", ntohs(tcp->ack));

	if (tcp->flag_fin)
		printf("fin\t");
	if (tcp->flag_syn)
		printf("syn\t");

	if (tcp->flag_rst)
		printf("rst\t");

	if (tcp->flag_psh)
		printf("psh\t");

	if (tcp->flag_ack)
		printf("ack\t");

	if (tcp->flag_urg)
		printf("urg\t");

	printf("\n");

	return sizeof(TCP_HEADER);

}

void PrintData(unsigned const char* data)
{

	unsigned char* sub_data = data;

	int i = 0;

	printf("\n==============DATA================\n");


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

		printf("%02x ", *(sub_data++));

		if (i % 16 == 0)

			printf("\n");

	}

}

 

구조체에 대해서 정리해보겠다.

pcap_t *pd;

pcap_t 구조체는 네트워크 디바이스나 패킷에 들어있는 pcap파일에서 패킷을 읽는데 사용되는 HANDLE이다


pcap_if_t *dev_info, *sub_info;

pcap_if_t 구조체는 네트워크 디바이스의 정보를 담을수 있는 구조체이다

(여기안에 ip주소도 있는거같았지만 아직 어떻게구하는지 모르겠다 한번 찾아보겠다).


struct bpf_program fcode;

bpf_program 구조체 안에는 pcap_open_live()함수로 인해 정해진 룰이 저장이 되는것 같다.


struct pcap_pkthdr *p;

pcap_pkthdr 구조체는 패킷의 정보를 저장할 구조체이다.

패킷의 크기가 담겨져있었따!


이제 함수를 알아보도록 하자

int pcap_findalldevs(pcap_if_t **alldevsp,char *errbuf);

[기능]

령결 리스트 형식으로 디바이스의 정보를 구한다

[파라미터]

pcap_if_t **alldevsp : 네트워크 디바이스의 포인터;

char *errbuf : 실패시 에러 메시지가 채워진다

[반환]

성공 : 0

실패 : -1


pcap_t pcap_open_live(char *device,int snaplen, int promisc, int to_ms, char *ebuf)

[기능]

네트워크 패킷들을 보기위한 패킷캡쳐디스크립터를 얻기위해 사용하는 함수이다.

[파라미터]

char *device : 사용할 디바이스 이름

int snaplen : 캡쳐할 최대 byte

int promisc : 1로 설정하면 broadcast모드가 되어 감시한다?

int to_ms : time out 시간이다 1000당 1초이다.

char *ebuf : 실패시 에러 메시지가 채워진다

[반환]

성공 : packet descriptor

실패 : NULL


int pcap_compile (pcap_t *p,bpf_program *fp, char *str, int optimize,bpf_u_int32 netmask)

[기능]

스트링 형태의 필터링 룰을 해석하여 bpf_program *fp에 저장을 한다

[파라미터]

pcap_t *p : 패킷 캡쳐 descriptor

struct bpf_program *fp : 필터링 룰을 저장을 구조체

char *str : 스트링 형태의 필터링 룰

int optimize : 결과 코드를 수행할 때 최적화 여부

bpf_u_int32 netmask : 0을 입력하면 모든 인터페이스를 캡쳐한다.

[반환]

성공 : 아무고또없음

실패 : -1


int pcap_setfilter ( pcap_t *p,struct bpf_program *fp)

[기능]

packet descriptor에 등록된 네트워크 어텝터에 fp에 저장된 룰을 적용시켜 필터링한다.(차단x)

[파라미터]

pcap_t *p : 네트워크 어탭터가 등록된 packet descriptor

struct bpf_program *fp : 룰이 저장되어있다.

[반환]

성공 : 0

실패 : -1

 


ip pcap_next_ex (pcap_t *p,struct pcap_pkthdr **pkt_header,u_char **pkt_data)

[기능]

오프라인 캡처로부터 혹은 네트워크 어댑터로부터 패킷을 읽어들인다.

[파라미터]

pcap_t *p : 네트워크 어댑터의 포인터

struct pcap_pkthdr **pkt_header : 패킷 hreader의 구조를 담는다. len에 패킷의 크기가 들어가더라

u_char **pkt_data : 패킷 데이터의 포인터를 얻는다

[반환]

1 : 성공

0 : timeout이 될 경우

-1 : 에러발생

-2 : EOF

'컴퓨터 공부 > C' 카테고리의 다른 글

매개변수 반환값 지정  (0) 2019.06.20