미친해커

[C] pcap로 네트워크 패킷 캡쳐하기 본문

C/pcap

[C] pcap로 네트워크 패킷 캡쳐하기

미친해커 2022. 9. 23. 03:42
반응형

pcap이란?

pcap(packet capture)는 네트워크 프로그래밍을 위한 라이브러리다. 유닉스 계열의 운영 체제들은 libpcap 라이브러리에  pcap이 포함되어 있어 libpcap을 이용해 네트워크 프로그래밍을 할 수 있다.

 

윈도우는 WinPcap이라고 하는 libpcap의 포팅된 버전을 사용한다.

 

네트워크의 패킷들을 잡을 수 있으며 일반적으로는 볼수 없는 헤더들의 데이터도 모두 캡처하여 볼 수 있다. pcap API는 C언어로 작성되어 있어 여러 언어에서 사용할 수 있다는 장점이 있다. (해당 블로그에서는 Unix 계열의 운영 체제들을 기준으로 실습한다)

libpcap 설치하기

블로그에서는 Ubuntu와 Kali Linux에서 프로그래밍 실습을 진행한다. 해당 운영 체제에는 기본적으로 libpcap 라이브러리가 설치되어 있지 않기 때문에 패키지 매니저를 통한 라이브러리 설치가 필요하다. 다음 명령어로 설치할 수 있다.

 

libpcap를 사용하기 위해서는 pcap.h 헤더 파일을 사용하면 된다.

$ sudo apt-get update
$ sudo apt-get install libpcap-dev

주요 함수

pcap_open_live

pcap_open_live 함수는 네트워크 인터페이스를 오픈하는 함수이다. 해당 함수는 pcap_t* 핸들을 반환하고 반환된 핸들을 사용해 패킷 캡쳐, 전송 등 작업을 수행할 수 있다.

char errbuf[PCAP_ERRBUF_SIZE];
pcap_t *pcap = pcap_open_live("eth0", BUFSIZ, 1, 1000, errbuf);

pcap_close

pcap_close 함수는 오픈한 네트워크 인터페이스 핸들을 닫아주는 함수이다. 네트워크 인터페이스를 오픈한 상태로 있다면 해당 인터페이스를 프로세스가 계속 점유하고 있기 때문에 사용하지 않을 때에는 반드시 닫아주어야 한다.

pcap_close(pcap);

pcap_next_ex

pcap_next_ex 함수는 네트워크 인터페이스로부터 패킷을 캡쳐하는 함수이다. 캡처된 패킷은 TCP 프로토콜의 경우 Ethernet, IP, TCP 등 모든 헤더와 데이터를 반환한다. 실제 반환되는 값으로는 함수의 성공 또는 실패 여부를 반환한다.

struct pcap_pkthdr {
    struct timeval ts;	/* time stamp */
    bpf_u_int32 caplen;	/* length of portion present */
    bpf_u_int32 len;	/* length this packet (off wire) */
};

struct pcap_pkthdr *header;
const unsigned char *packet;
int res = pcap_next_ex(pcap, &header, &packet);

header에는 해당 패킷 캡쳐된 시간과 길이가 저장되어 있으며 packet에는 캡쳐된 패킷의 헤더들과 데이터의 정보가 담겨 있다.

예제 코드

예제 코드는 캡쳐되는 모든 패킷들의 바이트 수를 출력하는 프로그램이다. 프로그램 실행 시에 인자로 패킷을 캡처할 네트워크 인터페이스의 이름을 넣어주면 동작한다.

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

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", "ens33", 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;
        }
        printf("%d bytes captured\n", header->caplen);
    }
}
$ ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        ...

$ sudo ./main ens33
60 60 bytes captured
98 98 bytes captured
98 98 bytes captured
98 98 bytes captured
98 98 bytes captured
...
반응형

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

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