본문 바로가기
코스웨어/12년 내장형하드웨어

[패킷 아날라이저] 10.26 업무일지 -정철

by 알 수 없는 사용자 2012. 10. 26.
728x90
반응형


1025.zip


님햐 내 패킷 훔쳐가지 마삼!



* Libpcap(Portable Packet Capturing Library)


패킷을 캡쳐하기 위한 도구로는 BPF(Berkeley Packet Filter), DLPI, NIT, SNOOP, SNIT, SOCK_PACKET, LSF(Linux Socket Filter), drain등

각 운영체제별로 다양한 도구가 있다. 하지만 여러분이 운영체제별로 패킷을 캡쳐하기 위한 위한 코드를 별도로 구성해야 한다면

시작하기도 전에 포기할지도 모른다.

하지만 이 모든 도구들을 수용하는 Portable한 API가 있는데 이것이 바로 libpcap이다.

라이브러리 사용자는 운영체제의 각기 다른 datalink로의 접근 방법에 상관없이 libpcap을 이용하여 소기의 목적을 달성할 수 있다.

libpcap을 이용한 대표적인 툴이 바로 tcpdump이다.



#include <pcap.h>

를 include 해준다. 하지만 컴파일이 되지 않는다.


/usr/include 디렉토리에서 찾아보지만 pcap.h가 보이지 않는다.

/usr/include/pcap/ 디렉토리에 pcap.h가 있다.


운영체제마다 pcap.h의 위치가 다를 수 있기때문에 확인 후 컴파일 할 것.



1. 랜카드의 이름 알려주는 함수 -> pcap_lookupdev()


원형 : char *pcap_lookupdev(char *errbuf)

리턴값 : 성공시(장치 이름), 실패시(NULL)


네트워크의 디바이스를 가져오는 함수.

가능한 가장 낮은 번호를 가져온다. (리눅스는 아마 eth0을 가져 올 것이다.)


pcap_lookupdev()함수를 이용하여 랜카드의 장치이름을 출력해보았다.



현재 랜카드의 이름이 eth0이라는 것을 알 수 있다.



2. 랜카드를 열어주는 함수 -> pcap_open_live()


원형 : pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to ms, char *ebuf)

리턴값 : 실패시(NULL)


이 함수는 실제로 랜카드를 열어주는 역활을 한다.

첫번째 인자 : 장치의 이름

두번째 인자 : 가져오는 크기

세번째 인자 : 1 -> 아무패킷이나 잡음 , 0 -> 자기 패킷만 잡음

네번째 인자 : 지연시간

다섯번째 인자 : 에러메세지


열었으면 닫아주어야 하는 법



pcap_close()함수를 이용해서 닫아주면 되겠다.



3. 패킷을 호출해 주는 함수 -> pcap_next()


원형 : u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)

리턴값 : const unsigned char *를 반환한다.


패킷을 헥사뷰로 한번 열어보겠다.



뭐 대충 이정도로 열린다.

패킷의 정보를 파악해보도록 한다.



랜카드 타입 추출 -> MAC 어드레스 -> 데이터 타입 추출



1. 랜카드의 타입을 추출 하는 함수 -> pcap_datalink()


원형 : int pcap_datalink(pcap_t *)

반환형 : 정수값


함수 설명에 보면 DLT_EN10MB 같은 것들을 반환한다고 나온다.

/usr/include 에서 grep -r DLT_EN10MB * 을 통하여 어디에 잇는지 찾아냈다.


pcap/net/bpf.h 에 나와있다고 나온다.

가보면 정수값들이 define되어 있다.


이제 ethernet header의 구조에 대하여 알아보록 한다.



우선 패킷의 앞 8byte와 뒤 4byte는 랜카드가 알아서 쳐먹으니까 우리는 Mac Frame 내용을 봐야한다.


첫 6 ,6 byte는 MAC ADDRESS가 위치하는 자리이다.

이자리는 IP가 아니라 장치의 번호를 쓴다.



저기 빨간줄의 HWaddr 하드웨어 어드레스가 MAC frame 어드레스에 들어간다.

친절하게 헤더파일에 구조체를 선언해두었음 ^_^


/usr/include/net/ethernet.h 에 구조체를 선언해 두었다.


뒤에 ETH_ALEN은 define값으로 6이다.


/usr/include/linux/if_ether.h 에 define되어 있다.


그냥 가따 쓰면 되겄다.


이제 data의 타입에 대하여 알아보록한다.

MAC 어드레스가 끝난 지점의 2byte가 data의 타입을 결정하는 녀석이다.


/usr/include/net/ethernet.h에서 ethernet_head 정의 뒤에 바로 나온다.


#여기서 잠깐

: 네트워크의 경우 big enddian을 사용하는 점에 주의하자.

아마 data타입을 출력해보면 IP의 경우 0008로 나올 것이다.


ntohs()함수를 이용하여 little enddian으로 바꾸어준다.



* 패킷의 이동 과정




1. 공유기 MAC 어드레스 <- 내 MAC 어드레스



우선 가장가까운 공유기로 패킷을 내보냄.

공유기가 우리의 MAC 어드레스와 IP를 대조하여 IP를 발급하기 때문에 욜로 보낸다.


2. 야동의 노예 MAC 어드레스 <- 공유기 MAC 어드레스



여기서 IP가 일치 할 경우 야동의 노예에게 야동은 전달된다.


만약 멀리 멀리 나가게 된다면


나 -> 공유기 -> 게이트 웨이 -> 라우터 등등 으로 거쳐 찾아가게 된다.


이과정에서 MAC어드레스는 계속해서 변하지만, IP는 변하지 않게 된다!


728x90