带套接字和python的低级数据包嗅探器

时间:2019-01-28 22:12:08

标签: python sockets struct sniffer

  

底部的整个脚本。

因此,我正按照标题所说的尝试在python中创建LowLevel数据包嗅探器。创建原始套接字并捕获数据包的过程似乎正常。

我的问题是:当我尝试使用以下代码将源IP和目标IP转换为人类可读形式时:

self.src_address = socket.inet_ntoa(struct.pack('<L', self.src))
self.dst_address = socket.inet_ntoa(struct.pack('<L', self.dst))

我收到以下错误消息:

Traceback (most recent call last):
  File "ip_header.py", line 68, in <module>
    sniffer()
  File "ip_header.py", line 62, in sniffer
    header = IP(raw_buffer)
  File "ip_header.py", line 31, in __init__
    self.src_address = socket.inet_ntoa(struct.pack('<L', self.src))
struct.error: 'L' format requires 0 <= number <= 4294967295

我知道错误是由struct.pack('<L', self.src)引起的
因此,我将格式从Long(L)更改为Long Long(Q)。然后我又收到由函数socket.inet_ntoa()引起的另一个错误。

OSError: packed IP wrong length for inet_ntoa

基本上,此功能将32位压缩的IPv4地址(类似字节的对象,长度为4个字节)转换为其标准的点分四进制字符串表示形式(例如,“ 123.45.67.89”)。

机智将src和dst IP转换为人类可读的格式,我得到了一堆无用的数字(显然这些数字代表IP)

procotol : ICMP, src : 2623909733031061696 -> dst : 6651666592092407870



这是整个脚本

#!/usr/bin/env python3
import struct
import socket
from ctypes import * 

class IP(Structure):
    '''
    This class parse IP header
    '''
    # list of ip protocols

    # structre of ip header
    _fields_ = [
            ("ihl", c_ubyte, 4),    # Internet Header Length represent the number of 32bits words.
            ("version", c_ubyte, 4),    # ip version number ( 4 for ipv4 ) , size = 4 bits
            ("tos", c_ubyte),
            ("len", c_ushort),  # Total Size of ip packet not only the header (20 bytes < len < 65535), size = 2 bytes
            ("id", c_ushort),   
            ('offset', c_ushort),
            ('ttl', c_ubyte),   # Time To Live in seconds , size = 1 byte
            ('protocol_num', c_ubyte),  # Protocol Number , (1 : icmp, 6:tcp, 17:udp ...) , size = 1 byte
            ('sum', c_ushort),  # Header CheckSum, size = 2 bytes
            ("src", c_ulong),   # Source Address , size = 4 bytes
            ("dst", c_ulong)    # Destination Address , size = 4 bytes
    ]
    def __new__(self, socket_buffer=None):
        # create ctypes buffer from socket buffer
        return self.from_buffer_copy(socket_buffer)

    def __init__(self, socket_buffer=None):
        # human readable ip
        self.src_address = socket.inet_ntoa(struct.pack('<L', self.src))
        self.dst_address = socket.inet_ntoa(struct.pack('<L', self.dst))

        # get type of protocol
        if self.protocol_num == 1:
            self.protocol = 'ICMP'
        elif self.protocol_num == 6:
            self.protocol = 'TCP'
        elif self.protocol_num == 17:
            self.protocol = 'UDP'
        else :
            self.protocol = self.protocol_num

def sniffer():
    '''
    create raw socket , sniff packets , close socket
    '''

    # create socket
    socket_protocol = socket.IPPROTO_ICMP
    sniff = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)

    # include ip header in the capture
    sniff.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

    # capture packet 
    try :
        while True:
            raw_buffer, addr = sniff.recvfrom(4096)

            # parse packet header
            header = IP(raw_buffer)
            print("procotol : {}, src : {} -> dst : {}".format(header.protocol, header.src_address, header.dst_address))
    except KeyboardInterrupt:
        sniff.close()

if __name__ == '__main__':
    sniffer()

0 个答案:

没有答案