2011년 5월 12일 목요일

Scapy 에서 텍스트형태의 HEX 패킷 데이터 쉽게 가져다 쓰기

이전 포스팅한 글에서 텍스트로 표현된 패킷을 바이너리로 변환하는 몇 가지 방법에 대해서 소개한 적이 있다. text2pcap 같은 것과 같이 말이다. 오늘은 Scapy 를 이용해 쉽게 로드해서 사용하는 방법을 소개해 본다. 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 기능에 대해서 가끔씩 소개할 예정이다.

P.S 블로그 내에서의 검색 기능이 완벽하지 않아, 제대로 검색이 잘 안되는 편이다. 검색 기능 페이지도 조만간 곧 따로 제공할 예정이다.

댓글 4개:

  1. scapy를 이용해서 패킷을 조작을 편리하게 할 수 있어서 용이한것 같습니다. 아쉬운게 이것을 pcap 파일로 다시 저장을 하는 방법이 같이 내용에 있으면 더 좋을것 같은데 아쉽네요^^;

    답글삭제
  2. 다시 pcap 파일로 저장하고자 하는 경우에는 wrpcap 을 이용하면 됩니다. Scapy 로 검색해 보시면, Scapy를 알아보기 위한 3부 소개가 있습니다. 여기에 보시면 찾아보실 수 있습니다. 가급적 기존에 썻던 글도 참고하시라고 링크를 달아드리려고 하는데, 여기서는 링크가 빠졌네요. ^^

    답글삭제
  3. Torrent 관련 트래픽이 발생되어 tcpdump로 패킷을 뜬다음 scapy로 읽어 들여 보았습니다. scopy에서 다음과 같은 부분이 있는데

    ###[ Raw ]###
    load= '\xde\xc0\x0e\x99\x00\x00>\xf1\x00\n*\x91\xb6\xac\xedCJ\x00\x00>\x99\x01M\xac\xc8\xfc\xfa\xdb\xfb\xc9\xed\xce\xb0\x11\x16\x1a\x8a\x0b\xd...
    해당 Raw는 데이타 인것 같은데 이 부분은 유니코드로 되어 있는 부분인가요? 아니면 디코딩 하는 방법이라도 있는지요?
    Torrent와 같은 데이타를 패킷을 캡쳐하여 분석할 경우 이 패킷은 토렌트관련 패킷이다 라고 확인하는 방법이 있는지? 실제 현업에서 보안장비에 보면 torrent 패킷이라고 로그가 기록이 되는데 과연 어떤것을 분석하여 탐지하는것인지 궁금합니다. 평소에 자주 들려서 많은 도움 되고 있습니다. 감사합니다.

    답글삭제
    답글
    1. \x 다음은 16진수 HEX 값 입니다. 그리고 문자열 형태로 표현된것은 ASCII 값이죠. 기술해 주신 RAW 값만 가지고서는 판단할 수가 없네요.
      토렌트관련 패킷은 사용하는 형태에 따라 다 다르기 때문에 발생되는 트래픽을 가지고서 여러 정보를 통해 판단을 합니다. 포트번호가 될 수도 있고요, 패킷분석기가 파싱해서 보여주면 더 없이 좋겠죠. 보안장비에서 토렌트라고 판단하는것은 해당 토렌트를 충분히 분석하고 해당 패킷만 탐지할 수 있는 시그너처를 제작한 것입니다. 시그너처 제작시에도 똑같이 해당 프로그램을 돌려보고 거기서 발생되는 트래픽에서 시그너처화 할 수 있는 패턴을 추출하게 됩니다. 여기서 이런 부분을 세부적으로 설명하기는 힘들것 같고요, 구글링에서 "snort signature torrent" 정도로 검색해 찾아보시면 스노트에서 사용되는 토렌트 시그너처등을 확인하실 수 있습니다. 해당 시그너처 내용을 보시면 어떠한 패턴을 가지고 차단하는지 감을 잡으실 수 있을것입니다. ^.^ 참고로 공개된 프로토콜은 그 구조를 알 수 있기 때문에 형태에 따라서 패킷을 보고 쉽게 판단이 가능해 집니다.

      삭제