귀찮아서 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 |
---|