레이블이 packet인 게시물을 표시합니다. 모든 게시물 표시
레이블이 packet인 게시물을 표시합니다. 모든 게시물 표시

2013년 5월 13일 월요일

패킷 데이터를 XML(Extensible Markup Language)로 저장하는 방법은?

패킷 데이터를 저장하는 방법은 다양합니다. PCAP 파일 그 자체가 될 수도 있고, 각 필드를 분리하여 해당 내용만 저장하거나 텍스트 또는 CSV, C 어레이 형태등 다양합니다. 패킷 데이터를 활용하는 방법에 따라 저장 방법의 차이가 있지만 구조화된 XML 로 데이터를 얻을 수는 없을까요?

이런 고민을 했다면 와이어샤크가 한 순간에 해결해 줍니다. 와이어샤크에서 기본적으로 지원하고 있기 때문인데요, 메뉴에서

File->Export->File->as XML - "PSML", "PDML"

위와 같은 경로를 보시면 쉽게 해당 패킷데이터를 XML 로 변경 저장해 줍니다. PSML 은 패킷 요약 정보이고 PDML 은 패킷 상세 정보입니다.

와이어샤크에서 지원하기 때문에 명령어 모드인 tshark 에서도 -T 옵션을 통해 사용가능합니다.

  -T pdml|ps|psml|text|fields
                           format of text output (def: text)

어디한번 패킷요약 정보를 XML 로 살펴볼까요?

# tshark -T psml -r 1.pcap | more
<?xml version="1.0"?>
<psml version="0" creator="wireshark/1.7.0">
<structure>
<section>No.</section>
<section>Time</section>
<section>Source</section>
<section>Destination</section>
<section>Protocol</section>
<section>Length</section>
<section>Info</section>
</structure>

<packet>
<section>1</section>
<section>0.000000</section>
<section>192.168.70.103</section>
<section>192.168.70.101</section>
<section>TCP</section>
<section>66</section>
<section>49239 &gt; ms-wbt-server [SYN] Seq=989508872 Win=8192 Len=0 MSS=1460 WS
=256 SACK_PERM=1</section>
</packet>

우리가 와이어샤크 메인 화면에서 보았던 형태의 구조로 데이터가 저장되어 있습니다. 처음에 각 섹션의 필드가 설명되어있고 <packet> 안에 각 섹션 정보가 들어가 있습니다. 두번째로 상세 정보를 보겠습니다.

# tshark -T pdml -r 1.pcap | more
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="pdml2html.xsl"?>
<!-- You can find pdml2html.xsl in /usr/local/share/wireshark or at http://anons
vn.wireshark.org/trunk/wireshark/pdml2html.xsl. -->
<pdml version="0" creator="wireshark/1.7.0" time="Mon May 13 08:34:45 2013" capt
ure_file="1.pcap">
<packet>
  <proto name="geninfo" pos="0" showname="General information" size="66">
    <field name="num" pos="0" show="1" showname="Number" value="1" size="66"/>
    <field name="len" pos="0" show="66" showname="Frame Length" value="42" size=
"66"/>
    <field name="caplen" pos="0" show="66" showname="Captured Length" value="42"
 size="66"/>
    <field name="timestamp" pos="0" show="Sep  2, 2012 07:36:41.107704000 KST" s
howname="Captured Time" value="1346539001.107704000" size="66"/>
  </proto>
  <proto name="frame" showname="Frame 1: 66 bytes on wire (528 bits), 66 bytes c
aptured (528 bits)" size="66" pos="0">
    <field name="frame.time" showname="Arrival Time: Sep  2, 2012 07:36:41.10770
4000 KST" size="0" pos="0" show="Sep  2, 2012 07:36:41.107704000"/>
    <field name="frame.offset_shift" showname="Time shift for this packet: 0.000
000000 seconds" size="0" pos="0" show="0.000000000"/>
    <field name="frame.time_epoch" showname="Epoch Time: 1346539001.107704000 se
conds" size="0" pos="0" show="1346539001.107704000"/>
    <field name="frame.time_delta" showname="Time delta from previous captured f
rame: 0.000000000 seconds" size="0" pos="0" show="0.000000000"/>
    <field name="frame.time_delta_displayed" showname="Time delta from previous
displayed frame: 0.000000000 seconds" size="0" pos="0" show="0.000000000"/>
    <field name="frame.time_relative" showname="Time since reference or first fr
ame: 0.000000000 seconds" size="0" pos="0" show="0.000000000"/>
    <field name="frame.number" showname="Frame Number: 1" size="0" pos="0" show=
"1"/>
    <field name="frame.len" showname="Frame Length: 66 bytes (528 bits)" size="0
" pos="0" show="66"/>
    <field name="frame.cap_len" showname="Capture Length: 66 bytes (528 bits)" s
ize="0" pos="0" show="66"/>
    <field name="frame.marked" showname="Frame is marked: False" size="0" pos="0
" show="0"/>
    <field name="frame.ignored" showname="Frame is ignored: False" size="0" pos=
"0" show="0"/>
    <field name="frame.protocols" showname="Protocols in frame: eth:ip:tcp" size
="0" pos="0" show="eth:ip:tcp"/>
  </proto>
  <proto name="eth" showname="Ethernet II, Src: Vmware_33:75:1f (00:0c:29:33:75:
1f), Dst: Vmware_8a:43:28 (00:0c:29:8a:43:28)" size="14" pos="0">
    <field name="eth.dst" showname="Destination: Vmware_8a:43:28 (00:0c:29:8a:43


보시는 것과 같이 꽤 많은 정보가 포함되어 있습니다. 이 XML 구조는 필드 이름으로 각 정보가 구분되어 들어가 있는데, 이 필드이름은 출력필터 문법으로 사용되고 있습니다. caplen 은 캡쳐된 길이를 뜻하고 timestampe 는 시간, frame.len 은 프레임 길이 eth.dst 는 이더넷 목적지 맥 주소 ip.id 는 IP 헤더의 Identification, tcp.port 는 TCP 포트 정보와 같습니다. 필드 이름을 보면 쉽게 이해가 되시죠? 출력필터를 그대로 사용하고 있기 때문에 이해가 쉽습니다. 즉, 프로토콜 구조 밑에 각 필드가 들어가는 구조입니다.

<proto name="geninfo">
<field name="num">
<field name="len">
<field name="caplen">
<field name="timestampe">
</proto>
<proto name="frame">
<proto name="eth">
<proto name="ip">
<proto name="tcp">

이제 이런 데이터의 활용은 여러분의 몫 이겠죠?
:-)

2013년 3월 8일 금요일

DaemonLogger 로 패킷 덤프를 쉽게 해보자

간단한 패킷 로그 데몬인 DaemonLogger 를 소개합니다. 다운로드는 Snort 사이트에서 받을 수 있고 현재 버전은 1.2.1 입니다. (예전에 소개한거 같은데 기억이 안나네요. 아무리 찾아도 쓰여졌던 기록은 없네요 ^^)

http://www.snort.org/snort-downloads/additional-downloads#daemonlogger

libpcap 기반으로 만들어져 있으며 크게 2가지 기능을 가지고 있습니다. 첫번째는 일반적으로 패킷을 스니핑 해서 디스크에 기록을 하며,  1G 가 되면 파일을 새롭게 만듭니다. 두번째는 패킷을 다시 Rewrite 하여 다른 인터페이스로 보내는 기능으로 소프트웨어적인 Tapping 과 같다고 할 수 있습니다.

나온지는 사실 오래되었긴 한데, 패킷 덤프만 필요로 하거나 공부할 목적으로 보신다면 괜챦습니다. 설치는 libpcap 과 libdnet 이 있으면 컴파일에 큰 문제가 없습니다.

# ./configure
# make

기본 도움말은 다음과 같습니다.

# ./daemonlogger -h
USAGE: daemonlogger [-options] <bpf filter>
        -c <count>      Log <count> packets and exit
        -d              Daemonize at startup
        -f <bpf file>   Load BPF filter from <bpf file>
        -F              Flush the pcap buffer for each packet
        -g <group name> Set group ID to <group name>
        -h              Show this usage statement
        -i <intf>       Grab packets from interface <intf>
        -l <path>       Log to directory <path>
        -m <count>      Generate <count> log files and quit
        -M <pct>        In ringbuffer mode log data to <pct> of
                        volume capacity
        -n <name>       Set output filename prefix to <name>
        -o <outf>       Disable logging, retransmit data from
                        <intf> to <outf>
        -p <pidfile>    Use <pidfile> for PID filename
        -P <pidpath>    Use <pidpath> for PID directory
        -r              Activate ringbuffer mode
        -R <pcap file>  Read packets from <pcap file>
        -s <bytes>      Rollover the log file every <bytes>
        -S <snaplen>    Capture <snaplen> bytes per packet
        -t <time>       Rollover the log file on time intervals
        -u <user name>  Set user ID to <user name>
        -v              Show daemonlogger version


아무런 옵션없이 실행하면 바로 패킷 덤프가 시작됩니다.

# ./daemonlogger
[-] Log filename set to "daemonlogger.pcap"
[-] Pidfile configured to "daemonlogger.pid"
[-] Pidpath configured to "/var/run"
[-] Rollover size set to 18446744071562067968 bytes
[-] Rollover time configured for 0 seconds
[-] Pruning behavior set to oldest IN DIRECTORY

-*> DaemonLogger <*-
Version 1.2.1
By Martin Roesch
(C) Copyright 2006-2007 Sourcefire Inc., All rights reserved

sniffing on interface eth0
Logging packets to daemonlogger.pcap.1362698542


따로 경로를 지정하지 않았다면 현 경로에 daemonlogger.pcap.[타임스탬프] 형태로 기록이 됩니다. 몇가지 주요 기능들을 한번 보면 다음과 같습니다.

-c 는 몇개의 패킷을 기록하고 빠져나갈것인지 정의합니다. -d 는 백그라운드로 데몬 형태로 동작합니다. -f 를 통해 BPF 필터가 적용된 파일을 로드할 수 있고 -i 로 패킷 덤프할 인터페이스 그리고 -l 로 기록될 로그 파일 경로를 설정합니다. -s 는 얼마 크기로(바이트 단위) 파일을 롤오버할지 지정하고 -t 는 시간 인터벌로 롤오버를 할 수 있습니다. -n 은 파일이름으로 사용할 것을 지정하는데 기본은 damonlogger.pcap 입니다. -n packetinside 라고 지정하면 packetinside.1362698110 과 같이 생성이 됩니다.

그리고 말씀드렸던 두번째 주요기능으로 다른 인터페이스에 재 전달할 수 있다고 드린 기능은 -o 로 인터페이스를 지정하면 됩니다. 즉 이것은 데이터를 기록하지 않고 바로 지정된 인터페이스로 전달합니다.

# ./daemonlogger -i eth0 -o eth2

간단한 도구라서 쉽게 사용할 수 있으니 참고하세요. 참고로 이와 비슷한 도구들을 블로그에서 많이 소개하였으니 다른 것도 살펴보세요.

즐거운 주말 보내세요 ;-)

[참고]
1. Libdnet
http://libdnet.sourceforge.net/

2012년 1월 19일 목요일

기가비트 환경에서 패킷덤프 손실을 줄여보기 위한 도구, GULP

기가비트 환경에서 손실없이 패킷을 잡아내기 위한 방법들은 무엇이 있을까? 여러가지 것들이 있을 수 있겠지만, 우리가 흔히 사용하고 있는 리눅스 시스템에서 특별한 변경없이 간단하게 사용할 수 있는 도구 하나를 소개해 볼까 한다. 도구 하나만으로 완벽한 손실없이 패킷을 잡아내기에는 여러가지 환경적 제약이 따른다. 그러므로, 최대한 손실을 줄이면서 패킷을 잡아낼 수 있는 방법을 고민해야 하는데, 스레드 기반의 GULP 가 도움이 되지 않을까 한다.

이 도구를 만든 배경 및 세부적인 정보는 다음 URL 에서 얻을 수 있다.

http://staff.washington.edu/corey/gulp/

비교적 작성된지가 오래되었으므로 이점을 감안하기 바란다.

컴파일은 간단히 make 를 하는 것 만으로도 어렵지 않게 결과를 얻어낼 수 있다.

# make
cc -O    check64bit.c   -o check64bit
./check64bit; rm -f check64bit


If output from Gulp is not compatible with tcpdump or wireshark,
Please see: http://staff.washington.edu/corey/gulp/gulp.html#64bit


cc -g -O gulp.c -o gulp -lpthread -lpcap

실행해 보면 아래와 같은 도움말 정보를 얻을 수 있다.

$ ./gulp
./gulp: Sending raw pcap data to a terminal is not a good idea.
        If you really want to do that, pipe ./gulp through cat but you
        probably want to redirect stdout to a file or another program instead.
        Perhaps you meant to pipe into 'tcpdump -r-' or 'ngrep -I-' ?

Usage: ./gulp [--help | options]
    --help      prints this usage summary
    supported options include:
      -d        decapsulate Cisco ERSPAN GRE packets (sets -f value)
      -f "..."  specify a pcap filter - see manpage and -d
      -i eth#|- specify ethernet capture interface or '-' for stdin
      -s #      specify packet capture "snapshot" length limit
      -r #      specify ring buffer size in megabytes (1-1024)
      -c        just buffer stdin to stdout (works with arbitrary data)
      -x        request exclusive lock (to be the only instance running)
      -X        run even when locking would forbid it
      -v        print program version and exit
      -Vx...x   display packet loss and buffer use - see manpage
      -p #      specify full/empty polling interval in microseconds
      -q        suppress buffer full warnings
      -z #      specify write blocksize (even power of 2, default 65536)
    for long-term capture
      -o dir    redirect pcap output to a collection of files in dir
      -C #      limit each pcap file in -o dir to # times the (-r #) size
      -W #      overwrite pcap files in -o dir rather than start #+1
    and some of academic interest only:
      -B        check if select(2) would ever have blocked on write
      -Y        avoid writes which would block

여러 패킷 덤프 도구들을 사용해 보았다면 옵션만 보아도 어렵지 않게 사용할 수 있다. 참고로 덤프되는 데이터를 바로 터미널에 출력하는 것은 권장 되지 않으므로, 파일로 리다이렉션 하거나 또는 tcpdump, ngrep 과 같은 프로그램으로 리다이렉션 하는 것이 좋다

다음예는 , -i 로 덤프할 인터페이스를 지정하고 '>' 로 파일로 저장하고 있다.

#./gulp -i eth0 > tt

덤프된 파일의 타입을 살펴보면 캡쳐파일임을 알 수 있고 tcpdump 프로그램으로 확인할 수 있다.

# file tt
tt: tcpdump capture file (little-endian) - version 2.4 (Ethernet, capture length 65535)
# tcpdump -r tt
reading from file tt, link-type EN10MB (Ethernet)

다시 패킷을 덤프하는 과정에서 중지하고 살펴보면 12만개 패킷 중 31 개의 패킷이 drop 되었다. 추가로 나오는 정보에서 이런 drop 되는 패킷을 줄이기 위하여 rmem_max 와  rmem_default 값을 늘려주기를 권장하고 있다.

참고로  이전에 작성한 다음 블로그 글을 참고하여 파라미터 값을 조정하면 도움이 될 것이다.

[링크] 커널에서 drop 되는 패킷 수가 많다면...

# ./gulp -i bond0 > tt2
^C
121313 packets captured
121343 packets received by filter
31 packets dropped by kernel

Note ./gulp may drop fewer packets if you increase:
  /proc/sys/net/core/rmem_max and
  /proc/sys/net/core/rmem_default
to 4194304 or more

ring buffer use: 1.8% of 100 MB

느낌상으로는 다른 캡쳐 도구에 비해 손실이 적어 보이기도 한다. 그래서 tcpdump 와 gulp 로 테스트를 해 보았다.

# tcpdump -i bond0 -n -s 1514 -w tt
tcpdump: listening on bond0, link-type EN10MB (Ethernet), capture size 1514 bytes
^C207292 packets captured
208468 packets received by filter
1176 packets dropped by kernel

# ./gulp -i bond0 -s 1514 > tt5
^C
240675 packets captured
240674 packets received by filter
0 packets dropped by kernel
ring buffer use: 0.8% of 100 MB

위 결과를 보면 tcpdump 에서는 1176 개의 패킷이 drop 된 것에 비해 gulp 에서는 한개의 패킷도 drop 되지 않았다.  간단한 결과만 보아도 단순 패킷덤프에서는 gulp 가 tcpdump 보다 우수하다.
gulp 에서 패킷이 유실되는 개수 및 RingBuffer 사용률을 같이 볼 수 있는데 -Vx 를 추가로 주고 덤프를 해 보면 된다.

# ./gulp -i bond0 -Vx > tt3
pkts dropped: 0, ring buf: 0.0%, max: 0.1%
pkts dropped: 0, ring buf: 0.0%, max: 0.1%
pkts dropped: 0, ring buf: 0.1%, max: 0.1%
pkts dropped: 0, ring buf: 0.0%, max: 0.1%
pkts dropped: 0, ring buf: 0.0%, max: 0.1%
pkts dropped: 0, ring buf: 0.0%, max: 0.4%
pkts dropped: 0, ring buf: 0.1%, max: 0.4%
pkts dropped: 0, ring buf: 0.1%, max: 0.4%
pkts dropped: 0, ring buf: 0.0%, max: 0.4%
pkts dropped: 0, ring buf: 0.0%, max: 0.4%
pkts dropped: 0, ring buf: 0.0%, max: 0.4%
pkts dropped: 0, ring buf: 0.1%, max: 0.4%
pkts dropped: 0, ring buf: 0.0%, max: 0.4%
pkts dropped: 0, ring buf: 0.0%, max: 0.4%
pkts dropped: 0, ring buf: 0.0%, max: 0.4%
pkts dropped: 0, ring buf: 0.1%, max: 0.4%
^Cpkts dropped: 0, ring buf: 0.1%, max: 0.4%

27455 packets captured
27454 packets received by filter
0 packets dropped by kernel
ring buffer use: 0.4% of 100 MB

패킷 데이터를 바로 파일로 저장하는 것 외에 프로그램으로 리다이렉션 하여 다음과 같이 사용할 수도 있다.

# ./gulp -i bond0 | tcpdump -r - -w tt4
# ./gulp -i bond0 | ngrep -I - www

그럼 어떤면에서 gulp 가 더 우수한 성능을 보여줄까 ? gulp 를 백그라운드로 실행하고 해당 프로세스를 찾아 strace 로 살펴보았다.

# ./gulp -i bond0 -s 1514 > tt5 &
[2] 5798
# ps -ef | grep gulp
root      5798 18450  0 14:32 pts/1    00:00:00 ./gulp -i bond0 -s 1514
root      6749 18450  0 14:33 pts/1    00:00:00 grep gulp
# strace -p 5798
Process 5798 attached - interrupt to quit
restart_syscall(<... resuming interrupted call ...>) = 0
nanosleep({0, 500000000}, NULL)         = 0
nanosleep({0, 500000000}, NULL)         = 0
nanosleep({0, 500000000}, NULL)         = 0
nanosleep({0, 500000000}, NULL)         = 0
nanosleep({0, 500000000}, NULL)         = 0
nanosleep({0, 500000000}, NULL)         = 0
nanosleep({0, 500000000}, NULL)         = 0
nanosleep({0, 500000000}, NULL)         = 0
nanosleep({0, 500000000}, ^C <unfinished ...>
Process 5798 detached

nanosleep 만이 계속 보인다. 무엇인가 계속 기록하고 해야 할텐데, nanosleep 만 보인다? 혹시 스레드를 사용하는 것일까? 그렇다. 다음과 같이 스레드 카운트를 확인해 보면 3개로 보인다.

# ps -o pid,comm,thcount 5798
  PID COMMAND         THCNT
 5798 gulp                3

이와 달리 같은 형태로  tcpdump 를 살펴보자.

# tcpdump -i bond0 -n -s 1514 -w tt6 &
[2] 9793
# tcpdump: listening on bond0, link-type EN10MB (Ethernet), capture size 1514 bytes

# ps -ef | grep tt6
root      9793 18450  0 14:35 pts/1    00:00:00 tcpdump -i bond0 -n -s 1514 -w tt6
root     10080 18450  0 14:35 pts/1    00:00:00 grep tt6

# strace -p 9793
write(4, "\245\1(\37\315Y\265\206\207\fa\315\257\26\1771u\265\240\223\30309A0\304\362\\\257\7k>~"..., 4096) = 4096
recvfrom(3, "\0\33!R\3334\0PV\250]5\10\0E\0\0(\v\"@\0\200\6Hzo\3\4\22\314\240g"..., 1514, MSG_TRUNC, {sa_family=AF_PACKET, proto=0x800, if10, pkttype=PACKET_HOST, addr(6)={1, 005056a85d35}, [18]) = 60
ioctl(3, SIOCGSTAMP, 0xbfffec18)        = 0
recvfrom(3, "\0PV\250]5\0\33!R\3334\10\0E\0\5\320w+@\0@\6\26\311\314\240g~o\3\4"..., 1514, MSG_TRUNC, {sa_family=AF_PACKET, proto=0x800, if10, pkttype=PACKET_OUTGOING, addr(6)={1, 001b2152db34}, [18]) = 1502
ioctl(3, SIOCGSTAMP, 0xbfffec18)        = 0
recvfrom(3, "\0PV\250]5\0\33!R\3334\10\0E\0\5\320w,@\0@\6\26\310\314\240g~o\3\4"..., 1514, MSG_TRUNC, {sa_family=AF_PACKET, proto=0x800, if10, pkttype=PACKET_OUTGOING, addr(6)={1, 001b2152db34}, [18]) = 1502
ioctl(3, SIOCGSTAMP, 0xbfffec18)        = 0
write(4, "R\370\377\3627\t\2\275\230\22G\321\27414\0172\0\341\224(\4rb\326\275\322\246\333\270\303e\200"..., 4096) = 4096
recvfrom(3, "\0\33!R\3334\0PV\250]5\10\0E\0\0(\v#@\0\200\6Hyo\3\4\22\314\240g"..., 1514, MSG_TRUNC, {sa_family=AF_PACKET, proto=0x800, if10, pkttype=PACKET_HOST, addr(6)={1, 005056a85d35}, [18]) = 60
ioctl(3, SIOCGSTAMP, 0xbfffec18)        = 0
recvfrom(3, ^C <unfinished ...>

무엇인가 아주 바쁘게 기록을 하며 움직이고 있다. 스레드 카운트를 확인 해보면 1 이다.

# ps -o pid,comm,thcount -p 9793
  PID COMMAND         THCNT
 9793 tcpdump             1

즉, GULP 는 스레드로 동작하여 파일 기록시에도 별도의 스레드로 처리하여 더 높은 성능을 나타내고 있는 것이다.

기가비트 네트워크에서는 트래픽 양이 워낙 많기 때문에 운영체제의 네트워크 파라미터를 최적화 하고, 적절한 패킷 캡쳐 도구를 선택해야 한다. 사용환경과 패킷캡쳐의 목적에 따라서 달라지겠지만, 자기에게 맞는 적절한 도구를 테스트해보고 선택하여 사용하면 될 것이다.

2011년 12월 12일 월요일

네트워크에서 흘러다니는 이미지파일 출력해주는 Driftnet

Mac 환경에서 네트워크에서 흘러다니는 이미지 파일을 보여주는 도구인 EtherPEG 가 있다.
이와 유사하게 *NIX 환경에서 사용할 수 있는 Driftnet 이 있다. Driftnet 은 네트워크 트래픽을 모니터링 하다 TCP 스트림에서 이미지 파일이 발견되면 출력해서 보여준다.

다음 URL 에서 소스를 받아다 컴파일 하거나 또는 패키지로 driftnet 을 설치하면 된다.

http://www.ex-parrot.com/~chris/driftnet/

실행하면 Driftnet 화면이 하나 나타나며, 이미지 파일을 보여준다. 다음 예제는 구글 이미지에서 packet 으로 검색해본 것이다.



-v 옵션으로 보면 콘솔 상태에서 좀더 세부적인 정보를 볼 수 있는데, 아래와 같이 탐지된 이미지 파일이 저장되는 것을 알 수 있다. 하지만, 직접 해보면 아주 결과가 좋아보이지는 않는다. 생각보다 실시간적으로 이미지 표시가 잘 안되는것 같았다.

이런 형태의 도구도 있으니 참고하기를 바란다.
[참고]

2011년 10월 10일 월요일

실시간으로 트래픽 사용량 깔끔하게 표시해 주는 'pktstat'

인터페이스별 패킷 상태 정보를 실시간으로 요약해 주는 'pktstat' 를 소개한다. Curses 기반으로 실행하게 되면 실시간으로 상태 정보를 업데이트 해 주어서 통신 접속상태별로 사용되는 트래픽 사용량을 보여준다. 사용방법도 간단해서 심플하게 트래픽 사용현황을 모니터링 하기에는 적합하다. 일단 출력되는 화면을 살펴보면 아래 그림과 같다:



설치는 간단히 apt-get install pktstat 와 같이 하면 되고, 다른 리눅스 패키지에서는 그에 적합한 패키지 설치 방법을 이용하면 된다.

-B 옵션은 bps 대신 바이트 기준으로 Bps 형태로 보여준다. -i 는 인터페이스를 지정하고 -p 는 비트 카운트 대신 패킷 카운트로 보여주며(즉 PPS 기준), -T 는 전체 토탈 전송량도 표시해 준다. 그리고 필터 옵션을 사용할 수가 있는데, 특정 포트인 80 번으로 제한한다고 치면

# pktstat -i eth0 -T "port 80"

과 같이 하면 된다. 필터를 잘 사용하면 원하는 형태별로 볼 수 있으므로 네트워크 관리자 입장에서는 유용하게 사용될 수 있으리라 생각된다. 실시간으로 업데이트되는 화면에서는 다음과 같은 키를 사용할 수도 있다.

           q           quit
           Ctrl-L      redraw screen
           t           toggle the -t flag (top mode)
           T           toggle the -T flag (totals mode)
           w           allows changing of the -w flag value (wait time)
           n           toggle the -n flag (numeric display)
           p           toggle the -p flag (packets instead of bits)
           b | B       toggle the -B flag (bps or Bps)
           f | F       toggle the -F flag (full hostnames)
           r           reset collected statistics (min, max, etc.), flush flow
                       history and reset DNS/service and fragment caches
           l           show and sort flows by when they were last active
           ?           toggle display of help/status text at the bottom of the
                       display

2011년 9월 28일 수요일

한 컴퓨터에서 발생시킨 트래픽 기준은 무엇으로 잡아야 할까?

패킷 분석을 하다보면, 문제가 되는 컴퓨터에서 발생시키는 트래픽이 얼마나 되는지 측정할 때가 있다. 네트워크 라는 넓은 범위에서 트래픽을 관찰하는 것이라면, 네트워크 관리자가 보게되는 것이 IP 주소 기준이 되기 때문에 해당 컴퓨터에서 발생하는 모든 트래픽이 기준이 될 것이다. 그런데, 컴퓨터내에서 특정한 프로세스가 발생시키는 트래픽에 대한 수치가 필요한 경우도 있다. 사실 특정 IP 에서 발생시키는 것은 여러 브로드캐스팅 부터 기타 네트워크 연결상에서 발생되는 일반적인 모든 트래픽을 다 포함시키기 때문에, 정확히 측정하고자 하는 수치가 어떤 것이냐 하는 점은 약간 모호한 점이 있다.

분석이라는 관점에서 보면 이런 수치가 필요한 경우가 무엇이 있을까 생각해 본다면, 분명 분석이 필요한 부분이 있을 것이라는 가정이 선다. 예를들어, 악성코드에 감염되어 사용자 본인의 의도와는 상관없이 트래픽이 발생될 수 있고, 또는 특정 프로그램에 의해서 발생되거나 잘못된 프로그램 등 여러 가능성들이 있다.  자~ 이런 관점에서 이것들이 발생시키는 트래픽을 측정하고자 할때는 발생시킨 트래픽을 구분하고 이에 대한 값들을 수치로 뽑아낼 수 있다. 평균 패킷 발송 개수, 초당 전송량, 평균 패킷 사이즈 등과 같이 데이터 말이다.

악성코드에 의해 감염된 것을 가정하고 이런 트래픽 수치를 산출한다고 했을때, 한 가지 명확히 해야 할 부분이 있을것 같다. 필자도 그냥 다른것은 생각치 않고 발생된 패킷 데이터를 가지고 수치를 뽑았는데 이런 생각이 들었다.

- 악성코드 자체가 순수하게 발생시킨 트래픽이 있을 수 있으며
- 악성코드 자체가 발생시킨 트래픽이 통신 과정을 이뤄내는 과정 까지 포함된
부분이 있을 수 있다.

자, 여기서 보는 관점에 따라 달라지겠지만 악성코드를 분석하는 분석가가 정보를 기술한다는 점에서는 악성코드가 순수하게 발생시키는 트래픽을 기준으로 할 때가 올바를 것이다. 외부의 요인이 결합되지 않고 그 자체가 발생시킨 데이터 말이다.

하지만, 트래픽을 발생시킨다는 것은 다른 목적지와의 통신과정이 있다는 것이다. 웹 서비스 포트인 80 번포트로 패킷이 발송되었을 때 TCP 3-Way Handshake 과정을 다 포함시키면 최소 몇개 이상으로 패킷 개수는 늘어난다. 악성코드 관점에서만 보면 80 번포트로 발생시킨 트래픽 한개일 뿐이지만 말이다. 그런데 또 목적지 포트에 도달할 수 없는 상황이라면 상황은 또 달라진다.

이렇게 요약해 볼 수 있다.

- 악성코드가 순수하게 Request 한 패킷 기준
- 악성코드가 순수하게 Request 한 패킷 기준이지만 통신 과정이 다 포함되는 경우
* 단, 악성코드가 실행된 시간과 얼마동안 동작했느냐에 따라 이 수치는 크게 영향을 받을 수 있다.

분석가 관점에서라면 첫번째가 더 의미 있을 수도 있지만, 현실적으로 트래픽이 폭증하여 대처를 해야 하는 네트워크 운영자 관점에서는 두번째가 더 의미 있다.
필자가 이런 이야기를 한번 다루는 것은 분석이 되어 만들어 지는 데이터 수치가 각기 다른 경우가 발생되어 발표된다는 점 때문이다.  어느 기준을 가지고 만들어 져야 할까 ? 첫번째 경우는 악성코드 자체만을 가지고 봤을때 가정 정확한 데이터이고, 두번째는 현실적인 대처에 포함된다.  보통의 경우 두번째로 쓰이는 경우가 많은것 같다. 더 정확히 하기 위해서라면 트래픽 수치를 다루는 경우 발생된 환경과 기준을 명확히 명시해 주는 것이 가장 좋은 방법이라 생각된다.

이거외 다른 사례도 발생되는 경우가 있는데, 트래픽 기준을 잡는데 특정 위치에서 덤프된 모든 트래픽 데이터를 가지고, 이 악성코드가 발생시킨 것으로 단순히 간주하는 경우도 있다. 즉 이 데이터 수치가 ' XX 악성코드' 가 발생시킨 트래픽이다 하고 정의해 버린 것이다. 이렇게 되면 대당 컴퓨터가 발생시키는 수치 자체에도 큰 변화가 생겨 잘못된 정보를 만들어 낸다. 실제 발생되는 컴퓨터에서 발생된 기준과, 전체 네트워크에서 다 덤프한 데이터를 가지고 하는 수치 측정은 분명히 다르다.

트래픽에 대한 수치를 뽑을 때는 분명 그 기준이 명확하고 동일하게 적용되어야 한다는 점을 말해보고 싶었다.

From Rigel

2011년 6월 27일 월요일

자동화된 패킷분석의 어려움을 이야기 해보자!

패킷분석을 주 업무로 하는 사람이라면, 그들만의 도구를 가지고 있거나 방법이 있을 것이다. 특히나 분석할 패킷파일 대상이 많다면, 더욱 더 자동화된 기능이 필요하다. 하지만, 자동화된 방법으로 개발하여 사용하다 보면 어려움이 많이 발생할 경우가 많다. 대표적인 것이, 주어진 프로토콜 형식에 맞지 않는 패킷파일이다.

이건 보안적인 관점에서 봐도 발생되는 같은 이치인데, 대표적인 SQL Injection 을 생각해 보자.
웹 개발을 할때, 개발자가 생각한 것 이외의 값이 들어오지 않을 것이라 가정하고, 개발하면서 보안적인 문제점이 생긴다. 프로그램 관점에서 정해진 폼에 따라 사용자가 데이터를 입력하면 아무런 문제가 없을 것이다. 하지만, 사용자가 인자값을 직접 수정할 수도 있다는 가정이 되어야 한다. 인자값을 임의로 수정해 전송해 버리면, 프로그램에서는 그 값에 대한 체크가 없는 이상 사용자가 정상적으로 입력한 값으로 인지해 버려 SQL Injection 과 같은 취약점이 발생되어 버린다.

패킷파일도 마찬가지이다. 나 또한 보안적 관점에서 패킷 파일 분석을 수행하다 보면,이 패킷파일들이 별에별 형태로 다양하다는 것이다. 악성코드가 생성한 패킷파일이면 더욱 그러하다. 예를 들어, DNS 는 UDP 53 번을 기본으로 사용한다. 그리고 Zone Transfer 와 같은 상황등에서는 TCP 53 번을 사용하기도 한다. 흔히, UDP 53 번을 사용하면 DNS 데이터라고 가정한다. 그런데, DNS 가 아닌 어뚱하게도 어떤 통신을 위해 사용되는 것이라면 어떨까? DNS 쿼리 데이터의 일정 값을 사용하는데 이상하게도 알수없는 페이로드로 채워져 있다면 말이다.

패킷분석을 수행하는 도구 입장에서는 DNS 로 판별했는데, 실제 데이터가 정확하지 않아 Exception 과 같은 오류가 발생할 수 있다. 이런류의 패킷파일 데이터 판단은 힘들어지는데, 실제 이 패킷 데이터를 알아내기 위해서는 직접 악성코드를 리버싱을 해야 정확한 데이터 의미를 파악할 수 있게된다.

비정상적인 DNS 데이터를 가지고 있는 패킷파일을 Scapy 를 통해서 확인해 보면 아래와 같다.

>>> a=rdpcap("test_dns.pcap")
WARNING: wrong value: DNS.ancount=38440
WARNING: wrong value: DNS.nscount=27668
WARNING: more wrong value: DNS.arcount=45458
WARNING: DNS RR prematured end (ofs=73, len=44)
WARNING: DNS RR prematured end (ofs=77, len=44)
WARNING: more DNS RR prematured end (ofs=81, len=44)

자 일단 읽어 들이는 과정에서도 경고 메시지가 나타난다. DNS 의 ancount 나 nscount 값이 지나치게 크게 나온다는 것이다.

>>> a
<test_dns.pcap: TCP:6 UDP:1115 ICMP:0 Other:28>

다음은 패킷파일 중 정상적인 DNS 패킷 데이터를 본 것이다.

>>> a[1145]
<Ether  dst=[삭제] src=[삭제] type=0x800 |<IP  version=4L ihl=5L tos=0x0 len=68 id=956 flags= frag=0L ttl=128 proto=udp chksum=0x52c9 src=[삭제] dst=[삭제] options=[] |<UDP  sport=1039 dport=domain len=48 chksum=0xfdec |<DNS  id=52467 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='1.1.1.1.in-addr.arpa.' qtype=PTR qclass=IN |> an=None ns=None ar=None |>>>>

정상적인 형태는 각 필드정보가 정확히 확인이 된다. 그런데, 아래의 경우를 보면 다르다.
몇몇 필드의 데이터 값이 이상하고, Raw 페이로드 값이 존재한다.

>>> a[176]
<Ether  dst=[삭제] src=[삭제] type=0x800 |<IP  version=4L ihl=5L tos=0x0 len=84 id=16541 flags= frag=0L ttl=24 proto=udp chksum=0xfe73 src=[삭제] dst=[삭제] options=[] |<UDP  sport=domain dport=7783 len=64 chksum=0xf167 |<DNS  id=56 qr=0L opcode=QUERY aa=0L tc=1L rd=1L ra=0L z=1L rcode=server-failure qdcount=0 ancount=38440 nscount=27668 arcount=45458 qd=None an='' ns='' ar='' |<Raw  load='$\xabn\x00z\xb6\x0bl\x98Q\xff\x87\xf9\xe2\xd0\xaeu\xa2[삭제]0305rh\x02\xbe\x18\xc0\x00\x00' |>>>>>
>>>

HEX 값을 확인해 보면 아래와 같다.

>>> hexdump(a[176][Raw])
0000   24 AB 6E 00 7A B6 0B 6C  98 51 FF 87 F9 E2 D0 AE   $.n.z..l.Q......
0010   75 A2 [삭제] 3 37 37 42   u..[삭제]C77B
0020   30 33 30 35 72 68 02 BE  18 C0 00 00               0305rh......

ancount, nscount 가 이렇게 큰 데이터를 가질 수 있는가? 즉, 큰 데이터 값만 보고도 조작된 패킷 가능성이 크다고 볼 수 있다. 그러므로 Scapy 에서도 로드할때 경고 메시지가 나타난다. UDP/53 번에 패킷을 전송하니 이것을 DNS 패킷으로 인식하고 그 값 데이터를 필드 값으로 사용하면서 엉뚱하게 이상한 값으로 설정된 것이다.

이와 같은 경우에는 다양한 Exception 처리를 해 주어야 하는데, 어떤 형태가 들어오기 예측하기 쉽지 않다보니 특수한 환경의 패킷 분석에서는 상당한 어려움이 발생할 수 있다. 이러한 이유로 어떤 자동화된 형태로 패킷을 분석 처리하기에는 많은 경험도 필요하고, 각각의 상황에 따라 처리도 해주어야 하다 보니 안정화 되기까지는 시간도 필요하다. 물론, 안정화 후에도 계속 이런 가능성은 존재하게 된다.  사용하려는 목적은 다르겠지만, 완벽하게 패킷 데이터를 분석하여 사용한다는 관점보다는 좀더 쉽게 패킷 분석가를 도와준다는 관점에서 생각하고 사용하면 이런 작업을 진행하는 분들에게는 좀더 마음이 편해지지 않을까?

/Rigel

2010년 12월 24일 금요일

스노트(Snort) 룰을 파싱하여 패킷 생성, 전송하기

IDS 로 많이 사용중인 오픈소스 스노트가 있다. 스노트로 제작된 관련 탐지 룰도 많이 찾아 볼 수 있고, 실제 무료/상업용 침입차단 패턴이 이 스노트 형태의 기반이 많다. 여기서 스노트를 다룰 것은 아니다. 다만, 패킷 분석이 많이 사용되는 영역중에 하나로 어떤 위협을 차단/탐지 하기 위한 패턴 작성을 빼 놓을 수 없다.

네트워크 상에서 흘러다니는 트래픽을 정확히 분석 판단하고 어떤 부분을 패턴으로 뽑아내어 사용할 것인가는 단순한 것부터 복잡한 것까지 다양하다.

시그너처 패턴 작성 후 올바로 탐지하는 것을 테스트 하기 위해 트래픽을 재 전송해 보고 한다. 이미 여기서 언급한 tcpreplay 나 기타 도구를 이용해 재전송해보는 것으로 내가 만든 패턴이 올바른지 확인할 수 있다.

앞서 소개한 PackIt 도구에서 유용한 유틸리티가 하나 있다. 그것은 스노트 룰을 PackIt 명령어로 만들어, 패킷을 전송할 수 있도록 도와주는 것이다. 스노트 룰의 QA 등과 같은 업무에는 나름 유용하게 사용할 수 있을 것이다.

다운로드는 다음의 경로에서 가능하다.

http://packetfactory.openwall.net/projects/packit/s2pgen.pl

이 파일은 펄(Perl) 스크립트로 간단히 만들어져 있는 것으로 룰 파일을 지정하면, packit 으로 검증해 볼 수 있게 명령어를 만들어 준다. 파일을 열어 첫 시작부분을 보면 주소 설정을 정의하는 부분이 있다. 시그너처 파일에서 룰을 읽어들여 파싱할때 필요한 기본 정보이다. 이 정보들만 여러분들의 네트워크 상황에 맞게끔만 조절하여 사용하면 된다.


# Defaults
$DEFAULT_PACKIT     = "packit";
$DEFAULT_ADDR       = "10.0.0.1";
$DEFAULT_DATA       = "R";

# Host/Port definitions
$EXTERNAL_NET_ADDR  = "10.0.0.1";
$HOME_NET_ADDR      = "192.168.0.4";
$HTTP_SERVER_ADDR   = "192.168.0.2";
$SQL_SERVER_ADDR    = "192.168.0.3";
$SMTP_SERVER_ADDR   = "192.168.0.4";
$TELNET_SERVER_ADDR = "192.168.0.5";
$AIM_SERVER_ADDR    = "192.168.0.6";
$ORACLE_PORT        = "1521";
$HTTP_PORT          = "80";
$SHELLCODE_PORT     = "81";

우선 스노트에서 제공하는 기본 룰 파일중 하나인 ddos.rules 파일을 가지고 만들어 보면 아래와 같다 :


# ./s2pgen.pl ddos.rules
echo

echo DDOS TFN Probe
packit -t icmp -s10.0.0.1 -d192.168.0.4 -p "0x 31 32 33 34" -SR -DR    -K 8  -N 678

echo DDOS tfn2k icmp possible communication
packit -t icmp -s10.0.0.1 -d192.168.0.4 -p "0x 41 41 41 41 41 41 41 41 41 41" -SR -DR    -K 0  -N 0

echo DDOS Trin00 Daemon to Master PONG message detected
packit -t udp -s10.0.0.1 -d192.168.0.4 -p "0x 50 4f 4e 47" -SR -D31335

echo DDOS TFN client command BE
packit -t icmp -s10.0.0.1 -d192.168.0.4  -SR -DR    -K 0  -N 456 -Q 0


packit 을 통해 보내기 전 echo 로 어떤 패킷인지 출력해 주고 packit 명령어로 전송할 패킷 정보를 만들어 준다. 그리고, 스노트에서 탐지가 되는지 확인해 보면 된다.

시그너처 제작 업무를 하는 이들에겐 나름 도움이 될 것이다. 또는 이를 변형하여 원하는 형태의 도구를 이용하여 만들어보는 것은 어떨까?

2010년 12월 13일 월요일

네트워크 패킷분석 블로그, 패킷인사이드가 1주년이 되었습니다~

네트워크 패킷 분석 관련 블로그를 시작한지, 어느덧 1년이 되었습니다.
처음으로 쓴 글을 보니 2009년 12월10일 이네요. 패킷 관련한 주제로는 많은 글들을 보지 못해서,
기록을 남기고자 시작하였고, 지금 보니 그래도 많이 작성했네요.

그리고, 1년안에 방문자 10만명을 달성하였습니다.

총방문자101,805

초기에는 방문자가 없었는데 말이죠, 지금은 꾸준히 매일 300-500 명이 방문해 주십니다.
요새는 패킷 주제 뿐만 아니라 더 범위를 넓혀서 이것저것 쓰고 있기도 하지만, 그래도 큰 주제는
패킷과 관련한 것들로 이루어 집니다.

앞으로도 계속 써 나갈 수 있어야 하는데, 잘 할 수 있을까요? :-)

많이들 방문해 주시고, 좋은 의견도 남겨주세요.

From Rigel

2010년 12월 2일 목요일

네트워크 패킷 인젝션,캡쳐 도구 Packit

네트워크 패킷을 인젝션하고 캡쳐할 수 있는 도구 Packit(Packet toolkit) 을 소개한다.
앞서 소개했던 많은 도구들과 같이 인젝션하기에 유용한 도구이다.

TCP,UDP,ICMP,IP,ARP,RARP 그리고 이더넷 헤더등 거의 모든 것을 정의할 수 있어,
방화벽, 침입탐지시스템, 트래픽 테스트와 같은 곳에 이용할 때 유용하게 사용될 수 있을 것이다.
Packit 의 버전은 현재 1.0 이며 설치를 하기 위해서는 libnet 1.1.2 이상의 라이브러리와
libpcap 라이브러리또한 필요하다.

소스파일의 다운로드는 다음의 경로에서 할 수 있다:

APT 패키지 사용자라면,
# apt-get install packit 으로 쉽게 설치도 가능하다.

사용에는 큰 어려움이 없으나, 다만 옵션이 상당히 많다. 이 뜻은 세부적으로
정의할 수 있다는 뜻이된다. 기본 사용방법은 아래와 같다:

usage: packit -m mode [-options] 'expression'

사용할 때 모드가 있다는 것을 주의해야 하는데, 모드에 따라서 옵션이 달라지기 때문이다.
옵션에는 capture, inject, trace 가 있으며 기본모드는 inject 이다.

1. 패킷 캡쳐

자주 사용할 만한 패킷 캡쳐 옵션 몇가지를 정리해 보면 아래와 같다

-c count 캡쳐할 카운트 수를 지정
-e 링크 레이어 헤더 데이터 출력
-i interface 네트워크 인터페이스 지정
-n 호스트 주소를 이름으로 변환하지 않음
-r file 패킷을 읽을 파일 지정
-s snaplen 패킷 캡쳐할 snaplen 데이터 사이즈 정의 (기본:68 바이트)
-w file 패킷 파일 저장
-X 헥사와 아스키로 데이터 출력

사용 옵션들을 보면 패킷인사이드에서 여러번 다뤘던 도구들과 큰 차이는 없다.
특히 tcpdump 에 익숙하다면 더욱 그럴것이다.

사용예제>

#packit -m capture -c 100 -i eth0 -w /data/packetinside.pcap
#packit -m cap -nX 'tcp and port 80'

2. 패킷 인젝션

기본적으로 인젝션 되는 패킷의 옵션은 아래와 같으며, 옵션만 봐도 크게 어렵지는 않다.

-t protocol 인젝트할 프로토콜 타입 지정 : TCP, UDP, ICMP, ARP (기본은 TCP)
-c count 인젝션에 몇 개의 패킷을 사용할 것인지 정의
-i interface 네트워크 인터페이스
-w interval 각 패킷을 보내는 간격 시간 (기본 : 1초)
-h 패킷을 보낸 후, 응답을 프린트 해줌 * 필요에 따라 유용한 기능
-v Verbose 모드로 세부적으로 정보를 출력함
-p payload 인젝션 할 페이로드를 지정, HEX 는 '0x' 로 시작하며 각 값의 구분은 공백으로 함
ASCII : -p 'hello world, packetinside.com'
HEX: -p '0x 40 40 40 90 90 90 0d 0a'
-Z length 인젝트할 패킷의 사이즈 정의

-t 로 프로토콜을 지정한 후 각 프로토콜 마다 사용가능한 옵션을 이용하면 되는데
IP,TCP,UDP,ICMP,ARP,이더넷 헤더 옵션을 가지고 있다.
여기서 각 옵션을 일일이 설명하기는 힘들고, packit 의 간단한 도움말을 보면 쉽게 알 수 있다.

TCP/UDP header options
  -a ack      Acknowledgement number
  -D port     Destination port (Range format: start-end)
  -F flags    Flags (format: -F UAPRSF)
  -q seq      Sequence number
  -S port     Source port (Default: Random)
  -u urg      Urgent pointer
  -W size     Window size (Default: 65535)

ICMPv4 header options
  General:
  -C code     Code (Default: 0)
  -K type     Type (Default: 8)

  Echo(0) / Echo Reply(8):
  -N id       ID number
  -Q seq      Sequence number

  Unreachable(3) / Redirect(5) / Time Exceeded(11):
  -g gateway  Redirect gateway host (ICMP Redirect only)
  -j address  Original source address
  -J port     Original source port
  -l address  Original destination address
  -L port     Original destination port
  -m ttl      Original time to live
  -M id       Original ID number
  -O tos      Original type of service
  -P proto    Original protocol (Default: UDP)

  Mask Request(17) / Mask Reply(18):
  -N id       ID number
  -Q seq      Sequence number
  -G mask     Address mask

  Timestamp Request(13) / Timestamp Reply(14):
  -N id       ID number
  -Q seq      Sequence number
  -U ts       Original timestamp
  -k ts       Recieved timestamp
  -z ts       Transmit timestamp

IP header options
  -d address  Destination address
  -f          Don't fragment
  -n id       ID number
  -o tos      Type of service
  -s address  Source address
  -T ttl      Time to live (Default: 128)
  -V ipproto  IP protocol number (RAWIP only)

ARP header options
  -A op       Operation type (Default: 1 (ARP request))
  -x address  Source protocol address
  -X hwaddr   Source hardware address
  -y address  Destination protocol address
  -Y hwaddr   Destination hardware address

Ethernet header options
  -e ethaddr  Source ethernet address
  -E ethaddr  Destination ethernet address

옵션은 위와 같으며, 패킷인사이드 블로그를 열심히 보신 분들이라면 옵션을 이해하는데
어려움이 없을 것이다. 몇가지 예제를 보도록 하자.

다음은 출발지 소스는 8.8.1.1 로 하고 목적지는 192.168.0.1 로 보내는데 총 10개의 패킷을
보낸다. -h 옵션은 응답도 출력하도록 한 것이다. -h 옵션이 주어지지 않으면,
단순히 전송하는 정보만 출력할 것이다.

# packit -t icmp -s 8.8.1.1 -d 192.168.0.1 -c 10  -h
Mode:  Packet Injection using device: eth1

-| SND 1 |------------------------------------------------------------------

Timestamp:   10:28:54.469954
ICMP header: Type: Echo Request(8)  ID: 5854  Seqn: 56577  
IP header:   Src Address: 8.8.1.1  Dst Address: 192.168.0.1
    TTL: 128  ID: 53261  TOS: 0x0  Len: 28  

-| No Response From Peer |--------------------------------------------------

아래는 TCP 패킷을 보내는 것으로 목적지 포트 80에 TTL은 111 그리고 페이로드는 0x40 을
보낸 것이다.

# packit -t TCP -s 192.168.0.253 -d 192.168.0.200 -S 403 -D 80 -T 111 -p '0x 40'
Mode:  Packet Injection using device: eth1

TCP header:  Src Port: 403  Dst Port(s): 80  Flag(s): None
    Window: 65535  
IP header:   Src Address: 192.168.0.253  Dst Address: 192.168.0.200
    TTL: 111  ID: 49354  TOS: 0x0  Len: 41  

Writing packet(s) (1): .

-| Packet Injection Statistics |--------------------------------------------
Injected: 1  Packets/Sec: 1.0  Bytes/Sec: 41.0  Errors: 0

그리고 다음은 ARP 패킷을 만들어 전송한 것이다. 우선 -t 로 ARP 타입을 지정해 주고
-A 1 은 ARP Request 를 뜻하고 -x 는 보내는 IP 주소 -X 보내는 이더넷 주소를 정의한 것이다.

# packit -t arp -A 1 -x 1.2.3.4 -X 5:4:3:2:1:0  
Mode:  Packet Injection using device: eth1

ARP header:  Type: Request(1)
    Sender:  Protocol Address: 1.2.3.4  Hardware Address: 5:4:3:2:1:0
    Target:  Protocol Address: 0.0.0.0  Hardware Address: 0:0:0:0:0:0


Writing packet(s) (1): .

-| Packet Injection Statistics |--------------------------------------------
Injected: 1  Packets/Sec: 1.0  Bytes/Sec: 42.0  Errors: 0

여기서는 간단한 형태로만 만들어 패킷을 전송하지만, 사용하고자 하는 목적에 따라서
다양하게 만들어 볼 수 있다. 옵션을 여러개 사용하여 복잡해 보이지만,
막상 사용해 보면 옵션등이 사용하려는 목적을 대충 추정해 볼 수 있어 심플하게 패킷을 전송할 수 있다.

여기 블로그에서 언급한 많은 도구들 중에서 어떤것이 자기에게 더욱 적합한지는 여러분들이 판단하길 바란다.

From Rigel

2010년 10월 25일 월요일

Scapy 의 다양한 기능을 익혀보자 - 두번째

Scapy 는 앞서 언급했듯이 파이썬(Python) 기반의 프로그램이다. 그러므로 파이썬에 익숙치 않은 사용자라면
이게 무엇인가 하고 혼란스럽기도 하다. 일반적인 컴퓨터 언어의 기본지식이 있는 사용자라면,
어렵지 않게 이해할 수 있는 부분이니 예제를 몇 개 보는 것만으로도 충분히 이해가 될 것이다. 첫번째 이야기에서 언급한 대로 간단히 설치를 하고 아래 예제대로 몇 가지를 직접 실행해 보자. 그러면 금방 이해가 되고, 머리속에 기억이 오래 남을 것이다.

1. Scapy 의 설정 정보 살펴보기

Welcome to Scapy (v1.1.1 / -)
>>> conf
Version    = v1.1.1 / -
ASN1_default_codec = <ASN1Codec BER[1]>
AS_resolver = <__main__.AS_resolver_multi instance at 0xaa69a4c>
BTsocket   = <class __main__.BluetoothL2CAPSocket at 0xaa0f89c>
IPCountry_base = 'GeoIPCountry4Scapy.gz'
L2listen   = <class __main__.L2ListenSocket at 0xaa0f74c>
L2socket   = <class __main__.L2Socket at 0xaa0f6ec>
L3socket   = <class __main__.L3PacketSocket at 0xaa0f6bc>
auto_fragment = 1
checkIPID  = 0
checkIPaddr = 1
checkIPsrc = 1
check_TCPerror_seqack = 0
color_theme = <DefaultTheme>
countryLoc_base = 'countryLoc.csv'
debug_dissector = 0
debug_match = 0
ethertypes = </etc/ethertypes/ >
except_filter = ''
gnuplot_world = 'world.dat'
histfile   = '/root/.scapy_history'
iface      = 'eth1'
manufdb    = </usr/share/wireshark/wireshark/manuf/ >
mib        = <MIB/ >
nmap_base  = '/usr/share/nmap/nmap-os-fingerprints'
noenum     = <Resolve []>
p0f_base   = '/etc/p0f/p0f.fp'
padding    = 1
prog       = Version    = v1.1.1 / -
display    = 'display'
dot        = 'dot'
hexedit    = 'hexer'
pdfreader  = 'xpdf'
psreader   = 'gv'
tcpdump    = '/usr/sbin/tcpdump'
tcpreplay  = 'tcpreplay'
wireshark  = 'wireshark'
promisc    = 1
prompt     = '>>> '
protocols  = </etc/protocols/ pim ip ax_25 esp tcp ah mpls_in_ip ipv6_opts xtp ipv6_route igmp igp ddp etherip xns_idp ipv6_frag vrrp gre ipcomp encap ipv6 iso_tp4 sctp ipencap rsvp hip udp ggp hmp idpr_cmtp fc skip st icmp pup manet isis rdp l2tp ipv6_icmp udplite egp ipip ipv6_nonxt eigrp idrp rspf ospf vmtp>
queso_base = '/etc/queso.conf'
resolve    = <Resolve []>
route      = Network         Netmask         Gateway         Iface           Output IP
127.0.0.0       255.0.0.0       0.0.0.0         lo              127.0.0.1      
192.168.0.0     255.255.255.0   0.0.0.0         eth1            192.168.0.240  
0.0.0.0         0.0.0.0         192.168.0.200   eth1            192.168.0.240  

conf 를 해 보면 현 세션의 설정 정보를 볼 수 있다. 설정정보의 변경은 간단하게 할 수 있는데, 만약 iface 의 네트워크 인터페이스를 바꾸고자 할 경우에는 conf.변수 = '값'  과 같이 사용하면 된다. 아래는 eth1 을 eth0 으로 변경해 본 것이다.

>>> conf.iface = 'eth0'


2. Scapy 를 이용해서 패킷 덤프도 해 보자.

sniff() 를 이용하면 패킷 덤프를 할 수 있다. 아래 화면은 sniff 를 한 후 Ctrl+C 를 눌러 중지하였더니 TCP 274 건 UDP 16 건이 탐지 되었다. 또 sniff 에 필터를 걸거나, count 옵션을 통해 몇 개까지 덤프를 한 후 중지할 것인지 지정할 수 있다. 기록된 데이터는 따로 특정 이름 변수에 담지 않아, '_' 에 기록되어 있다. _ 를 프린트 해 보면 패킷 정보가 출력이 된다.

>>> sniff()

^C<Sniffed: UDP:16 TCP:274 ICMP:0 Other:10>
>>> sniff(filter="tcp and port 80", count=15)
<Sniffed: UDP:0 TCP:15 ICMP:0 Other:0>
>>> print _
[<Ether  dst=00:01:36:2e:0b:a7 src=08:00:27:69:4f:90 type=0x800 |<IP  version=4L ihl=5L tos=0x0 len=610 id=7385 flags=DF frag=0L ttl=64 proto=tcp chksum=0x464d src=192.168.0.240 dst=74.53.201.162 options='' |<TCP  sport=45659 dport=www seq=772295791 ack=1844792927 dataofs=8L reserved=0L flags=PA window=4006 chksum=0x3356 urgptr=0 options=[('NOP', None), ('NOP', None), ('Timestamp', (296792, 1784140432))] |< ....(생략)


3. 복잡한 건 싫어, 간단한 요약 정보 살펴보기

위에 기록된 정보를 a 라는 변수에 할당하였고, nsummary() 를 이용해 출력해 보았더니 보기 쉽게 한 라인 단위로 요약된 정보를 나타내준다. 각 라인 정보는 배열로 들어가 있어, 원하는 배열 정보를 출력해 볼수도 있다.
5번째 있는 정보를 출력한다면 a[5] 와 같이 입력하면 된다.

>>> a = _
>>> a.nsummary()
0000 Ether / IP / TCP 192.168.0.240:45659 > 74.53.201.162:www PA / Raw
0001 Ether / IP / TCP 74.53.201.162:www > 192.168.0.240:45659 A
0002 Ether / IP / TCP 74.53.201.162:www > 192.168.0.240:45659 PA / Raw
0003 Ether / IP / TCP 192.168.0.240:45659 > 74.53.201.162:www A
0004 Ether / IP / TCP 74.53.201.162:www > 192.168.0.240:45659 A / Raw
0005 Ether / IP / TCP 192.168.0.240:45659 > 74.53.201.162:www A
0006 Ether / IP / TCP 74.53.201.162:www > 192.168.0.240:45659 A / Raw
0007 Ether / IP / TCP 192.168.0.240:45659 > 74.53.201.162:www A
0008 Ether / IP / TCP 192.168.0.240:37088 > 72.14.213.95:www PA / Raw
0009 Ether / IP / TCP 192.168.0.240:47910 > 69.174.57.101:www S
0010 Ether / IP / TCP 192.168.0.240:47911 > 69.174.57.101:www S
0011 Ether / IP / TCP 72.14.213.95:www > 192.168.0.240:37088 PA / Raw
0012 Ether / IP / TCP 192.168.0.240:37088 > 72.14.213.95:www A
0013 Ether / IP / TCP 69.174.57.101:www > 192.168.0.240:47910 SA
0014 Ether / IP / TCP 192.168.0.240:47910 > 69.174.57.101:www A
>>> a[5]
<Ether  dst=00:01:36:2e:0b:a7 src=08:00:27:69:4f:90 type=0x800 |<IP  version=4L ihl=5L tos=0x0 len=52 id=7387 flags=DF frag=0L ttl=64 proto=tcp chksum=0x4879 src=192.168.0.240 dst=74.53.201.162 options='' |<TCP  sport=45659 dport=www seq=772296349 ack=1844794757 dataofs=8L reserved=0L flags=A window=4006 chksum=0x518b urgptr=0 options=[('NOP', None), ('NOP', None), ('Timestamp', (296905, 1784175402))] |>>>
>>>

4.  패킷 구성 세부정보를 살펴본다. 어떻게, show() 명령어로..

a 에 기록되어 있는 5번째 내용을 트리구조와 비슷하게 살펴볼 수 있다. show() 를 이용해 언제든지 필요할때 마다 패킷의 구성정보를 살펴보자.

>>> a[5].show()
###[ Ethernet ]###
  dst= 00:01:36:2e:0b:a7
  src= 08:00:27:69:4f:90
  type= 0x800
###[ IP ]###
     version= 4L
     ihl= 5L
     tos= 0x0
     len= 52
     id= 7387
     flags= DF
     frag= 0L
     ttl= 64
     proto= tcp
     chksum= 0x4879
     src= 192.168.0.240
     dst= 74.53.201.162
     options= ''
###[ TCP ]###
        sport= 45659
        dport= www
        seq= 772296349
        ack= 1844794757
        dataofs= 8L
        reserved= 0L
        flags= A
        window= 4006
        chksum= 0x518b
        urgptr= 0
        options= [('NOP', None), ('NOP', None), ('Timestamp', (296905, 1784175402))]

5. str() 로 문자열 정보 보기

>>> str(a[13])
"\x00\x016.\x0b\xa7\x08\x00'iO\x90\x08\x00E\x00\x01\xf8\xadL@\x00@\x06\xe4:\xc0\xa8\x00\xf0J}\x9bc\xd1x\x00PP&7\xdcj!.F\x80\x18\x01m\xa0=\x00\x00\x01\x01\x08\n\x00\x06\x9a\xb1\x9c5<\xd0GET / HTTP/1.1\r\nHost: google.com\r\nUser-Agent: Mozilla/5.0 (X11; U; Linux i686; en; rv:1.9.0.9) Gecko/20080528 Epiphany/2.22\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Language: en-us,en;q=0.5\r\nAccept-Encoding: gzip,deflate\r\nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\nKeep-Alive: 300\r\nConnection: keep-alive\r\nCookie: rememberme=false; PREF=ID=ca4bab229fe11b17:TM=1264000421:LM=1264000421:S=ydhaQuYz7bGA7OEL\r\n\r\n"


6. hexdump() 로 16진수 HEX 값 보기

>>> hexdump(a[13])
0000   00 01 36 2E 0B A7 08 00  27 69 4F 90 08 00 45 00   ..6.....'iO...E.
0010   01 F8 AD 4C 40 00 40 06  E4 3A C0 A8 00 F0 4A 7D   ...L@.@..:....J}
0020   9B 63 D1 78 00 50 50 26  37 DC 6A 21 2E 46 80 18   .c.x.PP&7.j!.F..
0030   01 6D A0 3D 00 00 01 01  08 0A 00 06 9A B1 9C 35   .m.=...........5
0040   3C D0 47 45 54 20 2F 20  48 54 54 50 2F 31 2E 31   <.GET / HTTP/1.1
0050   0D 0A 48 6F 73 74 3A 20  67 6F 6F 67 6C 65 2E 63   ..Host: google.c
0060   6F 6D 0D 0A 55 73 65 72  2D 41 67 65 6E 74 3A 20   om..User-Agent:
0070   4D 6F 7A 69 6C 6C 61 2F  35 2E 30 20 28 58 31 31   Mozilla/5.0 (X11
0080   3B 20 55 3B 20 4C 69 6E  75 78 20 69 36 38 36 3B   ; U; Linux i686;
....(생략)

7. 사용가능한 명령어는 무엇이 있을까?

Scapy 에서 사용가능한 명령어가 무엇이 있는지 궁금할때는 lsc() 를 쳐 보자. 그리고 추가 도움말이 필요할때는 help() 가 있다.

>>> lsc()
sr               : Send and receive packets at layer 3
sr1              : Send packets at layer 3 and return only the first answer
srp              : Send and receive packets at layer 2
srp1             : Send and receive packets at layer 2 and return only the first answer
srloop           : Send a packet at layer 3 in loop and print the answer each time
srploop          : Send a packet at layer 2 in loop and print the answer each time
sniff            : Sniff packets
p0f              : Passive OS fingerprinting: which OS emitted this TCP SYN ?
arpcachepoison   : Poison target's cache with (your MAC,victim's IP) couple
send             : Send packets at layer 3
sendp            : Send packets at layer 2
traceroute       : Instant TCP traceroute
arping           : Send ARP who-has requests to determine which hosts are up
ls               : List  available layers, or infos on a given layer
lsc              : List user commands
queso            : Queso OS fingerprinting
nmap_fp          : nmap fingerprinting
report_ports     : portscan a target and output a LaTeX table
dyndns_add       : Send a DNS add message to a nameserver for "name" to have a new "rdata"
dyndns_del       : Send a DNS delete message to a nameserver for "name"
is_promisc       : Try to guess if target is in Promisc mode. The target is provided by its ip.
promiscping      : Send ARP who-has requests to determine which hosts are in promiscuous mode

8. Traceroute 로  IP 경로 추적하기

흔히 경로 추적에 사용하는 traceroute 를 scapy 에서도 그대로 사용할 수 있다.

>>> traceroute("packetinside.com")
Begin emission:
************************Finished to send 30 packets.
******
Received 30 packets, got 30 answers, remaining 0 packets
   211.245.21.34:tcp80
1  192.168.0.200   11  
2  218.146.42.254  11  
3  121.140.24.161  11  
4  218.146.42.253  11  
5  112.190.34.93   11  
6  218.145.33.197  11  
7  112.174.48.158  11  
8  211.44.125.129  11  
9  118.221.4.17    11  
10 211.108.63.138  11  
11 58.229.17.78    11  
12 114.202.0.198   11  
13 211.245.21.34   SA  
14 211.245.21.34   SA  
15 211.245.21.34   SA  
16 211.245.21.34   SA    
...(생략)


9. 프로토콜의 각 레이어 구성하기

위에서는 몇 가지 유용한 명령어들을 알아 보았는데, 실질적으로 내가 패킷파일을 구성하기 위해서는 어떻게 해야 하는지 소개해 보고자 한다. 패킷파일을 들여다 보면 형태에 따라 다르지만 크게,
이더넷 헤더 , IP 헤더, TCP/UDP 헤더, 애플리케이션 헤더 등이 있다.
그럼 이 각 헤더를 구성하는 아래의 예제를 들여다 보자.

>>> IP()
<IP  |>
>>> Ether()/IP()/TCP()
<Ether  type=0x800 |<IP  frag=0 proto=tcp |<TCP  |>>>
>>> Ether()/IP()/TCP()/"GET /HTTP/1.1\r\nHost: packetinside.com\r\n\r\n"
<Ether  type=0x800 |<IP  frag=0 proto=tcp |<TCP  |<Raw  load='GET /HTTP/1.1\r\nHost: packetinside.com\r\n\r\n' |>>>>
>>> hexdump(_)
0000   FF FF FF FF FF FF 00 00  00 00 00 00 08 00 45 00   ..............E.
0010   00 51 00 01 00 00 40 06  7C A4 7F 00 00 01 7F 00   .Q....@.|.......
0020   00 01 00 14 00 50 00 00  00 00 00 00 00 00 50 02   .....P........P.
0030   20 00 4E BE 00 00 47 45  54 20 2F 48 54 54 50 2F    .N...GET /HTTP/
0040   31 2E 31 0D 0A 48 6F 73  74 3A 20 70 61 63 6B 65   1.1..Host: packe
0050   74 69 6E 73 69 64 65 2E  63 6F 6D 0D 0A 0D 0A      tinside.com....
>>>
>>> str(IP())
'E\x00\x00\x14\x00\x01\x00\x00@\x00|\xe7\x7f\x00\x00\x01\x7f\x00\x00\x01'
>>> str(TCP())
WARNING: No IP underlayer to compute checksum. Leaving null.
'\x00\x14\x00P\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00\x00\x00\x00\x00'
>>> a=Ether()/IP(dst="www.google.com")/TCP()/"GET /index.html HTTP/1.0 \n\n"
>>> a
<Ether  type=0x800 |<IP  frag=0 proto=tcp dst=Net('www.google.com') |<TCP  |<Raw  load='GET /index.html HTTP/1.0 \n\n' |>>>>

Ether() 은 이더넷 헤더를 IP() 는 IP 헤더를 의미한다. Ethere()/IP() 와 같이 사용하면 이 두 헤더를 만들어 주는 것이다. 구성된 헤더는 hexdump 로도 확인해 볼 수 있고, str 로도 각 헤더별 구성을 볼 수 있다. 예제를 보는 것 만으로도 대충 동작 형태의 감이 잡힐 거이다. 여러분들이 필요한 헤더를 원하는 대로 가져다 붙이면 되는 것이다.

10. 패킷 구성 조금 더 깊게 들여다 보기

조금더 패킷구성에 대해서 살펴보자. 헤더 마다 세부적으로 값들을 다 조정할 수 가 있는데, 아래는 b 에 IP 헤더를 집어 넣는데 목적지 주소는 192.168.100.100 으로 하고 있다. 목적지 주소만을 보기 위해 b.dst 를 사용했고, b.ttl 을 통해 ttl 을 볼 수도 있다. ttl 값을 128 로 변경하였다가 그 값을 다시 삭제한 것도 보인다.

TCP 도 마찬가지로 c 에 할당하고 flags 값을 설정해 보기도 하고 , 목적지와 출발지 포트도 설정했다. 그리고
z 라는 변수에 IP()/TCP() 로 만들어 넣었더니.

어라~ 이상하다. 내가 설정한 정보하고는 다르다. 여기서 주의할 것이. 이것은 단지 IP/TCP 기본 헤더정보를 넣은 거이다. 우리가 만든 정보를 넣은것이 아니므로 , x 변수에 넣은 것과 같이
x=b/c 와 같이 넣어주고 x.show() 로 확인해 보면 정상적으로 다 들어가 있는 것을 볼 수 있다.

>>> b=IP(dst="192.168.100.100")
>>> b
<IP  dst=192.168.100.100 |>
>>> b.dst
'192.168.100.100'
>>> b.ttl
64
>>> b.ttl="128"
>>> b
<IP  ttl='128' dst=192.168.100.100 |>
>>> del(b.ttl)
>>> b
<IP  dst=192.168.100.100 |>
>>>

>>> c=TCP()
>>> c
<TCP  |>
>>> c.flags="PA"
>>> c.flags
24
>>> c
<TCP  flags=PA |>
>>> c.dport=80
>>> c.sport=2080
>>> c
<TCP  sport=2080 dport=www flags=PA |>
>>> z=IP()/TCP()
>>> z
<IP  frag=0 proto=tcp |<TCP  |>>
>>> z.show()
###[ IP ]###
  version= 4
  ihl= 0
  tos= 0x0
  len= 0
  id= 1
  flags=
  frag= 0
  ttl= 64
  proto= tcp
  chksum= 0x0
  src= 127.0.0.1
  dst= 127.0.0.1
  options= ''
###[ TCP ]###
     sport= ftp_data
     dport= www
     seq= 0
     ack= 0
     dataofs= 0
     reserved= 0
     flags= S
     window= 8192
     chksum= 0x0
     urgptr= 0
     options= {}

>>> x=b/c
>>> x
<IP  frag=0 proto=tcp dst=192.168.100.100 |<TCP  sport=2080 dport=www flags=PA |>>
>>> x.show()
###[ IP ]###
  version= 4
  ihl= 0
  tos= 0x0
  len= 0
  id= 1
  flags=
  frag= 0
  ttl= 64
  proto= tcp
  chksum= 0x0
  src= 192.168.0.240
  dst= 192.168.100.100
  options= ''
###[ TCP ]###
     sport= 2080
     dport= www
     seq= 0
     ack= 0
     dataofs= 0
     reserved= 0
     flags= PA
     window= 8192
     chksum= 0x0
     urgptr= 0
     options= {}
>>>

11. 패킷 전송하기

첫번째 이야기에서도 간단하게 패킷 전송을 다뤄보았다. 앞에서 만든 x 변수를 send 를 통해 쉽게 전송했다. 이 뜻은, 여러분이 필요한 형태로 패킷을 아주 쉽게 만들 수 있다는 것이다. 그리고 send 를 통해 전송을 하고.
이외 파일로 저장된 패킷파일을 바로 불러들여 전송을 시킬 수도 있다.

>>> send(x)
.
Sent 1 packets.
>>> sendp(rdpcap("/home/debian/test.pcap"))
WARNING: DNS RR prematured end (ofs=45, len=42)
WARNING: DNS RR prematured end (ofs=50, len=42)
WARNING: more DNS RR prematured end (ofs=45, len=42)
..........................................................................................................................................
Sent 138 packets.
>>>

Scapy 의 주요한 몇 가지 기능과 사용방법에 대해서 알아보았는데, 굳이 설명이 없더라도
소개한 예제만 보고도 기능이 충분히 이해가 될 것이다. 파이썬 기반이라도 설명을 했기 때문에
다양한 프로그램적인 요소를 접목하기도 아주 쉽다. 일단은 이 정도만 알아두어도
Scapy 를 이용해 활용하기에는 큰 무리가 없을 것이며, 더 많은 기능은 Scapy 사이트에서 문서를 참고해 보기 바란다. 더욱 많은 기능에 놀랄지도 모르겠다. :-)

마지막으로 세번째 이야기에서는 Scapy 를 프로그램 관점에서 소개해 보도록 하겠다.

From Rigel.

[Scapy 연관글]

2010년 10월 20일 수요일

강력한 패킷 조작 프로그램 Scapy 를 소개한다 - 첫번째

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

* 참고로 윈도우 기반에서 사용하고자 한다면, 다음의 문서를 참고하여 실행해 보길 바란다.
http://www.secdev.org/projects/scapy/doc/installation.html#platform-specific-instructions

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 기능을 알아보도록 하겠다. 계속 이것저것 소개할 것이 많은데, 정리하고 쓰자니 시간이 꽤 걸리는 거 같다. 이래서 정리는 인내가 필요해지는 것 같다 :-)

2010년 10월 15일 금요일

TCP/IP 헤더 내 맘대로...tcp[13] == 2 의 의미는 무엇일까?

tcpdump 를 이용해 패킷을 덤프하다 보면 다양한 표현식을 이용해 필터를 표현하는 경우가 많다. 많은 경우는
대략 사용되는 문자만 보더라도 의미가 파악되는 경우가 많다. 예를 들어, src 라 하면 하면 source 인 출발지가 연상되고 host 는 말 그대로 호스트를 뜻한다. 그럼 이걸 다 연결해서 보면 src host 192.168.0.0 필터의 의미를 금방 추측해 볼 수 있다. tcpdump 에서 이용되는 필터 표현방식은 큰 어려움이 없다. 그런데 아래와 같은 경우는 무엇일까?

tcp[13] == 2

얼핏 봐서는 의미가 잘 파악이 안된다. 어렵게 느껴질 수도 있는데 TCP 헤더를 생각해 보면 의외로 쉽게 풀린다.
일단 다음의 TCP 헤더 포맷을 살펴보자.
[출처 : nmap.org]

TCP 헤더 포맷은 Options 을 제외하고는 20 바이트로 구성되어 있다. 오프셋은 0 부터 시작하고, Octet 형태로 보면 첫 라인은 0 - 3 까지이고, 두번째 라인은 4-7 이다. 그렇다 바로 위에서 13 이라는 것은 바로 이 위치인 것이다. TCP 라고 하였으니 TCP 헤더를 뜻한 것이고 뒤에 들어가는 것은 헤더의 위치 값이다.

자, 그럼 두번째 라인은 4-7 까지이고, 3번째는 8-11 까지가 된다. 네번째 라인은 12-15 가 되는데 13 위치를 보면 TCP Flags 라고 되어 있다. 그렇다 바로 플래그 값을 뜻하는 것으로 대표적인 몇 가지 값을 보면 아래와 같다:

F : FIN
S : SYN
R : RESET
P : PUSH
A : ACK

TCP 3-way Handshake 라는 것을 들어보았다면 위의 용어가 익숙할 것이다. 13 위치가 플래그 라는 것은 알았는데 TCP[13] 의 '== 2' 은 무었일까? == 는 같다는 의미로 쉽게 알 수 있고, 2는 설정된 비트 값이다. 좀더 자세히 알아보도록 하겠다. 1바이트는 8 비트로 구성되어 있다. 그래서 위 헤더의 한 라인씩은 4바이트로 이루어져 있고 13 번째 위치 부분도 1바이트 구성이다. 그럼 8비트 구성일텐데, 위 플래그들을 보면 8개이다. 즉, 각 플래그는 한 비트씩 차지하고 있는 것이다. 좀더 자세하게 표현하면 아래와 같다 :

                  |C|E|U|A|P|R|S|F|
                |---------------|
                |0 0 0 0 0 0 1 0|
                |---------------|
                |7 6 5 4 3 2 1 0|

제일 아래 부분은 0-7 까지 비트를 표현한 것이고 그 윗 부분은 Set 된 비트를 의미한다. S 부분이 Set 되어 있는 상태이다. 그럼 이걸 다시 십진수로 변환해 보면 나머지는 다 0 이고 한 군데만 1 이므로 1*2 인 2가 되는 것이다. 차례로 각 계산을 세부적으로 표현하면 다음과 같아진다.

   7     6     5     4     3     2     1     0
0*2 + 0*2 + 0*2 + 0*2 + 0*2 + 0*2 + 1*2 + 0*2  =  2

이제 느낌이 팍 오는가? SYN 값이 0x02 가 되는 것이다. 그럼 TCP[13] == 2 의 의미를 다시 정리해 보면,
TCP 헤더의 13번째 Octet 위치는 TCP Flags 를 나타내는 것이고 2 는 SYN 를 표현한 것이다.

바로 TCP 패킷중 SYN 패킷만 해당하는 것을 탐지하고자 할때 사용할 수 있는 필터가 되는 것이다.


만약 PUSH 플래그를 잡고자 한다면 8 이 된다. 알고보면 어렵지 않은 부분인데, 이런 것을 모르고 해당
문법을 보게 되면 복잡함 부터 느껴지는 것은 당연하다. 이제 각 헤더의 어떤 부분도 여러분 스스로가 탐지해 낼 수 있게 된것이다.


다음번에는 패킷분석에 기본이 되는 TCP/IP 헤더 부분을 좀더 면밀히 살펴보고자 한다. 패킷분석의 기본이 되는 부분이지만, 의외로 처음 접하는 분들에겐 힘들어 보이는 부분이다. 헤더의 구성을 알게되면 패킷이라는 것에 대해 좀더 명확히 알 수 있으며, 이해가 훨씬 빨라진다. 한 패킷을 예로들어, OSI Layer 단계부터 시작해 TCP, IP 헤더까지 껴 맞춰보며 여러분들에게 명확한 이해를 제시하고자 한다.


패킷이 무엇이고, 통신이 어떻게 이뤄지며 패킷의 구성은 어떻게 이뤄지는지 이해가 잘 안된다면 꼭 보아야 할 내용이 될 것이다. 그럼 시작되는 그 날을 기약하며...



2010년 10월 12일 화요일

와이어샤크 1.4.1, 1.2.12 버전 릴리즈

와이어샤크의 최신버전이 릴리즈 되었다. 이번에 릴리즈 된 버전은
1.4.1 과 1.2.12 버전이다.

ASN.1 BER 해석기의 취약점이 해결되었고, 유저 인터페이스 관련한 몇 가지
버그들이 해결되었다. 1.4.1 버전에서는 다음 프로토콜 지원 기능이 업데이트 되었다.

ASN.1 BER, ASN.1 PER, EIGRP, GSM A RR, GSM Management, GSM MAP, GTP, GTPv2, ICMPv6, Interlink, IPv4, IPv6, IPX, LDAP, LLC, MySQL, NAS EPS, NTLMSSP, PN-IO, PPP, RPC, SDP, SLL, SSL, TCP

이외 업데이트 된 세부적인 내용은 다음 경로를 참고하면 된다.

http://www.wireshark.org/docs/relnotes/wireshark-1.4.1.html

또한, 와이어샤크 1.0 버전에 대해서는 더 이상 지원이 이뤄지지 않는다. 공식적인
지원이 끝난만큼, 1.0 사용자들은 1.4 버전으로 업그레이드 할 것을 권고한다.

2010년 10월 5일 화요일

오래 간만에 접속해본 tcpdump 사이트 바뀌었네..

오래간만에 tcpdump 사이트를 방문하였더니 홈페이지가 새롭게 리뉴얼 되었다. 근 몇년간 한번도
바뀐적 없이 운영된 것으로 기억하는데, 새로운 화면이 머랄까 신선하게 다가온다. ;-)
패킷 분석을 하는 분들에겐 tcpdump 와 libpcap 을 빼 놓을 수 없을 것이다.

앞으로도 꾸준히 발전하는 모습을 기대하며....
I love libpcap :-)

2010년 10월 1일 금요일

윈도우 기반의 네트워크 패킷 생성 도구 - NPG

오랜만에 윈도우 환경에서 사용할 수 있는 네트워크 패킷 생성 도구 하나를 소개하고자 한다.
이름은 Network Packet Generator 이며 약자로 NPG 이다. GNU GPL 라이센스로
자유롭게 사용가능하다. NPG 는 WinPcap 을 이용하여 패킷을 생성하며, 주요한 것을 요약해 보면 다음과 같다

- 오픈소스
- 윈도우 환경에서 동작
- Libpcap 기반의 패킷 생성기
- PCAP 호환 패킷 파일 또는 NPG 포맷의 파일을 이용하여 패킷 생성
- 패킷 바이트 스트림 전송

기능은 아주 다양하지는 않지만, 기존에 보아오던 것과 좀 다른 특징은 NPG 라 정의되어 있는
포맷 형태이다. 이 포맷 형태에 맞춰서 생성될 패킷의 HEX 값을 나열해 주면 된다.
이런 기능이 유용한 경우가 있기 때문에 특정 작업에서는 요긴할 것이다.

NPG 는 다음의 경로에서 받을 수 있다.


일단 아무 옵션없이 실행하면, 인터렉티브 모드로 동작하여 사용자가 선택하여 작업을 결정할 수 있는데,
처음 접하는 분들에겐 유용할 수도 있다.

C:\Npg1.3.0\bin>npg
Network Packet Generator 1.3.0
Copyright (C) 2006 Jason Todd
WikiSTC - http://www.wikistc.org/

No arguments detected, using interactive mode. Use npg -h for arugments.

Output information level:

[1] None
[2] Verbose
[3] Very Verbose
[4] Very Very Verbose

Selection [3]:


이외 몇 가지 옵션을 알아보면 다음과 같다.

-h 도움말
-d 패킷을 인젝트할 네트워크 디바이스를 선택
-f NPG 패킷파일의 이름 지정
-F Libpcap 호환 패킷파일 이름 지정
-l 사용가능한 네트워크 디바이스 나열
-p <packet byte stream>
인젝트할 패킷 바이트를 HEX 값으로 나열해주면 됨
-r <repeat count>  
패킷을 몇번 반복할지 카운트를 지정
-t <interval>
패킷을 인젝트 하기 전 시간 간격을 지정 (시간 기준은 밀리세컨드)
-v, -vv, -vvv
동작 상태를 표시 v 가 많을 수록 세부정보를 표시함

옵션을 대충 봐도 무슨 기능인지 추측이 가능할 정도로 복잡하지는 않다. 예를 들어,
다음과 같이 -F 를 통해 pcap 파일을 지정해 본다면

C:\Npg1.3.0\bin>npg -vvv -F packets.cap
Network Packet Generator 1.3.0
Copyright (C) 2006 Jason Todd
WikiSTC - http://www.wikistc.org/


Successfully opened file packets.cap as read only

Successfully processed 7 packets in packets.cap
599 bytes allocated in packet queue to be sent
Elapsed time : 0.000

시간 간격을 둘것인지 물어본다.

Use time intervals defined in packets.cap:

[1] Yes
[2] No

Selection [2]:
An output device must be selected for injecting the packets

기본설정은 No 이며 엔터를 치면 다음 사용가능한 디바이스를 나열해 준다.
여기서 패킷을 전송할 인터페이스 번호를 골라주면 된다.

Available devices:

[1] Network adapter 'Sun' on local host
[2] Network adapter 'NVIDIA nForce MCP Networking Adapter Driver' on local host

Select default device (1-2):2

인터페이스를 선택하면 아래와 같이 패킷을 인젝트 하여 전송한다.

Elapsed time : 0.001
7 packets successfully injected
599 bytes sent
Releasing 599 bytes used for LibpcapQueue

인터페이스를 지정하지 않으면 알아서 인터페이스를 나열해 주고, 시간간격을 지정해 주지 않아도
물어봐 준다. 그만큼 쉽게 사용 가능하다.

앞서 말한것과 같이 NPG 는 자체의 포맷 형태를 이용해 패킷을 만들어 전송할 수 있다. 이 형태를
알아보면 다음과 같다:

NPG 패킷파일은 {    } 로 둘러 쌓인 블럭으로 이뤄진다. 물론 값은 00-FF 사이의 HEX 값으로 표현되며
공백이나, 탭, 주석은 무시된다. 전송할 패킷 구성은 아래와 같은 형태 블럭으로 이뤄진다.

예제>
1. { 01 02 03 04 05 06 06 05 04 03 02 01 08 00 }
2. { 01 02 03 04 05 06
  06 05 04 03 02 01
  08 00 }
3. {0102030405060605040302010800}
4. {
0
1
0
2
0
3
}

그리고, 각 패킷 블럭이 시작되기 전 [  ] 로 묶어 표현해 주는 부분은 반복할 카운트와 시간간격을 지정하게 된다. 예를 들면 아래와 같다

[0,1000]
[3,0]

자, 그럼 NPG 파일안에 들어있는 예제파일을 한번 들여다 보자. 패킷 블럭 시작전에 [3,1000] 으로
3번 반복하고 1000 밀리세컨드 간격이 있다는 것을 뜻한다.
그리고 < > 로 묶인 부분은 이것이 어떤 형태인지 말해주는 태그이다.  그 다음 시작되는 {  } 는
실제 발송될 패킷이 기술되는 것으로 보기좋게 라인별로 기술되어 있다.
앞서 말했듯이 주석과, 공백등은 무시되므로 아래 예제와 같이 사람이 보기 좋게 나열하여
사용하는 것이 좋다.

# TCP/IP ICMP Echo Request
[3,1000]
<ICMP Echo Request>
{
# Ethernet HEADER -----

  01 02 03 04 05 06  # Destination MAC
  06 05 04 03 02 01  # Source MAC
  08 00              # Protocol

# IP HEADER -----------

  45                 # Version / Header Length
  00                 # Type of service
  00 3c              # Total length
  00 a5              # Identification
  00 00              # Flags / Fragment offset
  80                 # Time to live
  01                 # Protocol
  b8 c8              # Checksum
  c0 a8 00 02        # Source address
  c0 a8 00 01        # Destination address

# ICMP HEADER ---------

  08                 # Type
  00                 # Code
  4a 5c              # Checksum
  02 00              # Identification
  01 00              # Sequence number
  61 62 63 64 65 66  # Data (Windows ping)
  67 68 69 6a 6b 6c
  6d 6e 6f 70 71 72
  73 74 75 76 77 61
  62 63 64 65 66 67
  68 69
}

만들어진 포맷 파일을 이용하여 -f 옵션으로 전송할 수 있다.

C:\Npg1.3.0\bin>npg -vv -f packets.txt -d rpcap://\Device\NPF_{E849DA
84-A444-4334-BD12-157CFC55BD8B}
Network Packet Generator 1.3.0
Copyright (C) 2006 Jason Todd
WikiSTC - http://www.wikistc.org/


Successfully processed 3 packets in packets.txt
Elapsed time : 0.000
Injecting packet queue obeying time intervals

Waiting approximately 1000 milliseconds
Injecting Packet #1
Device: rpcap://\Device\NPF_{E849DA84-A444-4334-BD12-15XXX55BD8B}
Packet ID: ICMP Echo Request
Repeat count: 0

그리고 아래와 같이 -p 옵션을 통해 전송할 데이터를 바로 지정할 수도 있다.

C:\Npg1.3.0\bin>npg -vv -p 0001020304 -d rpcap://\Device\NPF_{E849DA8
4-A444-4334-BD12-15XXX55BD8B}

하지만 위에서 사용한 예에서는 임의로 지정한 것이기 때문에 패킷이 알 수없는 형태로 전송된다.
어떤 프로토콜 형태에 맞춰서 작성된 것이 아니기 때문이다. -p 옵션등은 명령어 옵션을 통해
바로 패킷을 전달하고자 할때 사용하면 된다.

[참고]
1. NPG
http://www.wikistc.org/wiki/Network_packet_generator
2. NPG 파일 다운로드 (요청에 의해 해당 소스 파일을 첨부해 놓습니다)

2010년 9월 15일 수요일

안드로이드의 또 다른 패킷 덤프/분석 앱

일전에 안드로이드 패킷 덤프 프로그램인 안드로 샤크를 소개한 적이 있습니다. 그 당시 베타가 진행중이었는데, 추가적인 소식이 계속 없었죠. 그 와중에 다른 프로그램이 공개되었습니다. 공개된 시점은 좀 되었는데, 제가 게을러서 이제야 소개하네요. 이미 아시는 분도 있겠지만,  안드로이드 마켓에서 'shark' 로 검색해 보시면 찾을 수 있습니다. 2개의 프로그램이 있는데요

- Shark for Root
- SharkReader

입니다. SharkReader 는 이름과 같이 PCAP 을 볼 수 있는 프로그램이고요, Shark for Root 는 패킷 덤프 프로그램입니다. 제가 tcpdump 를 통한 패킷덤프를 소개하였는데, GUI 로 조금은 편하게 패킷 덤프를 할 수 있습니다. Shark for Root 는 아래와 같은 화면입니다.

단, 패킷덤프를 위해서는 루트권한이 필요합니다. 그리고 SharkReader 는 제가 가진 모토로이 폰에서 실행은 되는데 세부 패킷정보를 보는 것은 제대로 나오지를 않더군요. 갤럭시 S 에서는 제대로 나오는 것을 확인했습니다. 아직 App 이 퍼펙트 하지는 않는거 같네요.

아, 한가지 빠트린 것이 있는데. 위 프로그램을 설치하면 Shark Updater 라는 것도 하나 생깁니다. 이건 PCAP 파일을 읽어들여 파싱해 보여주기 위한 모듈들을 다운로드 합니다.

2010년 9월 10일 금요일

Bit-Twist 로 패킷파일의 편집과 생성까지 자유자재로..

지금까지 패킷 편집 도구를 몇 가지 소개하였다. 패킷생성기능, 편집 기능등. 패킷인사이드를 검색해 보면 몇 가지를 찾아볼 수 있을 것이다. 이번 도구의 이름은 Bit-Twist 로 패킷을 생성하고, 편집할 수 있는 기능까지 갖추고 있다. 사용방법도 너무 쉬워서 한번 사용예제를 보는 것만으로도 쉽게 이해가 될 것이다.

- bittwist  : PCAP 기반의 패킷 생성기
- bittwistb : PCAP 기반의 이더넷 브릿지
- bittwiste : PCAP 파일 에디터

일단, 다음의 경로를 통해 파일을 다운로드 받을 수 있다.


아차, 여기 예는 리눅스 기반에서 소개한 것이지만. 윈도우에서도 사용가능하다는 점!

도움말은 -h 를 통해서 볼 수 있고, 몇 가지 옵션을 살펴보도록 하자.  우선, 패킷 생성기인 bittwist 로 시작해 보자.  -d 옵션은 현재 사용가능한 네트워크 인터페이스를 보여준다.

# bittwist -d
1. eth0
2. any (Pseudo-device that captures on all interfaces)
3. lo

-i 를 통해 인터페이스를 정할 수 있고, 인자로 패킷파일을 주면 해당 인터페이스로 패킷을 발송한다.

# bittwist -i eth0 test.pcap
sending packets through eth0
trace file: test.pcap
^C
1235 packets (1041023 bytes) sent
Elapsed time = 36.533449 seconds

위 예를 보면 1235 개의 패킷을 전송하였고, Ctrl+C 를 눌러 중단했다. 바로 전송이 빠르게 이뤄지지 않았기
때문에 수동으로 중지한 것이다. 이럴때 -m 옵션을 사용하면 즉시 전송하게 된다.

# bittwist -i eth1 test.pcap -m 0
sending packets through eth1
trace file: test.pcap

2040 packets (1578854 bytes) sent
Elapsed time = 0.037914 seconds

-m 옵션을 사용하였더니 즉시 패킷이 전송되었고, 2040개의 패킷이 다 전달되었다.
-c 옵션은 전송할 패킷 갯수를 지정할 수 있다. 만약 test.pcap 에서 10 개의 패킷만을 전달하고 싶다면 -c 10 을 사용하면 된다.

# bittwist -i lo test.pcap -m 0 -c 10
sending packets through lo
trace file: test.pcap

10 packets (4247 bytes) sent
Elapsed time = 0.000414 seconds

간단한 옵션 몇가지를 통해 금방 패킷을 전송할 수 있는 것을 보았다. 이와 비슷한 기능을 가진 도구로는 tcpreplay 가 기억이 날 것이다.  자, 이번에는 편집 기능을 사용 예를 통해 한번 알아보도록 한다.

1) 패킷에서 1-2 까지만의 패킷을 뽑아내 저장해 보자.

# bittwiste -I test.pcap -O rigel.pcap -R 1-2
input file: test.pcap
output file: rigel.pcap

2 packets (128 bytes) written

2) 패킷 덤프 할 시간을 지정해 저장하기

일단 PCAP 파일의 첫 시간을 살펴보았더니 2010년7월21일 10시26분이다.

# tcpdump -r test.pcap -tttt | more
reading from file test.pcap, link-type EN10MB (Ethernet)
2010-07-21 10:26:39.659705 IP 179.222.51.219.3645 > 147.245.206.234.www: S 592977294:59297
7294(0) win 8192 <mss 1460,nop,wscale 2,nop,nop,sackOK>

그리고, -S 옵션을 통해 시작시간과 끝 시간을 지정한다. 참고로 -I 옵션은 Input 파일 -O 옵션은 Output 파일을
뜻한다.

# bittwiste -I test.pcap -O rigel.pcap -S 21/07/2010,10:20:00-21/07/2010,10:26:40
input file: test.pcap
output file: rigel.pcap

944 packets (866907 bytes) written

3) IP 를 변경해 보자.

# tcpdump -r rigel.pcap
reading from file rigel.pcap, link-type EN10MB (Ethernet)
10:26:39.659705 IP 179.222.51.219.3645 > 147.245.206.234.www: S 592977294:592977294(0) win 8192 <mss 1460,nop,wscale 2,nop,nop,sackOK>

위 172.222.51.219 출발지 주소를 -> 192.168.0.0 으로 변경해 보자.

# bittwiste -I test.pcap -O rigel.pcap -R 1 -T ip -s 179.222.51.219,192.168.0.0
input file: test.pcap
output file: rigel.pcap

1 packets (66 bytes) written

# tcpdump -r rigel.pcap
reading from file rigel.pcap, link-type EN10MB (Ethernet)
10:26:39.659705 IP 192.168.0.0.3645 > 147.245.206.234.www: S 592977294:592977294(0) win 8192 <mss 1460,nop,wscale 2,nop,nop,sackOK>

확인해 보면 출발지 주소가 설정한대로 변경되었다.

4) -R 옵션을 사용하지 않으면 모든 범위에 적용된다.

# bittwiste -I test.pcap -O rigel.pcap  -T ip -s 179.222.51.219,192.168.0.0
input file: test.pcap
output file: rigel.pcap

2040 packets (1578854 bytes) written

3번과 같은 예제인데, 편집된 패킷 개수를 보면 2040 개이다. -R 을 사용하지 않아 전체에 적용이 된 것이다.

5) 포트 번호 변경

# bittwiste -I test.pcap -O rigel.pcap -R 1 -T tcp -d 80,8080
input file: test.pcap
output file: rigel.pcap

1 packets (66 bytes) written

6) Payload 삽입하기

# echo "hahaha" | xxd
0000000: 6861 6861 6861 0a                        hahaha.

-X 옵션을 통해 위 HEX 값을 삽입.

# bittwiste -I test.pcap -O rigel.pcap -R 1 -L 4 -X 686168616861 -T tcp
input file: test.pcap
output file: rigel.pcap

1 packets (72 bytes) written

편집된 rigel.pcap 을 아래와 같이 확인해 보면 Payload 가 삽입된 걸 볼 수 있다.

# tcpdump -r rigel.pcap -XX
reading from file rigel.pcap, link-type EN10MB (Ethernet)
10:26:39.659705 IP 179.222.51.219.3645 > 147.245.206.234.www: S 592977294:592977300(6) win 8192 <mss 1460,nop,wscale 2,nop,nop,sackOK>
        0x0000:  001e 4a48 3900 0024 2119 7756 0800 4500  ..JH9..$!.wV..E.
        0x0010:  003a 7ee5 4000 3006 813f b3de 33db 93f5  .:~.@.0..?..3...
        0x0020:  ceea 0e3d 0050 2358 1d8e 0000 0000 8002  ...=.P#X........
        0x0030:  2000 7bdf 0000 0204 05b4 0103 0302 0101  ..{.............
        0x0040:  0402 6861 6861 6861                      ..hahaha
    
이외 옵션을 잘못사용하면 아래와 같은 에러메시지를 얻게 된다.

bittwiste: invalid header specification

이 도구를 소개하면서 느낀것은 다른 도구들보다 사용이 쉬웠다. 도움말만 참고해서도 쉽게 사용할 수 있을
만큼 간단하고 기능또한 필요한 것으로 잘 모아져 있다.

패킷을 편집하고 생성하는 기능을 원한다면 이 도구가 큰 도움이 될 것이다.