헤더의 종류는 세가지로 나뉘어집니다( Ethernet헤더, IP헤더, UDP(orTCP)헤더 )
각각의 헤더 정보를 나누어 클래스로 만든다음 하나로 묶어주겠습니다 ( packet.py )
즉, 하나의 packet클래스안에 이더넷,아이피,유디피헤더 클래스들을 포함시켜 한번에 헤더의 각각의 정보를 분류하고 얻을 수 있다
[1] eth.py, udp.py, ip.py 각각의 클래스 생성
[2] packet.py에서 세개의 클래스들을 import한다
[3] 스니퍼프로그램에서 packet클래스를 이용해 각 정보를 이용한 필터링
[4] 원하는 정보만을 출력할 수 있다
[Server-A@ header]# vi eth.py // Eth클래스
import struct
class Eth:
def __init__(self,raw=None):
if raw != None:
self._dst=raw[0:6] // 도착지 맥주소
self._src=raw[6:12] // 출발지 맥주소
self._type=raw[12:14] // 이더넷 타입
def header(self):
return self._dst + self._src + self._type
def dst(self):
dst = struct.unpack('!6B',self._dst)
dst = '%02x:%02x:%02x:%02x:%02x:%02x' %dst
return dst // 'xx:xx:xx:xx:xx:xx' ex) 192.168.2.179 반환
def src(self):
src = struct.unpack('!6B',self._src)
src = '%02x:%02x:%02x:%02x:%02x:%02x' %src
return src // 'xx:xx:xx:xx:xx:xx' ex) 192.168.2.179 반환
def type(self):
(type,)=struct.unpack('!H',self._type) // 이더넷타입 반환 0x0800 (Ipv4 )
[Server-A@ header]# vi ip.py // Ip클래스
import struct
class Ip:
def __init__(self,raw=None):
if raw != None:
self._ver_and_len=raw[:1]
self._server=raw[1:2]
self._size=raw[2:4]
self._identification=raw[4:6]
self._flag_fragment=raw[6:8]
self._TTL=raw[8:9]
self._protocol=raw[9:10]
self._cksum=raw[10:12]
self._src=raw[12:16]
self._dst=raw[16:20]
@property
def ver:
(ver,)=struct.unpack('!B',ver_and_len)
ver=ver >> 4
return ver
@property
def length:
(len,)=struct.unpack('!B',ver_and_len)
len=(len & 0x0f ) << 2
return len
@property
def server(self):
(server,)=struct.unpack('!B',self._server)
return server
@property
def size(self):
(size,)=struct.unpack('!H',self._size)
return size
@property
def id(self):
(id,)=struct.unpack('!H',self._identification)
return id
@property
def flag(self);
(flag,)=struct.unpack('!H',self._flagFragment)
return flag
@property
def offset(self):
offset=(offset&0x1fff) << 2
return offset
@property
def ttl(self):
(ttl,)=struct.unpack('!H',self._TTL)
@property
def protocol(self):
(protocol,)=struct.unpack('!H',self._protocol)
return protocol
@property
def chksum(self):
(chksum,)=struct.unpack('!H',self._chksum)
return chksum
@property
def src(self):
src=struct.unpack('!BBBb,self._src)
src='%d.%d.%d.%d' %src
return src
@property
def dst(self):
dst=struct.unpack('!BBBb,self._dst)
dst='%d.%d.%d.%d' %dst
return dst
[Server-A@ header]# vi udp.py // Udp클래스
import struct
class Udp:
def __init__(self,raw):
self._src=raw[0:2] //출발지 포트번호
self._dst=raw[2:4] //도착지 포트번호
self._total=raw[4:6] // 헤더 전체 길이( data길이+8(헤더))
self._chksum=raw[6:8] // 체크섬
self._data=raw[8:] // 데이터
@property
def header(self):
return self._src + self._dst + self._len + self._chksum+self._data
@property
def src(self):
(src,)=struct.unpack('!H',self._src)
return src
@property
def dst(self):
(dst,)=struct.unpack('!H',self._dst)
return dst
@property
def total(self):
(total,)=struct.unpack('!H',self._total)
return total
@property
def chksum(self):
(chksum,)=struct.unpack('!H',self._type)
return chksum
@property
def data(self):
data=self._data.decode(errors='ignore')
return data
[Server-A@ tmp]# vi packet.py // Packet클래스
from header.eth import *
from header.ip import *
from header.udp import *
class Packet:
def __init__(self,raw):
self._eth=Eth(raw[:14]) // Eth클래스 객체 생성
if self.eth.type==0x0800: // 이더넷타입이 IPv4이라면
self.analyze_ip(raw[14:]) // ip클래스객체를 생성한다
def analyze_ip(self,raw): // ip클래스 객체생성 함수
self._ip=Ip(raw)
if self.ip.protocol==17: // protocol타입이 17 => UDP 이라면
self.analyze_udp(raw[20:]) // Udp클래스 객체를 생성해라
def analyze_udp(self,raw): // Udp클래스 객체 생성 함수
self._udp=Udp(raw)
@property
def eth(self): // eth클래스 객체반환
return self._eth
@property // ip클래스 객체반환
def ip(self):
return self._ip
@property
def udp(self): // udp클래스 객체반환
return self._udp
[Server-A@ tmp]# vi sniffer.py // 스니퍼 프로그램 ( 패킷클래스를 이용한 필터링 )
from packet import *
import time
import struct
raw=socket.socket(socket.PF_PACKET,socket.SOCK_RAW) // 로우소켓 생성
raw.bind(('eth0',SOCK_RAW)) // eth0 장치로 들어오는 모든 정보를 읽어들인다
while True:
data,addr=raw.recvfrom(65535) // eth0으로 들어온 데이터를 변수에 저장한다
packet=Packet(data) // 패킷 객체 생성
// 이더넷타입=IPv4 이고 UDP프토토콜사용하며 출발지나 도착지 포트번호가 8585인 경우
if (packet.eth.type == 0x0800 and packet.ip.protocol==17) and ( packet.udp.src == 8585 or packet.udp.dst == 8585 ) :
print(packet.eth.src + ' -> ' + packet.eth.dst + ' type : '+ hex(packet.eth.type))
print(packet.ip.src + ' -> ' + packet.ip.dst)
if packet.ip.protocol == 0x11: // 프토토콜타입이 0x11 ( 17 ) : UDP이라면
print()
print(str(packet.udp.src) + ' -> ' + str(packet.udp.dst))
print('total len : ' + hex(packet.udp.length))
print()
print('data : ' + packet.udp.data)