메서드를 활용한 계층별 헤더 분석

2017. 6. 17. 13:31NetworkHacking/Network





이전 글에서 헤더를 분석할 때 일일히 직접 16진수로 형변환 시켰습니다

이는 너무 번거로운 과정이므로 메서드를 이용해서 헤더의 정보를 얻어오는 실습입니다


이전 sniffer프로그램으로 얻어온 데이터를 다시 사용하겠습니다

104 data : 

b"\xd0~5\xdaO\x1c\x00\x0c)\xf0bs\x08\x00E\x00\x00!\x00\x00@\x00@\x11\xb3\xe2\xc0\xa8\x02\xb3\xc0\xa8\x02\xe6 \xa4\x8e'\x10\x00\riyhello"

105 data :  b"\x00\x0c)\xf0bs\xd0~5\xdaO\x1c\x08\x00E\x00\x00!\x00\x00@\x00@\x11\xb3\xe2\xc0\xa8\x02\xe6\xc0\xa8\x02\xb3 '\x10\xa4\x8e\x00\riyhello\x00\x00\x00\x00\x00\x00\x    00\x00\x00\x00\x00\x00\x00"




헤더 분석과정은 다음과 같습니다

[1] 가상머신에서 파이썬을 실행시킨 후 struct모듈을 import합니다

[2] 헤더의 정보를 긁어온다

[3] 각 헤더별로 분리한 후 바이트 크기에 맞춰서 unpack 시킨다 ( bytes -> 숫자(10진수) )

- pack,unpack 옵션

! : little endian :  시스템 메모리에서 데이터를 읽는 방식 ( 1byte씩 역순으로 읽는 방식 )

B : 1byte크기의 바이트형(또는 인트형)으로 변환

H : 2byte크기의 바이트형(또는 인트형)으로 변환

L :  4byte크기의 바이트형(또는 인트형)으로 변환


* 그림 참고

리틀엔디안 방식으로 254(인트)를 각각 1바이트(\xfe) 2바이트(\x00\xfe) 4바이트(\x00\x00\x00\xfe)크기의 바이트형태로 pack시켰습니다


[ 그림1 ]


헤더정보를 복사해서 packet에 저장하고 각 헤더별로 분류했습니다

각각 이더넷헤더(14byte) , 아이피헤더(20byte) , UDP헤더(8byte) 입니다

이제 각 헤더들을 바이트 크기에 맞춰서 분류시키겠습니다


>>> struct.unpack( '형식' , 변환할 데이터 ) : 데이터의 개수와 형식의 개수는 일치해야합니다


각각의 헤더들은 아래 그림들과 같이 분류시킬 수 있습니다


먼저 이더넷 헤더입니다

[ 그림2 ]


다음은 아이피 헤더입니다

[ 그림3 ]


마지막으로 UDP 헤더입니다

[ 그림4 ]



unpack메서드를 통해서 각 데이터들이 10진수의 형태로 형변환되어짐은 알 수 있습니다

pack메서드는 unpack메서드의 인자들을 서로 바꿔주기만 하면 됩니다



# 추가 내용 #

[1] ip헤더에서 Version & 헤더길이 따로 가져오기

[2] 내 컴퓨터의 MAC Address를 바이트로 출력하기


[1] Version & Header Length

[ 그림5 ]


[1-1] 버전 구하기

버전 & 길이의 값이 69 = 0x45 = 0100 / 0101 => 버전 / 길이

따라서 4만큼 shift연산시키면 해당 값은 0000 0100 이되어 4가된다 => IPv4


[1-2] 길이 구하기

버전 & 길이의 값 69 = 0x45 = 0100 0101 => 해당 값을 0x0F와 and연산한다

0100 0101

0000 1111 and

=> 0000 0101 그리고 2만큼 shift연산시키면 0001 0100 = 20 : 길이가 된다



[2] MAC Address를 바이트로 출력하기 

[ 그림6 ]


#ifconfig 명령어로 확인하여 MAC Address를 긁어오면 위 그림과 같은 형태를 가지고 있습니다 ( 마지막 " : "는 오타 )

해당 문자열을 16진수로 바꾸어서 패킷을 필터링하는데 사용할 수 있습니다

그런데 문자열은 어떻게 변환시킬 수 있을까요? 이전에 했던 과정들은 모두 숫자를 대상으로 unpack시켰었습니다 )

아래 그림과 같은 과정이 필요합니다


[ 그림7 ]


반복문 사용

>>> dst

'd0:7e:35:da:4f:1c'

>>> dst = dst.split(':')

>>> dst

['d0', '7e', '35', 'da', '4f', '1c']

>>> for i in range(len(dst)):

...   dst[i]=int(dst[i],16)

... 

>>> dst

[208, 126, 53, 218, 79, 28]

>>> dst = struct.pack('!BBBBBB',dst)

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

struct.error: pack expected 6 items for packing (got 1) // 직접써주어야함 ( dst를 하나로 인식해버림 )

>>> dst = struct.pack('!BBBBBB',dst[0],dst[1],dst[2],dst[3],dst[4],dst[5])

>>> dst

b'\xd0~5\xdaO\x1c'


MAC Address를 바이트 형태로 얻어냈습니다. 이 값을 이용해서 내 장치로 들어오는 데이터들을 필터링해낼 수 있습니다