프로그래밍/패킷 캡쳐
2.1 - 패킷을 잡아보자 !
hackability
2009. 5. 30. 02:14
이번글에서는 패킷을 잡을 수 있는 환경을 만들고 간단히 패킷을 잡아보려고 합니다.
패킷을 잡기 전에 몇 가지 준비를 하셔야 합니다.
1. WinPcap 설치. 네이버에서 WinpCap이라고 검색하시면 쉽게 다운받고 설치 하실 수 있습니다.
2. Include 폴더와 Lib 폴더를 프로젝트 폴더(3번에서 만들 프로젝트)안에 넣습니다.
패킷을 잡기 전에 몇 가지 준비를 하셔야 합니다.
1. WinPcap 설치. 네이버에서 WinpCap이라고 검색하시면 쉽게 다운받고 설치 하실 수 있습니다.
2. Include 폴더와 Lib 폴더를 프로젝트 폴더(3번에서 만들 프로젝트)안에 넣습니다.
3. Visual Studio 2005 에서 콘솔로 프로젝트를 만드신뒤, 빈 main.cpp를 하나 만듭니다.
프로젝트 -> 속성 -> 구성 속성 -> C/C++ -> 일반 -> 추가 포함 디렉토리에 Include 폴더를 추가 합니다.
위와 마찬가지로 프로젝트 -> 속성 -> 구성 속성 -> 링커 -> 일반 -> 추가 라이브러리 디렉토리에 Lib 폴더를 추가 합니다
이제 기본적인 세팅은 끝낫습니다.
소스는 다음과 같습니다.
이제 기본적인 세팅은 끝낫습니다.
소스는 다음과 같습니다.
/*
Modify: 2009 - 05 - 30
Programmed by centy
Blog: http://centy.tistory.com/
E-Mail: ktb88@naver.com
*/
//-- 해더
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include "pcap.h"
#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"wpcap.lib")
//-- 구조체,클래스
// IP 데이터들을 다루기 위한 클래스
class IP_ADDRESS
{
public: // 멤버 변수
UCHAR m_byte1;
UCHAR m_byte2;
UCHAR m_byte3;
UCHAR m_byte4;
public: // 멤버 함수
IP_ADDRESS() {}
~IP_ADDRESS() {}
};
// IP Protocol을 다루기 위한 구조체
typedef struct _IP_HEADER
{
UCHAR ver_ihl; // Version (4 bits) + Internet header length (4 bits)
UCHAR tos; // Type of service
WORD tlen; // Total length
WORD identification; // Identification
WORD flags_fo; // Flags (3 bits) + Fragment offset (13 bits)
UCHAR ttl; // Time to live
UCHAR proto; // Protocol
WORD crc; // Header checksum
IP_ADDRESS saddr; // Source address
IP_ADDRESS daddr; // Destination address
UINT op_pad; // Option + Padding
}IP_HEADER,*PIP_HEADER;
//-- 함수
// initpcap() - 캡처 장치를 초기화 시킨다.
BOOL initpcap();
//-- 전역 변수
pcap_t *adhandle;
struct pcap_pkthdr *header;
UCHAR *pkt;
//-- 프로그램 시작
int main()
{
if( initpcap() == FALSE ) return 1;
int res;
// 패킷을 캡처 한다
while((res = pcap_next_ex(adhandle, &header, (const UCHAR**)&pkt)) >= 0)
{
// 패킷 크기가 0 이면 아무런 행동을 취하지 않는다.
if( res == 0 ) continue;
// 패킷에 ip header를 추출한다. (pkt + ethernet size)
PIP_HEADER ih = (PIP_HEADER) ((UCHAR *)pkt + 14);
// 프로토콜을 검색
switch( ih->proto )
{
case IPPROTO_TCP: // TCP 라면
printf("TCP 패킷 획득 \n");
break;
case IPPROTO_UDP: // UDP 라면
printf("UDP 패킷 획득 \n");
break;
default:
printf("다른 형식 패킷 획득 [%d] \n",ih->proto);
break;
}
}
return 0;
}
BOOL initpcap()
{
pcap_if_t *alldevs;
char errbuf[256];
bpf_u_int32 NetMask;
struct bpf_program fcode;
pcap_if_t *d;
// PCAP 초기화
printf("!] PCAP을 초기화 중입니다... \n");
// 로컬에서 장치 목록을 검사합니다.
if (pcap_findalldevs(&alldevs, errbuf) == -1)
{
printf("?] pcap_findalldevs 에서 문제 발생 \n");
return FALSE;
}
// 선택된 어탭터로 점프 합니다. 보통 마지막이 사용하는 네트워크 카드가 되지만
// 무선인터넷이나 네트워크 카드를 2개 이상 사용한다면 사용자가 선택 할 수 있도록
// 수정되어야 합니다.
for(d=alldevs ; d->next!=NULL ; d=d->next) ;
// 네트워크 카드 출력
printf("!] 네트워크 카드 명 [ %s ] \n",d->description);
// 장치 열기
if ( (adhandle = pcap_open_live(d->name, // 장치 명
65536, // 패킷당 버퍼 사이즈
0, // promiscuous mode
0, // read timeout
errbuf // 에러 버퍼
) ) == NULL)
{
printf("?] [ %s ] 는 winpcap에서 지원하지 않습니다.\n",d->name);
pcap_freealldevs(alldevs); // 장치 목록 해제
return FALSE;
}
pcap_freealldevs(alldevs);
NetMask=0xffffff;
// 필터명으로 컴파일
if(pcap_compile(adhandle, &fcode, "tcp or udp", 1, NetMask) < 0)
{
printf("?] pcap_compile에서 문제 발생 \n");
return FALSE;
}
// 필터 set
if(pcap_setfilter(adhandle, &fcode)<0)
{
printf("?] pcap_setfilter에서 문제 발생 \n");
return FALSE;
}
printf("!] PCAP 초기화 완료... \n");
return TRUE;
}
실행 결과는 다음과 같습니다.
성공입니다! UDP 패킷과 TCP 패킷 그리고 128 Protocol을 사용하는 패킷도 잡히는군요.
그런데 이렇게 보니 뭔가 멋이 없네요.... 다음 글에서 더욱 멋잇게 표현해보도록 하겠습니다. :)