안녕하세요. 언제나 휴일에 언휴입니다.
프로젝트에서 사용할 PCAP 파일 다운로드 (PCAP 파일이면 다른 파일도 관계 없어요.)
* 동영상 강의에서는 앞쪽 200개만 자른 파일로 시연하였습니다.
패킷 분석기 구현 프로젝트는 Tcpdump 유틸 등으로 수집한 pcap 파일을 분석하는 프로그램 제작입니다.
현재 PACP 파일 분석, ethernet 프로토콜 , IPv4 프로토콜 스택 정보를 출력하는 부분까지 구현한 상태입니다.
이번 강의는 TCP 프로토콜 스택 정보를 출력하는 부분을 구현합니다.
구현 과정은 동영상 강의를 참고하세요.
- TCP.h
#pragma once #include "PcapFile.h" typedef struct _TCPHeader TCPHeader; struct _TCPHeader { ushort src_port; ushort dst_port; uint seqno; uint ackno; uchar hdlen; uchar fin : 1; uchar syn : 1; uchar rst : 1; uchar psh : 1; uchar ack : 1; uchar urg : 1; uchar reserved : 2; ushort winsize; ushort checksum; ushort upoint; }; void ParseTCP(uchar* base, uint len);
- TCP.c
#include "TCP.h" void ParseTCP(uchar* base, uint len) { TCPHeader* th = (TCPHeader*)base; printf("★★★ TCP 헤더 ★★★\n"); printf("\tsrc port:%u\n", ntohs(th->src_port)); printf("\tdest port:%u\n", ntohs(th->dst_port)); printf("\tseq no:%u\n", ntohl(th->seqno)); printf("\tack no:%u\n", ntohs(th->ackno)); printf("\t"); if (th->syn) { printf("SYN "); } if (th->ack) { printf("ACK "); } if (th->fin) { printf("FIN "); } if (th->rst) { printf("RST "); } if (th->psh) { printf("PSH "); } if (th->urg) { printf("URG "); } printf("\n"); printf("\twindow size:%u\n", ntohs(th->winsize)); printf("\turg pointer:%u\n", ntohs(th->upoint)); }
- IPv4.h
#pragma once #include "PcapFile.h" #define PRO_ICMPv4 0x01 #define PRO_IGMP 0x02 #define PRO_TCP 0x06 #define PRO_UDP 0x11 #define PRO_OSPF 0x59 typedef struct _IPv4Header IPv4Header; struct _IPv4Header { uchar hlen : 4; uchar version : 4; uchar tos; ushort tlen; ushort id; ushort fl_off; #define DONT_FRAG(x) (x&0x40) #define MORE_FRAG(x) (x&0x20) #define FRAG_OFF(x) ntohs(x&0xFF1F) uchar ttl; uchar protocol; ushort checksum; uint srcaddr; uint dstaddr; }; void ParseIPv4(uchar *base, uint len);
- IPv4.c
#include "IPv4.h" #include "TCP.h" void PrintIPv4(uint addr) { uchar *up = (uchar *)&addr; int i = 0; for (i = 0; i < 3; i++) { printf("%d.", up[i]); } printf("%d", up[i]); } void ParseIPv4(uchar *base, uint len) { IPv4Header *iph = (IPv4Header *)base; printf("☆☆☆☆☆ IPv4 Header ☆☆☆☆☆☆\n"); printf("\n version:%d\n", iph->version); printf("\n hlen:%d bytes\n", iph->hlen * 4); printf("\t total length :%d bytes\n", ntohs(iph->tlen)); printf("\t id:%d\n", ntohs(iph->id)); if (DONT_FRAG(iph->fl_off)) { printf("\t Don't Fragment\n"); } if (MORE_FRAG(iph->fl_off)) { printf("\t More Fragment\n"); } printf("\t offset:%d bytes\n", FRAG_OFF(iph->fl_off)); printf("\t Time To Live:%d\n", iph->ttl); printf("\t Protocol :%d\n", iph->protocol); printf("\t ICMP:%d IGMP:%d TCP:%d UDP:%d OSPF:%d\n", PRO_ICMPv4, PRO_IGMP, PRO_TCP, PRO_UDP, PRO_OSPF); printf("\t src:"); PrintIPv4(iph->srcaddr); printf("\t"); PrintIPv4(iph->dstaddr); printf("\n"); uchar *next = base + (iph->hlen * 4); len = len - (iph->hlen * 4); switch (iph->protocol) { case PRO_ICMPv4: printf("\t to be defined\n"); break; case PRO_TCP: ParseTCP(next,len); break; default: printf("\t Not supported\n"); break; } }
- EHEther.h
#pragma once #include "PcapFile.h" #define L3_IPv4 0x0800 #define L3_ARP 0x0806 typedef struct _EtherHeader EtherHeader; struct _EtherHeader { uchar dst_mac[6]; uchar src_mac[6]; ushort l3type; }; void ParseEther(uchar *buffer, uint len);
- EHEther.c
#include "EHEther.h" #include "IPv4.h" void ViewEther(EtherHeader *eh); void ParseEther(uchar *buffer, uint len) { EtherHeader *eh = (EtherHeader *)buffer; uchar *next = buffer + sizeof(EtherHeader); len = len - sizeof(EtherHeader); ViewEther(eh); switch (ntohs(eh->l3type)) { case L3_IPv4: ParseIPv4(next, len); break; case L3_ARP: printf("ARP: to be defined\n"); break; default: printf("Not support\n"); break; } } void ViewMac(const char *msg, uchar *base); void ViewEther(EtherHeader *eh) { printf("★★★★★ ethernet header ★★★★★\n"); ViewMac("dest", eh->dst_mac); ViewMac("source", eh->src_mac); printf("\tL3Type:%#x\n", ntohs(eh->l3type)); printf("\t(IPv4:0x0800 ARP:0x0806)\n"); } void ViewMac(const char *msg, uchar *base) { printf("\t%s", msg); printf("%02x", base[0]); for (int i = 1; i < 6; i++) { printf(":%02x", base[i]); } printf("\n"); }
- PcapFile.h
#pragma once #include #pragma comment(lib,"ws2_32") #include typedef unsigned int uint; typedef unsigned short ushort; typedef unsigned char uchar; typedef struct _PFHeader PFHeader; struct _PFHeader //패킷 파일 헤더 { uint magic;//0xA1B2C3D4 ushort major; ushort minor; uint gmt_to_local; uint timestamp; uint max_caplen; uint linktype; }; typedef struct _PACKETHEADER PackHeader; struct _PACKETHEADER //패킷 헤더 { uint captime;//second uint caputime;//u second uint caplen; uint packlen; }; #define PF_MAGIC 0xA1B2C3D4 #define LT_ETHER 0x01 void ParseEthers(FILE *fp); int ParsePCapFile(FILE *fp, PFHeader *pfh);
- PCapFile.c
#include "PcapFile.h" #include "EHEther.h" char buffer[0x100000]; void ViewPCapFile(PFHeader *pfh); void ViewPacketHeaderInfo(PackHeader *ph, int pno); void ParseEthers(FILE *fp) { PackHeader ph = { 0 }; int pno = 0; while (fread(&ph, sizeof(PackHeader), 1, fp) == 1) { pno++; ViewPacketHeaderInfo(&ph, pno); fread(buffer, sizeof(uchar), ph.caplen, fp); ParseEther(buffer, ph.caplen); } } int ParsePCapFile(FILE *fp, PFHeader *pfh) { fread(pfh, sizeof(PFHeader), 1, fp); if (pfh->magic != PF_MAGIC) { return 0; } ViewPCapFile(pfh); return 1; } void ViewPCapFile(PFHeader *pfh) { printf("=========== PCAP File 헤더 정보 ============\n"); printf("\t 버전:%d.%d\n", pfh->major, pfh->minor); printf("\t최대 캡쳐 길이:%d bytes\n", pfh->max_caplen); } void ViewPacketHeaderInfo(PackHeader *ph, int pno) { printf("!!! <%4d th> 프레임 !!!\n", pno); printf("패킷:%6d bytes 캡쳐:%6d\n", ph->packlen, ph->caplen); }
- Program.c
//https://ehpub.co.kr #include #include #include #include "PcapFile.h" int main() { setlocale(LC_ALL, "KOREAN"); char fname[256 + 1] = ""; printf("분석할 pcap 파일명:"); scanf_s("%s", fname, sizeof(fname)); FILE *fp = 0; fopen_s(&fp, fname, "rb"); if (fp == 0) { perror("파일 열기 실패"); system("pause"); return 0; } PFHeader pfh = { 0, }; if (ParsePCapFile(fp, &pfh) == 0) { printf("PCAP 파일이 아닙니다\n"); fclose(fp); system("pause"); return 0; } switch (pfh.linktype) { case LT_ETHER: ParseEthers(fp); break; default: printf("Not Support\n"); break; } fclose(fp); system("pause"); return 0; }