미친해커

[C] 패킷의 이더넷(Ethernet) 헤더의 정보 출력하기 본문

C/pcap

[C] 패킷의 이더넷(Ethernet) 헤더의 정보 출력하기

미친해커 2022. 9. 28. 21:57
반응형

이더넷 프로토콜이란?

이더넷은 전세계적으로 사용되는 기술 규격이다. OSI 모델 데이터 링크 계층에서 MAC 패킷과 프로토콜을 정의한다. 또한 네트워크에서 각 기기가 48비트 길이의 고유 MAC 주소를 이용하여 데이터를 주고 받을 수 있도록 만들어졌다.

이더넷 헤더

이더넷 헤더의 사이즈는 총 14바이트으로 이루어져 있으며, 6바이트의 도착지(Destination) 그리고 출발지(Source) MAC 주소, 2바이트의 Ethernet Type이 존재한다.

 

Ethernet Type에는 다음 계층의 프로토콜이 무엇인지 기록된다.

구조체

C언어를 기준으로 구조체는 아래와 같이 정의할 수 있으며 필요한 경우 구조체 바이트 정렬이 필요하다.

typedef struct _NETWORK_ETHERNET_HEADER
{
    unsigned char Destination[6]; /* Destination MAC Address */
    unsigned char Source[6];      /* Source MAC Address */
    unsigned short Type;          /* Ethernet Type | You need to change the byte order */
} NETWORK_ETHERNET_HEADER, *PNETWORK_ETHERNET_HEADER;

네트워크 바이트 오더(Network Byte Order)

네트워크 바이트 오더(Network Byte Order)란 네트워크에서 사용하는 바이트 오더(Byte Order)를 말한다. 쉽게 말해 컴퓨터 시스템에는 Little Endian, Middle EndianBig Endian 등의 바이트 오더가 존재한다.

 

네트워크에서는 Big Endian을 사용하고 대부분의 프로세서는 Little Endian을 사용한다. 두 엔디안의 차이는 아래와 같다.

종류 0x1234 표현(2바이트 표현) 0x12345678 표현(4바이트 표현)
Big Endian (빅 엔디안)          01 02 03 04 05 06 07 08
00000000 12 34 XX XX XX XX XX XX
         01 02 03 04 05 06 07 08
00000000 12 34 56 78 XX XX XX XX
Little Endian (리틀 엔디안)          01 02 03 04 05 06 07 08
00000000 34 12 XX XX XX XX XX XX
         01 02 03 04 05 06 07 08
00000000 78 56 34 12 XX XX XX XX

빅 엔디안은 상위 바이트부터 순서대로 저장되고 리틀 엔디안은 하위 바이트부터 순서대로 저장된다는 차이점이 있다.

 

바이트 오더에 대한 자세한 내용은 아래 포스트를 참고해주세요.

 

[Network] 네트워크 바이트 오더 (Network Byte Order)

바이트 오더(Byte Order) 네트워크 바이트 오더를 설명하기 전에 바이트 오더에 대해 먼저 설명해야 한다. 바이트 오더란 컴퓨터 메모리에 바이트가 저장되는 순서를 바이트 오더라고 부른다. 바이

crazyhacker.tistory.com

주요 함수

ntohs

ntohs(Network byte order TO Host byte order Short) 함수는 2바이트 데이터를 네트워크 바이트 오더에서 호스트 바이트 오더로 변환하는 함수이다.

unsigned short Data = ntohs(NetworkByteOrderData);

예제 코드

예제 코드는 이전 포스팅에서 제작한 패킷 캡쳐 프로그램에서 기능을 추가했다.

#include <stdio.h>
#include <pcap.h>

typedef struct _NETWORK_ETHERNET_HEADER
{
    unsigned char Destination[6];
    unsigned char Source[6];
    unsigned short Type; // You need to change the byte order.
} NETWORK_ETHERNET_HEADER, *PNETWORK_ETHERNET_HEADER;

int main(int argc, char *argv[])
{
    if (argc < 2)
    {
        printf("Usage: %s [interface]\n", argv[0]);
        return -1;
    }
    
    char errbuf[PCAP_ERRBUF_SIZE];
    pcap_t *pcap = pcap_open_live(argv[1], BUFSIZ, 1, 1000, errbuf);

    if (pcap == NULL)
    {
        fprintf(stderr, "pcap_open_live(%s) return null - %s\n", argv[1], errbuf);
        return -1;
    }

    while (1)
    {
        struct pcap_pkthdr* header;
        const unsigned char *packet;
        int res = pcap_next_ex(pcap, &header, &packet);
        if (res == 0) continue;
        if (res == PCAP_ERROR || res == PCAP_ERROR_BREAK)
        {
            printf("pcap_next_ex return %d(%s)\n", res, pcap_geterr(pcap));
			break;
        }
        
        NETWORK_ETHERNET_HEADER *Ethernet = packet;
        Ethernet->Type = ntohs(Etherent->Type);
        
        printf("[Destination] : ");
        for (int i = 0; i < 6; i++)
        {
            printf("%02X ", Ethernet->Destination[i]);
        }
        putchar('\n');

        printf("[Source] : ");
        for (int i = 0; i < 6; i++)
        {
            printf("%02X ", Ethernet->Source[i]);
        }
        putchar('\n');
        
        printf("[EthernetType] : 0x%04X\n", Ethernet->Type);
    }
}
$ ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
		...

$ sudo ./main ens33
[Destination] : 00 50 56 FC 50 1D 
[Source] : 00 0C 29 7A 5F 24 
[EthernetType] : 0800
...
반응형

'C > pcap' 카테고리의 다른 글

[C] pcap로 네트워크 패킷 캡쳐하기  (3) 2022.09.23
Comments