2011년 5월 24일 화요일

PCAP 파일에서 TCP 스트림 정보를 쉽게 다루기

패킷파일에서 스트림 정보를 좀더 쉽게 볼 수 있는 도구가 있다. 'streams' 라는 것으로 pcap 파일에서 TCP 스트림 정보를 브라우징 해서 볼 수 있도록 도와주는 것이다. 각 세션 정보를 Interactive 하게 볼 수 있으며, pipe 를 통해 스트림 정보를 외부로 호출할 수 도 있다.
일단, 다음의 경로에서 다운로드 받을 수 있다.

http://src.carnivore.it/streams/

파일을 받아 압축을 풀고 컴파일을 해야 하는데, 약간은 불편하게 되어 있다. configure 파일을 생성하고 해야 하는데, 에러가 발생하여 바로 src/ 안에서 직접 컴파일을 하였다.

컴파일을 하기 위해서는 Libpcap 이 당연히 설치되어 있어야 하고, Interactive 하게 커맨드 사용이 가능하여야 해서 readline 라이브러리도 필요하다. 이 2가지만 갖춰져 있으면 다음과 같이 컴파일을 하면 된다. (에러가 발생하는데, 소스파일에 VERSION 정보가 define 되어 있지 않아서 발생한다. 소스코드에 define 으로 VERSION 정보만 입력해 준다)

gcc cmd.c hash.c sig.c streams.c strm.c util.c -I/usr/include/readline -lpcap -lreadline

그러면 a.out 파일이 생성된다. -o 옵션을 이용해 바로 streams 로 바이너리를 생성해도 된다.
컴파일된 파일을 실행해 보면 아래 화면과 같이 볼 수 있다.


PCAP 파일을 테스트해 보기 위해 43개의 패킷이 들어있는 임의의 패킷파일을 선정하였다. 패킷 파일의 정보를 보면 아래와 같다. (와이어샤크에서 받을 수 있는 샘플 패킷 데이터를 이용하였는데, 덤프된 시간이 2004 년이다^^ )


File type:           Wireshark/tcpdump/... - libpcap
File encapsulation:  Ethernet
Number of packets:   43
File size:           25803 bytes
Data size:           25091 bytes
Capture duration:    30 seconds
Start time:          Thu May 13 19:17:07 2004
End time:            Thu May 13 19:17:37 2004
Data byte rate:      825.53 bytes/sec
Data bit rate:       6604.26 bits/sec
Average packet size: 583.51 bytes
Average packet rate: 1.41 packets/sec


일단 실행된 상태에서 패킷을 로드하기 위해 analyze 명령어를 사용한다. http.cap 을 로드하였더니 2개의 스트림을 볼 수 있다. list 명령어는 스트림된 화면을 출력한다. 전체 패킷이 42개 였는데, 스트림된 형태로 요약해 보면 아래와 같이 2개라는 것이다. 하나가 479 바이트 나머지는 18,364 바이트다.

streams>
streams> analyze ./http.cap
file processed, 2 streams (2 non-empty and complete).
streams> list
    0:       0.000000      30.063228  145.254.160.237:3372 > 65.208.228.223:80 (479 bytes)
    1:       0.911310      17.905747  65.208.228.223:80 > 145.254.160.237:3372 (18364 bytes)
streams>

패킷내용을 살펴보기 위해 ext 로 외부 기능을 호출해 본다. hd 를 호출하면 되는데 hd 가 무엇인가 해서 util.c 를 보았더니 HEX DUMP 형태로 출력해 주는 기능을 가진 것이다.


void hd(const u_char *data, size_t len) {
        register int i, j;

        if (!data || !len) return;

        for (i = 0; i < len; i += 0x10) {
                printf("0x%08x  ", i);

                for (j = 0; j < 0x10 && i+j<len; j++) {
                        if (j == 0x8) putchar(' ');
                        printf("%02x ", data[i+j]);
                }

                printf("%-*c|", (3 * (0x10 - j)) + (j > 0x8 ? 1 : 2), ' ');

                for (j = 0; j < 0x10 && i + j < len; j++)
                        putchar(isprint(data[i+j]) ? data[i+j] : '.');

                puts("|");
        }
        putchar('\n');

        return;
}


호출하면 pipe 로 그 정보를 넘기는데 0 번째 정보를 보고자 하면 pipe 0 을 한다.

streams> ext hd
streams> pipe 0
479 bytes written (479 in total)
00000000  47 45 54 20 2f 64 6f 77  6e 6c 6f 61 64 2e 68 74  |GET /download.ht|
00000010  6d 6c 20 48 54 54 50 2f  31 2e 31 0d 0a 48 6f 73  |ml HTTP/1.1..Hos|
00000020  74 3a 20 77 77 77 2e 65  74 68 65 72 65 61 6c 2e  |t: www.ethereal.|
00000030  63 6f 6d 0d 0a 55 73 65  72 2d 41 67 65 6e 74 3a  |com..User-Agent:|
00000040  20 4d 6f 7a 69 6c 6c 61  2f 35 2e 30 20 28 57 69  | Mozilla/5.0 (Wi|
00000050  6e 64 6f 77 73 3b 20 55  3b 20 57 69 6e 64 6f 77  |ndows; U; Window|
00000060  73 20 4e 54 20 35 2e 31  3b 20 65 6e 2d 55 53 3b  |s NT 5.1; en-US;|
00000070  20 72 76 3a 31 2e 36 29  20 47 65 63 6b 6f 2f 32  | rv:1.6) Gecko/2|
00000080  30 30 34 30 31 31 33 0d  0a 41 63 63 65 70 74 3a  |0040113..Accept:|
00000090  20 74 65 78 74 2f 78 6d  6c 2c 61 70 70 6c 69 63  | text/xml,applic|
000000a0  61 74 69 6f 6e 2f 78 6d  6c 2c 61 70 70 6c 69 63  |ation/xml,applic|
000000b0  61 74 69 6f 6e 2f 78 68  74 6d 6c 2b 78 6d 6c 2c  |ation/xhtml+xml,|

그러면 0번째의 정보를 볼 수 있는 GET 방식으로 다운로드 하는 헤더 정보를 볼 수 있다.
그리고 이런 정보를 파일로 저장하기 위해서는 outfile 로 저장할 파일 이름을 지정해 주고 , dump 로 저장할 스트림 번호를 지정하면 된다.

streams> outfile ./http.bin
streams> list
    0:       0.000000      30.063228  145.254.160.237:3372 > 65.208.228.223:80 (479 bytes)
    1:       0.911310      17.905747  65.208.228.223:80 > 145.254.160.237:3372 (18364 bytes)
streams> dump 1
18364 bytes written to ./http.bin

저장된 파일을 보면 18,364 바이트를 확인할 수 있으며, 해당 텍스트 내용이 기록되어 있다.


$ ls -l http.bin
-rw-r--r-- 1 rigel rigel 18364 2011-05-20 23:42 http.bin
$ head http.bin
HTTP/1.1 200 OK
Date: Thu, 13 May 2004 10:17:12 GMT
Server: Apache
Last-Modified: Tue, 20 Apr 2004 13:17:00 GMT
ETag: "9a01a-4696-7e354b00"
Accept-Ranges: bytes
Content-Length: 18070
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=ISO-8859-1


다시 streams 로 돌아와서 필터정보를 사용해 보자. match 라는 명령어를 이용하면 되고, 아래 예는 GET 으로 필터를 건 것이다.

streams> match GET
applying new match expression...
streams> list
    0:       0.000000      30.063228  145.254.160.237:3372 > 65.208.228.223:80 (479 bytes)
streams>

그리고 status 정보는 현재의 상태 정보를 보여준다.

streams> status

  trace file:           ./http.cap
  bpf expression:       tcp
  match expression:     GET
  stream filter:        off (list all streams)
  time display mode:    relative
  external program:     hd
  output file:          ./http.bin

사용방법은 간단하며, 스트림화된 정보를 다루는 경우 유용하게 사용될 수 있다. 패킷파일을 다루는 도구는 다양하며, 업무 및 기타 사용목적에 따라서 필요한 도구는 달라진다. 앞으로도 다양한 도구를 소개할 예정이며, 여러분들에게 필요한 도구를 선택해 사용하면 된다.

지금 당장 이런것이 필요없더라도, 이런것이 있구나 하는 정도 알아두고 필요할때 패킷인사이드에서 검색해서 사용해 보자.

댓글 없음:

댓글 쓰기