[컴퓨터네트워크]패킷 분석하기

2JE0·2022년 10월 15일

컴퓨터네트워크

목록 보기
2/2
post-thumbnail

패킷은 패킷 헤더 24바이트를 제외하고는 다음과 같은 구조로 이루어져 있다.

그리고 IP Header는 다음과 같은 구조로 이루어져 있다. 따라서 형식에 맞는 구조체를 선언하여 패킷을 읽는 방식을 사용했다.


패킷 분할하는 법

Ping 옵션을 사용하여 [-l size]송신 버퍼 크기를 변경했을 때 패킷을 잡은 모습이다.
송신 패킷이 분할 되었고 마지막 fragment에는 ICMP가 붙어있다.




#include <stdio.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
typedef struct _PFHeader  //패킷 파일 헤더
{
    unsigned int magic;
    unsigned short major;
    unsigned short minor;
    unsigned int gmt_to_local;
    unsigned int timestamp;
    unsigned int max_caplen;
    unsigned int linktype;
} PFHeader;

typedef struct _pcap_pkthdr  //패킷 파일 헤더
{
    unsigned int sec;
    unsigned int usec;
    unsigned int caplen;
    unsigned int len;

} pcap_pkthdr;

typedef struct _ether_header  //패킷 파일 헤더
{
    unsigned char DMac[6];
    unsigned char SMac[6];
    unsigned char Ether_type[2];
} ether_header;

typedef struct _ip_header {
    unsigned char hlen;
    unsigned char type_of_service;
    unsigned short total_length;
    //
    unsigned char id[2];
    unsigned char fragmentation_offset[2];
    //
    unsigned char time_to_live;
    unsigned char protocol;
    unsigned short header_checksum;
    //
    unsigned char src_ip_address[4];
    unsigned char dest_ip_address[4];
} ip_header;

int num_of_packet = 0;
void print_pcap_pkthdr(pcap_pkthdr* pcap_p) {
    printf("sec:%d\n", pcap_p->sec);
    printf("usec:%d\n", pcap_p->usec);
    printf("caplen:%d\n", pcap_p->caplen);
    printf("len:%d\n", pcap_p->len);
}
void print_local_time(pcap_pkthdr* pcap_p) {
    time_t timer = pcap_p->sec;
    struct tm* t = localtime(&timer);
    printf("Local time: %d %02d:%02d:%02d.%06d\n", t->tm_year + 1900, t->tm_hour, t->tm_min, t->tm_sec, pcap_p->usec);
}
void print_cap_len(pcap_pkthdr* pcap_p) {
    printf("captured length: %d, actual length: %d \n", pcap_p->caplen, pcap_p->len);
}
void print_ipheader_len(ip_header* ipheader) {
    printf("The length in the IP header: %d\n", (ipheader->hlen & 0xF) * 4);
}
void print_ether_header(ether_header* eheader) {
    printf("Source MAC address %02X", eheader->SMac[0]);
    for (int i = 1; i < 6; i++) {
        printf(":%02X", eheader->SMac[i]);
    }
    printf(" -> ");
    printf("Destination MAC address %02X", eheader->DMac[0]);
    for (int i = 1; i < 6; i++) {
        printf(":%02X", eheader->DMac[i]);
    }
    printf("\n");
}
void print_protocol(int protocol) {
    printf("protocol: ");
    switch (protocol) {
        case 1:
            printf("ICMP");
            break;
        case 2:
            printf("IGMP");
            break;
        case 6:
            printf("TCP");
            break;
        case 9:
            printf("IGRP");
            break;
        case 17:
            printf("UDP");
            break;
        case 47:
            printf("GRE");
            break;
        case 50:
            printf("ESP");
            break;
        case 51:
            printf("AH");
            break;
        case 57:
            printf("SKIP");
            break;
        case 88:
            printf("EIGRP");
            break;
        case 89:
            printf("OSPF");
            break;
        case 115:
            printf("L2TP");
            break;
        default:
            printf("ERROR");
            break;
    }
    printf("\n");
}
void print_id_and_flags(ip_header* ipheader) {
    unsigned int id = (ipheader->id[0] << 8) + ipheader->id[1];
    bool DF = ipheader->fragmentation_offset[0] & (1 << 6);
    bool MF = ipheader->fragmentation_offset[0] & (1 << 5);
    printf("ID: %d\n", id);
    printf("DF: %d\n", DF);
    printf("MF: %d\n", MF);
}
void print_TTL(int ttl) {
    printf("TTL: %d\n", ttl);
}
void print_TOS(int tos) {
    printf("Type of service: %d\n", tos);
}
void print_ip_header(ip_header* ipheader) {
    printf("Source IP address %d", ipheader->src_ip_address[0]);
    for (int i = 1; i < 4; i++) {
        printf(".%d", ipheader->src_ip_address[i]);
    }
    printf(" -> ");
    printf("Destination IP address %d", ipheader->dest_ip_address[0]);
    for (int i = 1; i < 4; i++) {
        printf(".%d", ipheader->dest_ip_address[i]);
    }
    printf("\n");
    print_protocol(ipheader->protocol);
    print_id_and_flags(ipheader);
    print_TTL(ipheader->time_to_live);
}
void print_ip_address(ip_header* ipheader) {
    printf("Source IP address %d", ipheader->src_ip_address[0]);
    for (int i = 1; i < 4; i++) {
        printf(".%d", ipheader->src_ip_address[i]);
    }
    printf(" -> ");
    printf("Destination IP address %d", ipheader->dest_ip_address[0]);
    for (int i = 1; i < 4; i++) {
        printf(".%d", ipheader->dest_ip_address[i]);
    }
    printf("\n");
}
void print_one_packet(FILE* fp) {
    printf("============PACKET %d=============\n", ++num_of_packet);
    char buffer[70000];
    pcap_pkthdr pcap_p;
    ether_header eheader;
    ip_header ipheader;
    fread(&pcap_p, sizeof(pcap_pkthdr), 1, fp);
    print_local_time(&pcap_p);  // 7번
    print_cap_len(&pcap_p);     // 8번 caplen,actlen

    fread(&eheader, sizeof(ether_header), 1, fp);
    if (eheader.Ether_type[0] == 0x8) {
        fread(&ipheader, sizeof(ip_header), 1, fp);
        // print_ipheader_len(&ipheader);      // 8번 ip header len
        print_ether_header(&eheader);       // 9번
        print_ip_address(&ipheader);        // 10번
        print_protocol(ipheader.protocol);  // 11번
        print_id_and_flags(&ipheader);      // 12번
        print_TTL(ipheader.time_to_live);   // 13번
        print_TOS(ipheader.type_of_service);
        fread(buffer, pcap_p.caplen - sizeof(ether_header) - sizeof(ip_header), 1, fp);
    } else {
        fread(buffer, pcap_p.caplen - sizeof(ether_header), 1, fp);
    }
    printf("=============+++++++++============\n", ++num_of_packet);
}
int main(int argc, char* argv[]) {
    FILE* fp;
    char buffer[100];
    PFHeader h;
    pcap_pkthdr pcap_p;
    ether_header eheader;
    ip_header ipheader;
    fp = fopen(argv[1], "rb");
    if (fp == NULL) {
        perror("error: no file");
        exit(0);
    }
    fread(&h, sizeof(PFHeader), 1, fp);
    while (1) {
        if (feof(fp) != 0) break;
        print_one_packet(fp);
    }

    printf("\n\n");
    return 0;
}

0개의 댓글