Scapy

지금까지 패킷분석과 관련한 많은 도구들을 언급하였는데, 이 도구를 미처 소개하지 못했다.
강력한 기능과 프로그램적인 면에서도 뛰어난 도구인데말이다. 필자가 오늘 소개하고자 하는 도구는
Scapy 라는 것이다. Scapy 는 인터렉티브하게 패킷을 조작할 수 있는 강력한 기능을 제공하며,
수 많은 프로토콜의 디코딩 기능과 수정된 패킷을 전송할 수 있는 기능등을 포함하고 있다.

이 도구의 큰 장점은 다양한 기능을 수행할 수 있는 것인데, 우리가 흔히 스캐닝을 하거나, 패킷덤프를
하거나, 원격 시스템의 Alive 유무를 점검 또는 공격 패킷등을 만들고자 할때 사용하는 도구들이
다 달라진다. 예를 들면, hping, nmap, arpsoof, tcpdump, tshark, p0f 등의 여러 도구의 기능들 말이다
하지만 Scapy 는 이 도구 하나로 가능하다. 너무 강력한 도구인양 소개한 것일까?

사용용도에 따라 달라지겠지만 무척이나 편리한 기능을 갖고 있는 것은 사실이다. 다만 사용하는데 있어서는
일반적인 도구에 비해서는 사용방법이 처음에는 힘들 수도 있다. Scapy 는 파이썬을 기반으로
작성되어 있는데, 사용형태가 파이썬에서 코드를 사용하는 것과 같이 사용할 수 있으므로
파이썬에 익숙해져 있는 사용자라면 더 없이 편할 것이다. 또한, Scapy 모듈을 이용하여,
파이썬에서 패킷을 핸들링 하는 프로그램을 작성한다면 간단하게 그 기능을 이용할 수 있어
개발자 관점에서도 유용하다.

뛰어나다는 설명보다도 일단 직접 경험해 보는 것이 빠르다.  바로 설치해 보고 각 기능을
사용해 보면 앞서 얘기한 것들이 이해가 될 것이다.

1. 설치

Scapy 2.x 이상의 버전에서는 파이썬 2.5 이상이 필요하다. 그리고 libpcap, libdnet 이 필요하다.
보통 많은 경우에는 이런것들이 이미 설치되어 있으므로 사용하는데 큰 문제는 없을 것이다.

다음의 경로에서 파일을 다운로드 받을 수 있다:


$ unzip scapy-latest.zip
$ cd scapy-2.*
$ sudo python setup.py install

하는 것으로 쉽게 설치가 된다. 파이썬에 익숙한 사용자라면 어렵지 않을 것이다. 또는,
각 시스템에서 제공하는 패키지가 있다면 그것을 이용해도 좋다.

# apt-get install scapy

* 참고로 윈도우 기반에서 사용하고자 한다면, 다음의 문서를 참고하여 실행해 보길 바란다.

2. 간단한 사용 예

실행하게 되면 다음과 같은 화면을 볼 수 있다.

# scapy
WARNING: No route found for IPv6 destination :: (no default route?)
Welcome to Scapy (2.1.0)
>>>

(설치되어 있는 모듈 및 환경에 따라, 경고 메시지가 뜰 수 있는데 무시하고 사용 가능하다.단, 해당 모듈 기능을 사용하지 않는 한)

몇 가지 간단한 기능을 살펴보자!

>>> ls()
ARP        : ARP
BOOTP      : BOOTP
CookedLinux : cooked linux
DHCP       : DHCP options
DNS        : DNS
DNSQR      : DNS Question Record
DNSRR      : DNS Resource Record
....
현재 지원하는 레이어 형태를 볼 수 있다. 쉽게 보면 프로토콜 이다.

다음은 존재하는 PCAP 파일을 오픈하는 것이다. 오픈할 파일을 " 없이 사용하는 경우는 다른 형태로 이해한다.
오픈 후에는 파싱되어 메모리 상에 다 들어가 있으므로 바로 바로 필요한 내용을 꺼내 사용할 수 있다.

>>> a=rdpcap(test.pcap)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
NameError: name 'test' is not defined
>>> a=rdpcap("test.pcap")
>>> a
<test.pcap: TCP:2040 UDP:0 ICMP:0 Other:0>
>>>

파일 전송도 할 수 있는데, 원하는 형태로 마음대로 수정하여 전송이 가능하다. 각 프로토콜 레이어 별로 정보를 기록하고 헤더를 붙일 수 있다. 아래의 경우는 IP 헤더에서 목적지를 1.2.3.4 로 설정하고, ICMP 헤더를 붙인 것이다.

>>> send(IP(dst="1.2.3.4")/ICMP())
.
Sent 1 packets.

전송하기 전 tcpdump 로 확인한 내용을 보면, 목적지 1.2.3.4 로 ICMP 패킷이 전송된걸 확인할 수 있다.

# tcpdump -v icmp
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
09:07:36.479199 IP (tos 0x0, ttl 64, id 1, offset 0, flags [none], proto ICMP (1), length 28) packet > 1.2.3.4: ICMP echo request, id 0, seq 0, length 8

이 정도에서 간단한 맛보기를 언급하고 다음 이어지는 두번째 편에서 좀더 세부적으로 Scapy 기능을 알아보도록 하겠다. 계속 이것저것 소개할 것이 많은데, 정리하고 쓰자니 시간이 꽤 걸리는 거 같다. 이래서 정리는 인내가 필요해지는 것 같다 :-)
 


tcpdump 에서 -xX 와 같이 출력되는 형태의 데이터를 가져오고자 한다.

$ tcpdump -xX -n -r test.pcap

에서 출력되는 다음의 내용을 대상으로 가정해 보겠다.


0x0000:  4500 003e 344e 4000 4011 5d49 c0a8 00f0  E..>4N@.@.]I....
0x0010:  a87e 3f01 bddb 0035 002a 7cef 8555 0100  .~?....5.*|..U..
0x0020:  0001 0000 0000 0000 0377 7777 0667 6f6f  .........www.goo
0x0030:  676c 6502 636f 026b 7200 001c 0001       gle.co.kr.....

대략 추정되는 것과 같이 DNS  패킷이다.  자, 그럼 일단 Scapy 를 실행하고 'IP(import_hexcap())' 를 이용해서 패킷 HEX 데이터를 로드해 보자. tcpdump 의 텍스트 내용을 복사하고 import_hexcap() 를 수행후 그 상태에서, 바로 붙여 넣기를 한다. 그리고 Ctrl+D 를 누른다. Ctrl+C 를 누르면 안된다. 붙여 넣기가 완료되면 그 아래에 바로 해당 값들이 변환되어 Scapy 에서 보기 쉽게 표현해 준다.

Welcome to Scapy (2.1.0)
>>> IP(import_hexcap())
        0x0000:  4500 003e 344e 4000 4011 5d49 c0a8 00f0  E..>4N@.@.]I....
0x0010:  a87e 3f01 bddb 0035 002a 7cef 8555 0100  .~?....5.*|..U..
0x0020:  0001 0000 0000 0000 0377 7777 0667 6f6f  .........www.goo
0x0030:  676c 6502 636f 026b 7200 001c 0001       gle.co.kr.....
^D
<IP  version=4L ihl=5L tos=0x0 len=62 id=13390 flags=DF frag=0L ttl=64 proto=udp chksum=0x5d49 src=192.168.0.240 dst=168.126.63.1 options=[] |<UDP  sport=48603 dport=domain len=42 chksum=0x7cef |<DNS  id=34133 qr=0L opcode=QUERY aa=0L tc=0L rd=1L ra=0L z=0L rcode=ok qdcount=1 ancount=0 nscount=0 arcount=0 qd=<DNSQR  qname='www.google.co.kr.' qtype=AAAA qclass=IN |> an=None ns=None ar=None |>>>
>>>


한눈에 보기 쉽게 정리가 된다. 자, 그럼 이제 무엇을 할 수 있겠는가? 이렇게 로드가 되었다면 이제 이 데이터는 내 마음대로 수정이 가능한 것이다. 데이터는 원하는 형태로 조정하고 전송시킬 수도 있게 되는 것이다. 예를 들어, 아래 그림과 같이 _.show() 해서 보면 패킷 구조를 한눈에 쉽게 파악할 수도 있다.


만약 특정 값을 수정한다면 아래와 같이 쉽게 할 수도 있다. 로드한 값을 a 에 저장하고 UDP 의 목적지 포트인 53을 9999로 변경해 보고 확인한 것이다.

>>> a[UDP].dport
53
>>> a[UDP].dport = 9999
>>> a
<IP  version=4L ihl=5L tos=0x0 len=62 id=13390 flags=DF frag=0L ttl=64 proto=udp chksum=0x5d49 src=192.168.0.240 dst=168.126.63.1 options=[] |<UDP  sport=48603 dport=9999 len=42 chksum=0x7cef |<DNS  id=34133 qr=0L opcode=QUERY aa=0L tc=0L rd=1L ra=0L z=0L rcode=ok qdcount=1 ancount=0 nscount=0 arcount=0 qd=<DNSQR  qname='www.google.co.kr.' qtype=AAAA qclass=IN |> an=None ns=None ar=None |>>>


Scapy 의 활용도는 무궁무진 하다. 패킷 데이터를 쉽고, 간단하게 처리할 수 있으니 이 얼마나 편하던가 :-) 앞으로도 Scapy 기능에 대해서 가끔씩 소개할 예정이다.

// www.packetinside.com/search?updated-max=2011-06-02T00:51:00%2B09:00&max-results=7



+ Recent posts