ARP / 파이썬3 ARP 클래스 정의 및 packet.py, sniffer.py 수정에 대해서 정리한다.
1계층: 물리계층
2계층: 데이터-링크 계층
PDU: frame, 이더넷 프레임
* 이더넷 헤더
DST + SRC + TYPE + DATA
7 ~ 2 계층: 볼 수 있는 영역, 운영체제
1 계층: 볼 수 없는 영역, 물리(NIC)
( Preamble, SFD, FCS<Frame Check Sqeunce>, Padding )
* Preamble, SFD, FCS, Padding 같은 헤더들은 NIC 장치를 지날때 붙는데 수신 패킷에는 패딩이 붙고
송신 패킷에는 패딩이 붙지 않는걸 보면 알 수 있다.
* 최소 프레임 크기 : 64바이트 (헤더 14 + 데이터 46 + FCS 4)
( 스니퍼를 이용해서 보면 FCS는 보이지 않고 데이터에 남는 부분은 padding으로 채워진다 )
2계층: 라우팅이 필요하지 않은 네트워크
- 아이피 설정만 제대로 되어 있으면 무조건 통신이 되야한다.
- 과거에는 MAC address만으로 통신이 가능했을 것
- 네트워크상에서 식별자로 아이피를 사용하기 시작
예). 192.168.10.2 호스트와 통신을 하고자 한다면?
해당 네트워크는 스위치만으로 연결
192.168.10.2 호스트의 물리 주소를 알 수 있어야 한다. -> 이더넷 헤더를 만들수 있다.
ARP( Address Resolution Protocol )
- 아이피 주소로 물리 주소를 확인할 수 있는 프로토콜
- 운영체제마다 동작하는 방식이 약간 다르다.
1. 윈도우즈
- 주기적으로 같은 네트워크에 호스트들의 물리주소를 수집을 하고 캐시를 해 놓는다.
2. 리눅스
- 통신하기 직전에 상대방의 물리 주소를 확인하고 일정 시간동안만 캐시를 유지
( 같은 대역만 캐시를 유지 )
eth 헤더: b'\xff\xff\xff\xff\xff\xff\xd0P\x99\xa82\x99\x08\x06
1. ARP 요청( request )
- 상대방의 맥 어드레스를 질의
arp 헤더: b'\x00\x01\x08\x00\x06\x04\x00\x01\xd0P\x99\xa82\x99\xc0\xa8\x01S\x00\x00\x00\x00\x00\x00\xc0\xa8\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
1). 하드웨어 타입(2바이트): 이더넷(0x0001), 토큰링, ... ( 1계층 네트워크 구조를 나타냄 )
2). 프로토콜 타입(2바이트): 아이피 버전4, 아이피 버전6, ...
3). 하드웨어 길이(1바이트): MAC 주소 길이
4). 프로토콜 길이(1바이트): ipv4 -> 4, ipv6 -> 6
5). opcode(2바이트): arp request: 1, arp response: 2
6). sender mac(6바이트)
7). sender ip(4바이트)
8). target mac
9). target ip
2. ARP 응답( response )
- arp 응답 헤더는 opcode가 2가 되고 자신의 mac 주소를 헤더에 실어서 보내준다.
d0:50:99:a8:32:99 -> ff:ff:ff:ff:ff:ff type: 0x806
맥 어드레스의 브로드캐스팅 주소 : ff:ff:ff:ff:ff:ff
아이피의 브로드 캐스팅 주소: 호스트가 255인 아이피를 브로드 캐스팅 주소
- arp 클래스 정의 및 packet.py, sniffer.py 수정
( packet.py / sniffer.py에서 이전 코드와 바뀐 부분은 분홍색으로 구분을 해두었다 )
arp.py
class Arp:
def __init__( self, raw=None ):
if raw != None:
self._hard_type = raw[:2]
self._proto_type = raw[2:4]
self._hard_len = raw[4:5]
self._proto_len = raw[5:6]
self._opcode = raw[6:8]
self._sender_mac = raw[8:14]
self._sender_ip = raw[14:18]
self._target_mac = raw[18:24]
self._target_ip = raw[24:28]
@property
def header( self ):
return self._hard_type + self._proto_type + self._hard_len + self._proto_len \
+ self._opcode + self._sender_mac + self._sender_ip + self._target_mac \
+ self._target_ip
@property
def hard_type( self ):
(hard_type,) = struct.unpack('!H', self._hard_type)
return hard_type
@property
def proto_type( self ):
(proto_type,) = struct.unpack('!H', self._proto_type)
@property
def hard_len( self ):
(hard_len,) = struct.unpack('!B', self._hard_len)
return hard_len
@property
def proto_len( self ):
(proto_len,) = struct.unpack('!B', self._proto_len)
return proto_len
@property
def opcode( self ):
(opcode,) = struct.unpack('!H', self._opcode)
return self._opcode
@property
sender_mac = struct.unpack('!6B', self._sender_mac)
sender_mac = '%02x:%02x:%02x:%02x:%02x:%02x' % sender_mac
return sender_mac
@property
sender_ip = struct.unpack('!4B', self._sender_ip)
sender_ip = '%d.%d.%d.%d' % sender_ip
return sender_ip
@property
target_mac = struct.unpack('!6B', self._target_mac)
target_mac = '%02x:%02x:%02x:%02x:%02x:%02x' % target_mac
return target_mac
@property
target_ip = struct.unpack('!4B', self._target_ip)
target_ip = '%d.%d.%d.%d' % target_ip
return target_ip
packet.py
from header.ip import *
from header.udp import *
from header.arp import *
class Packet:
def __init__( self, raw ):
self._eth = Eth( raw[:14] )
if self._eth.type == 0x0800:
self.analyze_ip( raw[14:] )
if self._eth.type == 0x0806:
self.analyze_arp( raw[14:] )
def analyze_ip( self, raw ):
self._ip = Ip( raw )
if self._ip.type == 17:
self.analyze_udp( raw[20:] )
def analyze_udp( self, raw ):
self._udp = Udp( raw )
def analyze_arp( self, raw ):
self._arp = Arp( raw )
@property
def eth( self ):
return self._eth
@property
def ip( self ):
return self._ip
@property
def arp( self ):
return self._arp
sniffer.py
import socket
import struct
import time
from header.packet import *
raw = socket.socket( socket.PF_PACKET, socket.SOCK_RAW )
raw.bind( ('eth0', socket.SOCK_RAW) )
while True:
data, addr = raw.recvfrom( 65535 )
packet = Packet( data )
if packet.eth.type == 0x0806:
print("data: ", data)
print( packet.eth.src + ' -> ' + packet.eth.dst + 'type: ' + hex(packet.eth.type) )
print( "opcode: ", packet.arp.opcode )
print( "sender ip: " + packet.arp.sender_ip + " target ip: " + packet.arp.target_ip )
print( "sender mac: " + packet.arp.sender_mac + " target_mac: " + packet.arp.target_mac )
print()
'프로그래밍 > NETWORK HACKING' 카테고리의 다른 글
[네트워크 보안] ARP Cache Poisoning을 이용한 ARP Spoofing (0) | 2017.06.23 |
---|---|
[네트워크 보안] ARP 클래스 setter 추가 / arping.py (0) | 2017.06.22 |
[네트워크 보안] 파이썬3 UDP 프로토콜 클래스 정의 및 packet.py / sniffer.py 수정 (0) | 2017.06.21 |
[네트워크 보안] 파이썬3 클래스로 각 프로토콜 헤더를 정의( packet.py, eth.py, ip.py, sniffer.py ) (0) | 2017.06.20 |
[네트워크 보안] 파이썬3 struct 모듈을 이용한 패킷 분석 (0) | 2017.06.17 |
댓글