본문 바로가기
프로그래밍/NETWORK HACKING

[네트워크 보안] ARP / 파이썬3 ARP 클래스 정의 및 packet.py, sniffer.py 수정

by B T Y 2017. 6. 22.
반응형

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() 

 

 

 

반응형

댓글