Source code for aptdetector.network.sniffer

"""``sniffer`` contains base network sniffer implemntation

but if you
want to use it, Currently there are two implementation to choose from:
* :class:`URLSniffer` - Sniff urls that are moving around in network
* :class:`FileSniffer` - Sniff files that are in the network
Both classes are :class:`BaseSniffer` subtypes
"""
from aptdetector.network.packet import TcpPacket
from aptdetector.network.parser.parse_pcap import parse_pcap_file
from aptdetector.utils.exception import FileParsingException
from aptdetector.utils.typecheck import params, returns

from collections import OrderedDict


[docs]class BaseSniffer(object): """The ``BaseSniffer`` is an implementation of a bare minimum network sniffer. Raises: FileNotFoundError: pcap_file was not found on the system or you do not have permission >>> from aptdetector.network.sniffer import BaseSniffer >>> base_sniffer = BaseSniffer() >>> base_sniffer.pcap_file='/tmp/notexist.pcap' [Errno 2] No such file or directory: '/tmp/notexist.pcap' >>> base_sniffer.pcap_file >>> base_sniffer.pcap_file='examples/test.pcap' >>> base_sniffer.pcap_file 'examples/test.pcap' >>> for pkt in base_sniffer.connections(): ... print(pkt) ... Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'NoneType' object is not iterable >>> base_sniffer.parse() >>> for pkt in base_sniffer.connections(): ... print(pkt) ... 182.160.157.199:80 ---> 192.168.204.136:49174 http://www.magmedia.com.au/ 182.160.157.199:80 ---> 192.168.204.136:49178 http://www.magmedia.com.au/wp-includes/js/jquery/jquery.js?ver=1.7.2 182.160.157.199:80 ---> 192.168.204.136:49178 http://www.magmedia.com.au/wp-content/uploads/2014/01/MetroWest_COVER_Issue2_Feb2014.jpg 108.61.196.84:80 ---> 192.168.204.136:49184 http://pixeltouchstudios.tk/seedadmin17.html 173.244.195.17:80 ---> 192.168.204.136:49185 http://grannityrektonaver.co.vu/15c0b14drr9f_1_08282d03fb0251bbd75ff6dc6e317bd9.html 182.160.157.199:80 ---> 192.168.204.136:49178 http://www.magmedia.com.au/images/footer/3000melbourne.png 182.160.157.199:80 ---> 192.168.204.136:49178 http://www.magmedia.com.au/images/footer/3207portmelbourne.png 182.160.157.199:80 ---> 192.168.204.136:49178 http://www.magmedia.com.au/wp-content/uploads/2012/09/background1.jpg 173.244.195.17:80 ---> 192.168.204.136:49185 http://grannityrektonaver.co.vu/00015d76d9b2rr9f/1415286120 173.244.195.17:80 ---> 192.168.204.136:49187 http://grannityrektonaver.co.vu/00015d766423rr9f/1415286120 173.244.195.17:80 ---> 192.168.204.136:49185 http://grannityrektonaver.co.vu/00015d76rr9f/1415286120/5/x00809070554515d565b010b03510053535c0505;1;6 173.244.195.17:80 ---> 192.168.204.136:49185 http://grannityrektonaver.co.vu/00015d76rr9f/1415286120/5/x00809070554515d565b010b03510053535c0505;1;6;1 173.244.195.17:80 ---> 192.168.204.136:49185 http://grannityrektonaver.co.vu/00015d76rr9f/1415286120/7 173.244.195.17:80 ---> 192.168.204.136:49185 http://grannityrektonaver.co.vu/00015d761709rr9f/1415286120 173.244.195.17:80 ---> 192.168.204.136:49187 http://grannityrektonaver.co.vu/00015d76rr9f/1415286120/8 """ def __init__(self): """conversations must be none at first""" self.__pcap_file = None self.__conversations = None
[docs] def parse(self): """parse the pcap file using :class:parse_pcap_file""" try: all_packets = parse_pcap_file(self.__pcap_file) self.__conversations = all_packets except FileParsingException as err: print(err) except IOError as err: print(err)
@property @returns(str) def pcap_file(self): """returns address of Pcap file""" return self.__pcap_file @pcap_file.setter @params(self=object, value=str) def pcap_file(self, value): """set the address of Pcap file""" try: with open(value): self.__pcap_file = value self.__conversations = None except IOError as err: print(err)
[docs] def connections(self, source=None, destination=None, simplify=False, show_port=False): """parsed connections. The ``connections`` function is a list that contains all connections from source to any or from any to destination Args: source (str): Source Address in Network Connections destination (str): Destination Address in Network Connections simplify (bool): should we simplify the results show_port (bool): should we hide port numbers Returns: a List of :class:`TcpPacket` or an :class:`OrderedDict` containing all the comminucations from src or to the dst Raises: None >>> from aptdetector.network.sniffer import BaseSniffer >>> sni = BaseSniffer() >>> sni.pcap_file='examples/test.pcap' >>> sni.parse() >>> sni.connections(destination='173.123.12.1') >>> sni.connections(source='182.160.157.199',show_port=True) OrderedDict([('182.160.157.199:80', ['192.168.204.136:49174', '192.168.204.136:49178', '192.168.204.136:49178',\ '192.168.204.136:49178', '192.168.204.136:49178', '192.168.204.136:49178'])]) >>> >>> sni.connections(source='173.244.195.17',show_port=True,simplify=True) OrderedDict([('173.244.195.17:80', ['192.168.204.136:49185', '192.168.204.136:49187'])]) >>> >>> sni.connections(destination='192.168.204.136',show_port=True,simplify=True) OrderedDict([('192.168.204.136:49174', ['182.160.157.199:80']), ('192.168.204.136:49178', ['182.160.157.199:80']),\ ('192.168.204.136:49184', ['108.61.196.84:80']), ('192.168.204.136:49185', ['173.244.195.17:80']), ('192.168.204.136:49187',\ ['173.244.195.17:80'])]) """ if source is not None: if TcpPacket.valid_ip(source): target = source target_id = 1 else: print("source is not a correct ip") return None elif destination is not None: if TcpPacket.valid_ip(destination): target = destination target_id = 2 else: print("destination is not a correct ip") return None else: target = None all_packets = OrderedDict() if target is None: return self.__conversations else: for pkt in self.__conversations: if (pkt.sourceHost != target and target_id == 1) or ( pkt.destinationHost != target and target_id == 2): continue key = pkt.create_packet(target_id=target_id, show_port=show_port, reverse=False) reverse_key = pkt.create_packet(target_id=target_id, show_port=show_port, reverse=True) if key in all_packets.keys(): # all_packets have been initialized before if reverse_key in all_packets[key] and simplify is True: # duplicate, no need to append pass else: # new value all_packets[key].append(reverse_key) else: # all_packet should be initialized all_packets[key] = [reverse_key] if len(all_packets) < 1: return None return all_packets