스캔 프로그래밍 / 계층별 헤더 프로그래밍

2017. 6. 14. 21:12NetworkHacking/Network




UDP , TCP 소켓을 만들어 보았고 , 이번에는 raw 소켓입니다

로우소켓은 특정한 타입이 없는 소켓으로써 UDP나 TCP 등, 타입을 가리지 않고 모든 정보를 읽어들이는 장점을 가집니다

이번에는 특정 장치에 대해서 스니퍼 프로그래밍을 실시하고 해당 장치에 들어오고 나가는 모든 패킷들을 검사하겠습니다



[1] 로우 소켓을 생성한다

로우 소켓은 장치명을 대상으로 프로그래밍 합니다.

현재 제가 사용하는 NIC카드는 " eth0 " 입니다


[ 그림1 ]


장치명은 확인되었고  아래는 로우소켓생성 코드입니다

#vi sniffer.py

 import socket

 raw = socket.socket( socket.PF_PACKET , socket.SOCK_RAW )

 raw.bind( ( 'eth0' , socket.SOCK_RAW ) )      // 로우소켓은 특정 장치를(eth0) 대상으로 합니다

 while True:

     data,addr = raw.recvfrom( 65535 )

     print( "data : ", data )



[ 그림2 스니퍼프로그램 실행 ]


[2] #python3 sniffer.py > log.txt 

해당 장치명으로 들어오고 나가는 모든 패킷들을 읽어들입니다. 리다이렉션을 통해 log.txt 파일에 저장하도록 했다 ( 워낙에 정보가 빨리 읽혀지고 많다 )

해당 작동을 계속 실행시킨 상태에서 다음 과정으로 넘어간다


[3] 해당 장치명을 이용한 서버와 클라이언트의 정보교환을 실행한다 ( 다른 컴퓨터와 정보를 교환했음)


 import socket

 sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

 sock.bind(('100.100.100.110',8080))

 while True:

     data,addr=sock.recvfrom(65535)

     print(" Server is received data : ",data.decode())

     print(" Send Client IP : ", addr[0] )

     print(" Send Client Port :", addr[1] )

 import socket

 sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

 while True:

     data = input()

      sock.sendto(data.encode(),('100.100.100.110',8080))

      print("Client send and recieved data : ",data)

     print(" data from IP : ", addr[0])

     print(" data from Port : " , addr[1] )


[ 서버 / 클라이언트 ] 

[ 그림3 서로 데이터를 교환한 모습]



서버와 클라이언트 사이에서 hello 와 hahaha 라는 데이터를 서로 교환하였습니다

해당 기록이 log.txt 에 남아있을 것이므로 확인해보도록 하겠습니다


[4] 패킷 교환 정보 확인

log.txt파일을 vi편집기로 열어서 hello문자열을 검색해서 찾아냅니다

클라이언트의 입장으로 작업을 하였고, 104data는 정보를 보냈을 때, 105data는 서버로부터 정보를 받았을 때의 정보입니다

#vi log.txt 


" /hello " 입력하시면 찾을 수 있습니다

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\x00\x00\x00\x00\x00\x00\x00"


서버와 클라이언트가 교환한 데이터 hello 문자열 앞에 알수없는 문자들이 보이실겁니다 이게바로 헤더입니다

아스키코드표를 확인하여 해당 문자들을 16진수로 변환시켜서 확인하여야합니다


헤더 : 보내려는 데이터에 대한 정보를 표현해놓은 부분

프로토콜 헤더 : 계층마다 필요한 정보들을 표현 - 1계층부터 4계층까지의 정보들이 담겨 있습니다

헤더를 읽을 때에는 앞에서부터 차례에 맞게 읽어나가셔야합니다


[ 2계층의 정보 ]

- 주소체계 : MAC address , H/W address

- 16진수 3자리로 표현 ( 앞3자리 : 제조사 , 뒤 3자리 : 하드웨어주소 )

- PDU : Frame

- 프로토콜 : 터널링(PPTP,L2TP, ... ) , ARP


- 이더넷 헤더 : 14바이트의 고정크기를 가진다. 헤더의 처음부터 14바이트 

\xd0~5\xdaO\x1c\x00\x0c)\xf0bs\x08\x00 "

1> 출발지 맥주소 : 이더넷 헤더중 처음 6바이트

"\xd0~5\xdaO\x1c" => 0xd0 : 0x7e :0x05 : 0xda : 0x00 :0x1c


2> 도착지 맥주소 : 그 다음 6바이트

"\x00\x0c)\xf0bs" => 0x00 : 0x0c : 0x29 : 0xf0 : 0x62 : 0x73


3> 이더넷 타입 : 마지막 2바이트 

"\x08\x00" => 0x0800

0x0800 => IPv4의 데이터라는 뜻

0x0806 => ARP의 데이터라는 뜻

0x86dd => IPv6의 데이터라는 뜻


# 해당 이더넷 타입에 따라서 뒤에 문자들이 변하기 때문에 헤더를 읽을 때에는 앞에서부터 해석합니다

# 헤더의 앞 14byte는 무조건 이더넷 헤더를 읽어들입니다. 따라서 필터링에 많이 쓰입니다


[ 3계층의 정보 ] ( 보통 " E " 문자열이 3계층 헤더의 시작입니다 ) 

- 주소체계: IPv4, IPv6

- 목적지까지의 경로를 선정합니다

- PDU (Protocol data unit ) : Packet


- ip헤더 : 20바이트의 크기를 가진다 , ip와 관련된 정보들이 저장

" E\x00\x00!\x00\x00@\x00@\x11\xb3\xe2\xc0\xa8\x02\xb3\xc0\xa8\x02\xe6 "

1> version & header length : 1byte

" E " => 0x45 => 0100 / 0101 각각 버전 / 길이 입니다

왼쪽으로 두칸 shift연산하면 실제길이가 나옵니다 => 0000 0101 -> 0001 0100 = 20byte : 고정된 값으로 사용

2> server filed : 1byte : 지금은 사용하지 않고 IPv6에서 사용합니다

" \x00 " 

3> ip패킷의 전체 크기 : 2byte : 3계층헤더 + 4계층헤더             

" \x00! " => 0x0021 = 33byte

4> identification : 2byte

" \x00\x00 "

5> flag & fragment offset : 2byte

"@\x00 "

6> TTL ( Time To Live ) 최대 라우터의 개수 : 1byte

- 운영체제마다 설정된 값이 다르며, 출발지에서 도착지까지 가는데 거치는 라우터의 개수를 저장
- 설정된 값을 초과하면 해당 패킷을 폐기된다
- unix : 254
- linux : 64
- windows : 128

" @ " : 64

7> 포로토콜 타입 : 1byte

- ip패킷이 전달하는 프로토콜 타입 ( tcp(0x06) , udp(0x11) , icmp(0x01) )

" \x11 " : UDP

8> 체크섬 : 2byte

"\xb3\xe2 " => 0xb3e2

9> 출발지 IP : 4byte

\xc0\xa8\x02\xb3 " => 0xc0.0xa8.0x02.0xb3 == 192.168.2.179

10> 도착지 IP : 4byte

\xc0\xa8\x02\xe6 " => 0xc0.0xa8.0x02.0xe6 == 192.168.2.230



[ 4계층의 정보 ]

- 주소체계 포트

- 데이터의 전송방법, 어떠한 통신방식, 송신자와 수신자의 정보를 표현

- UDP나 TCP를 사용

- PDU : Segment


실습중에 UDP통신을 사용하였으며, 해당 정보는 UDP통신에 대한 헤더정보입니다


- UDP헤더 : 8byte의 고정된 크기를 가집니다

\xa4\x8e'\x10\x00\riy "


1> 출발지의 포트번호 : 2byte

" \xa4\x8e " => 0xa48e = 42126

2> 도착지의 포트번호 : 2byte

" '\x10 " => 0x2710 = 10000

3> UDP 세그먼트의 크기 ( 헤더 + 데이터 ) : 2byte

" \x00\xr " => 0x000d = 13

4> 체크섬 : 에러를 체크하는 기능 : 2byte

" iy " => 0x6979 



# 이와 같이 헤더를 보면 각 계층에 대한 정보들이 들어있어 라우터가 헤더를 읽어들여 전송을 할 수 있게된다

# MAC Address 는 장치에게 주어지는 고유번호로 장치들을 구별할 수 있게한다

# Ethernet : 현재 가장 많이 쓰이는 데이터 교환 방식, 전기적 신호의 충돌을 이용하는 방식

# 추가 #

서브넷팅: 네트워크를 여러개의 더 작은 네트워크로 분할시키는 작업

서브넷마스크: 이 때 사용하는 값 , 실제 네트워크 아이디를 뽑아낼 때 사용

IP( Internet Protocol )란?

IP는 5개의 Class로 나뉘어져 있다 ( A,B,C,D,E )

[ 일반클래스 ]

1> A Class

- 첫번째 한자리의 숫자를 네트워크의 아이디로 사용한다

- 0.0.0.0 ~ 127.255.255.255    => 실제로는 0.0.0.1 ~ 127.255.255.254

- ( 00000000.00000000.00000000.00000000 ~ 01111111.11111111.11111111.11111111 )

- A Class의 서브넷마스크는 255.0.0.0


2> B Class

- 앞의 두자리 숫자를 네트워크 아이디로 사용한다

- 128.0.0.0 ~ 191.255.255.255 => 실제로는 128.0.0.1 ~ 191.255.255.24

- ( 10000000.00000000.00000000.00000000 ~ 10111111.11111111.1111111.11111111)

- B Class의 서브넷 마스크는 255.255.0.0


3> C Class

- 앞의 세자리 숫자를 네트워크 아이디로 사용한다

- 192.0.0.0 ~ 255.255.255.255 => 실제로는 192.0.0.1 ~ 223.255.255.254

- ( 11000000.00000000.00000000.00000000 ~ 11011111.11111111.11111111.11111111 )

- C Class의 서브넷마스크는 255.255.255.0 

[ 특수 클래스 ]



4> D Class : 멀티캐스트 용도로만 사용하도록 예약

 - 사용할 수 없다 ( 장비나 인터페이스에 설정할 수 없다 )

 - 서브넷이 없음

 - 공통비트 : 1110 , 111000000.0.0.1 ~ 1110111.255.255.254

-> 224.0.0.0 ~ 239.255.255.255 


5> E Class : 그냥 사용할 수 없음

 - 공통비트 : 1111 , 11110000.0.0.1 ~ 11111111.255.255.254

-> 240.0.0.1 ~ 255.255.255.254