Example #1
0
 def test_malformed(self):
     from credslayer.core import manager
     pcap = FileCapture("samples/smb-crash.pcap")
     self.assertRaises(manager.MalformedPacketException,
                       manager._process_packet, Session(pcap[8]), pcap[8],
                       False)
     pcap.close()
Example #2
0
 def __init__(self, filename, summary=True, keep_packets=False):
     self.result = []
     self.cap = FileCapture(filename,
                            only_summaries=summary,
                            keep_packets=keep_packets)
     if filename in packet2num:
         self.length = packet2num[filename]
     else:
         self.length = self.packet_length()
Example #3
0
    def test_credit_cards_false_positives(self):
        pcap = FileCapture("samples/imap.pcap")
        credit_cards_found = set()

        for packet in pcap:
            strings = utils.extract_strings_splitted_on_end_of_line_from(
                packet)
            credit_cards_found |= extract.extract_credit_cards(strings)

        pcap.close()

        print(credit_cards_found)
        self.assertTrue(len(credit_cards_found) == 0)
Example #4
0
    def test_extract_emails(self):
        pcap = FileCapture("samples/imap.pcap")
        emails_found = set()

        for packet in pcap:
            strings = utils.extract_strings_splitted_on_end_of_line_from(
                packet)
            emails_found |= extract.extract_emails(strings)

        pcap.close()

        print(emails_found)

        self.assertTrue(len(emails_found) >= 46)
        self.assertTrue("*****@*****.**" in emails_found)
        self.assertTrue("*****@*****.**" in emails_found)
        self.assertTrue("*****@*****.**" in emails_found)

        # TODO: make this one work... The thing is, the email address is splitted in 2 different packets... Give up ?
        # self.assertTrue("*****@*****.**" in emails_found)

        pcap = FileCapture("samples/ldap-simpleauth.pcap")
        emails_found.clear()

        for packet in pcap:
            strings = utils.extract_strings_splitted_on_end_of_line_from(
                packet)
            emails_found |= extract.extract_emails(strings)

        pcap.close()

        print(emails_found)

        self.assertTrue(len(emails_found) == 1)
        self.assertTrue("*****@*****.**" in emails_found)
Example #5
0
    def __init__(self, pcapfile, userfilter=None):
        """Initialization method of the class.

        Parameters
        ----------
        pcapfile : str
            Path to a previously captured pcap.

        """
        self._tshark_pkts = FileCapture(
            input_file=pcapfile,
            keep_packets=False,
            use_json=True,
            include_raw=True,
            display_filter=userfilter)
    def listen(self, sniff_sni=False, sniff_cn=False, sniff_san=False, packet_count: int = None, debug: bool = False) -> Iterator[TLSHandshakeMessage]:
        # Workaround for pyshark, because SIGINT handling does not work properly
        original_sigint_handler = signal.getsignal(signal.SIGINT)
        if original_sigint_handler == signal.default_int_handler:
            signal.signal(signal.SIGINT, lambda *args: os._exit(0))

        try:
            # Currently only IPv4 is supported for BPF tcp data access. Manpage says: "this will be fixed in the future" for IPv6.
            # Until then, only the 'tcp' filter is applied
            # bpf_filter = 'tcp[((tcp[12:1] & 0xf0) >> 2):1] = 22'
            bpf_filter = 'tcp'
            display_filter = f'(ssl.record.content_type == 22 && ssl.handshake.type)'

            if self.bpf_filter != '':
                bpf_filter += f' && {self.bpf_filter.strip()}'
            if self.display_filter != '':
                display_filter += f' && {self.display_filter.strip()}'

            if packet_count is not None and packet_count <= 0:
                packet_count = None

            if self.input_file is not None:
                packet_iterator = FileCapture(
                    input_file=self.input_file, display_filter=display_filter, keep_packets=False, debug=debug
                )
            elif not sys.stdin.isatty():
                packet_iterator = PipeCapture(
                    pipe=sys.stdin.buffer, display_filter=display_filter, debug=debug
                )
            else:
                capture = LiveCapture(
                    interface=self.interface, bpf_filter=bpf_filter, display_filter=display_filter, debug=debug
                )
                packet_iterator = capture.sniff_continuously()

            if not (sniff_sni or sniff_cn or sniff_san):
                sniff_sni = True
                sniff_cn = True
                sniff_san = True

            for packet in packet_iterator:
                handshake_message = self._get_handshake_message(
                    packet, sniff_sni=sniff_sni, sniff_cn=sniff_cn, sniff_san=sniff_san
                )

                if handshake_message is not None:
                    yield handshake_message

                    if packet_count is not None:
                        packet_count -= 1
                        if packet_count <= 0:
                            break

        except Exception:
            pass

        # Restore original SIGINT handler
        signal.signal(signal.SIGINT, original_sigint_handler)

        return
Example #7
0
def process_training_file(app_name: str, file_path: str) -> List[Connection]:
    """
    Returns list of connections extracted from a training pcap file.

    Args:
        app_name: training app
        file_path: path to the training pcap file

    Returns:
        list of connections (TLS client hello + TLS server hello)
    """
    client_hellos = []
    server_hellos = []

    # Process all the packets from the file
    for packet in FileCapture(file_path):
        wpacket = WrappedPacket(packet)

        if wpacket.is_tls_client_hello() and wpacket.is_server_name_ok(
                app_name):
            tls_packet = TlsPacket(wpacket, app_name=app_name)
            client_hellos.append(tls_packet)

        if wpacket.is_tls_server_hello():
            server_hellos.append(TlsPacket(wpacket, app_name=app_name))

    return extract_connections(client_hellos, server_hellos)
Example #8
0
    def __init__(self, path):
        """Construct packet class."""
        self._log = log()

        import parsers.packet.models as models

        self._log.info("Reading {} packet file.".format(path))
        try:
            self.pcapfile = FileCapture(path, display_filter='coap or xmpp or mqtt')
        except:
            self.log.error("Unable to read {} packet file".format(path),
                           exc_info=True)
        self.packets = []

        for packet in self.pcapfile:
            time = int(float(packet.frame_info.time_epoch))
            src_macaddr = packet.eth.src
            dst_macaddr = packet.eth.dst

            protocol = packet.highest_layer

            src_ipaddr = packet.ip.src
            dst_ipaddr = packet.ip.dst

            if protocol == "COAP":
                src_port = packet.udp.srcport
                dst_port = packet.udp.dstport
                message = self.parse_coap(packet.coap)

            elif protocol == "XMPP":
                src_port = packet.tcp.srcport
                dst_port = packet.tcp.dstport
                message = self.parse_xmpp(packet.xmpp)

            elif protocol == "MQTT":
                src_port = packet.tcp.srcport
                dst_port = packet.tcp.dstport
                message = self.parse_mqtt(packet.mqtt)

            self.packets.append(models.Packet(
                time, src_macaddr, dst_macaddr, src_ipaddr, src_port,
                dst_ipaddr, dst_port, protocol, message
            ))

        self.pcapfile.close()
Example #9
0
 def __init__(self):
     Thread.__init__(self)
     self._messages: List[Message] = []
     self._is_split: bool = False
     self._current_message_id: int = -1
     self._current_message_instance_id: int = -1
     self._current_message_size: int = -1
     self._current_message_data: ByteArray = ByteArray(bytes())
     # self._capture: LiveCapture = LiveCapture('enp0s31f6', bpf_filter='tcp port 5555')
     self._capture: FileCapture = FileCapture('assets/port-5555.pcap')
Example #10
0
    def test_extract_credit_cards(self):
        pcap = FileCapture("samples/smtp-creditcards.pcap")

        credit_cards_found = set()

        for packet in pcap:
            strings = utils.extract_strings_splitted_on_end_of_line_from(
                packet)
            credit_cards_found |= extract.extract_credit_cards(strings)

        pcap.close()

        print(credit_cards_found)

        self.assertTrue(
            CreditCard("Visa", "4111-4000-4321-3210") in credit_cards_found)
        self.assertTrue(
            CreditCard("Visa", "4321 4444 3214 3212") in credit_cards_found)
        self.assertTrue(
            CreditCard("Mastercard", "5555 5555 5555 5555") in
            credit_cards_found)
Example #11
0
    def __init__(self, pcapfile, scapy_pkts=None, tshark_pkts=None):
        """Initialization method of the class.

        Parameters
        ----------
        pcapfile : str
            Path to a previously captured pcap.
        scapy_pkts : :obj:`PacketList`
            List of packets generated by Scapy.
        tshark_pkts : :obj:`FileCapture`
            List of packets generated by Pyshark.

        """
        if scapy_pkts:
            self._scapy_pkts = scapy_pkts
        else:
            self._scapy_pkts = rdpcap(pcapfile)
        if tshark_pkts:
            self._tshark_pkts = tshark_pkts
        else:
            self._tshark_pkts = FileCapture(pcapfile)
        self._i = -1
Example #12
0
def file_capture(pcap_files, bpf, out_file, count=0, dump=False):
    """

    :param dump: Dump to stdout if true, does not send packets
    :type dump: bool
    :type count: int
    :type out_file: str
    :type bpf: str
    :type pcap_files: List[str]
    """
    # try:
    # es = None
    # if node is not None:
    #     es = Elasticsearch(node)

    logging.debug('Loading packet capture file(s)')
    for pcap_file in pcap_files:
        logging.debug("Pcap file is: %s", pcap_file)
        capture = FileCapture(pcap_file, bpf, out_file)

        if not dump:
            decode_packets(capture, count)
        else:
            dump_packets(capture, count)
Example #13
0
def get_connections(file_path: str) -> List[Connection]:
    """
    Returns list of connections extracted from a pcap file.

    Args:
        file_path: path to the pcap file

    Returns:
        list of connections (TLS client hello + TLS server hello)
    """
    client_hellos = []
    server_hellos = []

    # Process all the packets from the file
    for packet in FileCapture(file_path):
        wpacket = WrappedPacket(packet)

        if wpacket.is_tls_client_hello():
            client_hellos.append(TlsPacket(wpacket))

        elif wpacket.is_tls_server_hello():
            server_hellos.append(TlsPacket(wpacket))

    return extract_connections(client_hellos, server_hellos)
Example #14
0
    def test_sessions_extract(self):
        from credslayer.core.session import SessionsManager

        sessions = SessionsManager()

        pcap = FileCapture("samples/ftp.pcap")

        for packet in pcap:
            sessions.get_session_of(packet)

        pcap.close()

        print(sessions)
        self.assertTrue(len(sessions) == 1)
        self.assertTrue(
            "TCP 10.10.30.26:43958 <-> 129.21.171.72:21" in sessions)

        sessions.clear()

        pcap = FileCapture("samples/imap.pcap")

        for packet in pcap:
            if "tcp" in packet:
                sessions.get_session_of(packet)

        pcap.close()

        print(sessions)
        self.assertTrue(len(sessions) == 3)
        self.assertTrue(
            "TCP 131.151.32.21:4167 <-> 131.151.37.122:143" in sessions)
        self.assertTrue(
            "TCP 131.151.32.91:3614 <-> 131.151.37.122:1065" in sessions)
        self.assertTrue(
            "TCP 131.151.32.91:1065 <-> 131.151.37.117:1065" in sessions)

        sessions.clear()

        pcap = FileCapture("samples/snmp-v1.pcap")

        for packet in pcap:
            if "udp" in packet:
                sessions.get_session_of(packet)

        pcap.close()

        print(sessions)
        self.assertTrue(len(sessions) == 3)
        self.assertTrue("UDP 172.31.19.54 <-> 172.31.19.73" in sessions)
        self.assertTrue("UDP 172.31.19.73 <-> 224.0.1.35" in sessions)
        self.assertTrue("UDP 172.31.19.255 <-> 172.31.19.73" in sessions)
Example #15
0
def readPackets(filepath) -> PacketList:
    fileCapture = FileCapture(str(filepath))
    packets = [p for p in fileCapture]
    return packets
Example #16
0
def read_pcap_file(pcap_file):
    packs = filter(None, map(make_obj, FileCapture(pcap_file)))
    return packs
Example #17
0
class Packet(object):
    """Packet filter by IoT related packet."""

    def __init__(self, path):
        """Construct packet class."""
        self._log = log()

        import parsers.packet.models as models

        self._log.info("Reading {} packet file.".format(path))
        try:
            self.pcapfile = FileCapture(path, display_filter='coap or xmpp or mqtt')
        except:
            self.log.error("Unable to read {} packet file".format(path),
                           exc_info=True)
        self.packets = []

        for packet in self.pcapfile:
            time = int(float(packet.frame_info.time_epoch))
            src_macaddr = packet.eth.src
            dst_macaddr = packet.eth.dst

            protocol = packet.highest_layer

            src_ipaddr = packet.ip.src
            dst_ipaddr = packet.ip.dst

            if protocol == "COAP":
                src_port = packet.udp.srcport
                dst_port = packet.udp.dstport
                message = self.parse_coap(packet.coap)

            elif protocol == "XMPP":
                src_port = packet.tcp.srcport
                dst_port = packet.tcp.dstport
                message = self.parse_xmpp(packet.xmpp)

            elif protocol == "MQTT":
                src_port = packet.tcp.srcport
                dst_port = packet.tcp.dstport
                message = self.parse_mqtt(packet.mqtt)

            self.packets.append(models.Packet(
                time, src_macaddr, dst_macaddr, src_ipaddr, src_port,
                dst_ipaddr, dst_port, protocol, message
            ))

        self.pcapfile.close()

    def get_method(self, code):
        """Get method from coap code."""
        if code == "0.01":
            return "GET"

        elif code == "0.02":
            return "POST"

        elif code == "0.03":
            return "PUT"

        elif code == "0.04":
            return "DELETE"

        else:
            return "Unassigned"

    def packet_type(self, _type):
        """Get type of coap packet."""
        if _type == 0x00:
            return "Confirmable"

        elif _type == 0x01:
            return "Non-confirmable"

        elif _type == 0x02:
            return "Acknowledgement"

        elif _type == 0x03:
            return "Reset"

    def get_msgtype(self, _type):
        """Get message type of MQTT."""
        if _type == 0x01:
            return "CONNECT"

        elif _type == 0x02:
            return "CONNACK"

        elif _type == 0x03:
            return "PUBLISH"

        elif _type == 0x04:
            return "PUBACK"

        elif _type == 0x05:
            return "PUBREC"

        elif _type == 0x06:
            return "PUBREL"

        elif _type == 0x07:
            return "PUBCOMP"

        elif _type == 0x08:
            return "SUBSCRIBE"

        elif _type == 0x09:
            return "SUBACK"

        elif _type == 0x0A:
            return "UNSUBSCRIBE"

        elif _type == 0x0B:
            return "UNSUBACK"

        elif _type == 0x0C:
            return "PINGREQ"

        elif _type == 0x0D:
            return "PINGRESP"

        elif _type == 0x0E:
            return "DISCONNECT"

        else:
            return "Reserved"

    def get_qostype(self, qos):
        """Get QoS type in MQTT."""
        if qos == 0x00:
            return "Fire and Forget"

        elif qos == 0x01:
            return "Acknowledged delivery"

        elif qos == 0x02:
            return "Assured delivery"

        else:
            return "Reserved"

    def parse_coap(self, packet):
        """Parse CoAP packet."""
        message = {
            'message_id': packet.mid,
            'code': self.get_method(packet.code),
            'type': self.packet_type(int(packet.type)),
        }

        if message['type'] == "Confirmable":
            try:
                message['token'] = packet.token
            except:
                pass

            try:
                message['payload'] = {
                    'description': packet.payload_desc,
                    'data': packet.payload.binary_value.decode(),
                }
            except:
                pass

        return message

    def parse_xmpp(self, packet):
        """Parse XMPP Protocol."""
        return {
            'xml_tag': packet.xml_tag
        }

    def parse_mqtt(self, packet):
        """Parse MQTT Protocol."""
        message = {
            'qos': self.get_qostype(int(packet.qos)),
            'retain': bool(packet.retain),
            'message_type': self.get_msgtype(int(packet.msgtype)),
        }

        try:
            message['topic'] = packet.topic
            message['message'] = packet.msg
        except:
            pass

        try:
            message['client_id'] = packet.clientid
        except:
            pass

        return message

    def __del__(self):
        """Destruct packet class."""
        self._log.info("Finishing packet parser...")
        del self
Example #18
0
def get_raw_cap(path_to_cap: str):
    return FileCapture(input_file=path_to_cap,
                       display_filter='icmp',
                       use_json=True,
                       include_raw=True)
Example #19
0
from pyshark import FileCapture
from binascii import unhexlify

# prevent error output
import os
import sys
f = open(os.devnull, 'w')
sys.stderr = f

# What is the IP address of the device that is pinging other devices?
cap = FileCapture('Basics.pcap', display_filter='icmp.type == 8')
print('IP of device pinging other devices:', cap[0]['ip'].addr)

# According to the ping traffic, what is the IP address of the host that is not up?
cap = FileCapture('Basics.pcap', display_filter='icmp.type == 8 && icmp.resp_not_found')
print('IP of device pinging other devices:', cap[0]['ip'].dst)

# What is the IP address of the device at 00:50:56:F9:77:70 given by ARP
cap = FileCapture('Basics.pcap', display_filter='arp.src.hw_mac == 00:50:56:f9:77:70')
print('ip address of device at 00:50:56:F9:77:70:', cap[0]['arp'].get('arp.src.proto_ipv4'))

# What is the first website that 10.0.0.132 visited?
cap = FileCapture('Basics.pcap', display_filter='http && ip.addr==10.0.0.132')
print('first website visited by 10.0.0.132:', cap[0]['http'].get('http.host'))

# How many bytes large is the only .ico file downloaded via HTTP?
cap = FileCapture('Basics.pcap', display_filter='http.request.uri contains ".ico"')
req = cap[0].frame_info.number
cap = FileCapture('Basics.pcap', display_filter='http.response')
for c in cap:
Example #20
0
from sys import exit
from pyshark import FileCapture

packets = None
try:
    packets = FileCapture("files/home.pcapng")
except Exception as e:
    print("===== Datei kann nicht eingelesen =====")
    exit(0)

#for packet in packets:
#print(packet)
packets.close()
Example #21
0
def get_cap(path_to_cap: str):
    return FileCapture(input_file=path_to_cap, display_filter='icmp')
Example #22
0
class TGenerator(object):
    """This class is responsible for generating the templates from scapy
    packages and completing the remaining layers with the dissectors of
    tshark through pyshark."""
    def __init__(self, pcapfile, scapy_pkts=None, tshark_pkts=None):
        """Initialization method of the class.

        Parameters
        ----------
        pcapfile : str
            Path to a previously captured pcap.
        scapy_pkts : :obj:`PacketList`
            List of packets generated by Scapy.
        tshark_pkts : :obj:`FileCapture`
            List of packets generated by Pyshark.

        """
        if scapy_pkts:
            self._scapy_pkts = scapy_pkts
        else:
            self._scapy_pkts = rdpcap(pcapfile)
        if tshark_pkts:
            self._tshark_pkts = tshark_pkts
        else:
            self._tshark_pkts = FileCapture(pcapfile)
        self._i = -1

    def __del__(self):
        self._tshark_pkts.close()

    def __iter__(self):
        return self

    def __next__(self):
        """Generates a list of templates from a pcap file combining scapy and
        tshark dissectors.

        Returns
        -------
        :obj:`Template`
            A `Template` generated from the packets.

        """
        if self._i == len(self._scapy_pkts) - 1:
            # Closing the file
            self._tshark_pkts.close()
            raise StopIteration
        else:
            self._i += 1
            return self.tgenerate(self._scapy_pkts[self._i],
                                  self._tshark_pkts[self._i],
                                  self._name(self._scapy_pkts[self._i]))

    def tgenerate(self, scapy_pkt, tshark_pkt, name):
        """Generates a template from a scapy and tshark packet.

        Parameters
        ----------
        scapy_pkt : :obj:``
            The packet generated by Scapy.
        tshark_pkt : :obj:``
            The packet generated by Pyshark.
        name : str
            The name of the `Template`.

        Returns
        -------
        :obj: `Template`
            The `Tempalate` generated from the packets.

        """
        raw = bytes(scapy_pkt).hex()
        pkt_len = len(scapy_pkt)
        template = Template(name, raw=raw)
        # Adding the layers that scapy is able to dissect to the template
        for l in self._getlayers(scapy_pkt):
            offset = pkt_len - len(l)
            lslice = str(slice(offset, pkt_len)).encode().hex()
            layer = TLayer(name=l.__class__.__name__, lslice=lslice, raw=raw)
            for f in self._scapyfields(l, offset, scapy_pkt, layer):
                layer.addfield(f)
            template.addlayer(layer)
        # Adding layers that scapy is not able to dissect using tshark
        if scapy_pkt.lastlayer().name == "Raw":
            nlayers = len(list(self._getlayers(scapy_pkt)))
            for l in tshark_pkt.layers[nlayers - 1:]:
                # Use it in case you want to delete scapy layers
                # offset = len(scapy_pkt) - len(raw)
                offset = 0
                fields_slices = self._slices(l, offset)
                if fields_slices:
                    lslice = str(slice(fields_slices[0][1].start,
                                       pkt_len)).encode().hex()
                else:
                    lslice = str(
                        slice(pkt_len - len(scapy_pkt['Raw']),
                              pkt_len)).encode().hex()
                layer = TLayer(name="Raw." + str(l.layer_name.upper()),
                               lslice=lslice,
                               raw=raw,
                               custom=True)
                for f in self._tsharkfields(tshark_pkt, l, scapy_pkt,
                                            fields_slices, layer):
                    layer.addfield(f)
                template.addlayer(layer)
        return template

    def _scapyfields(self, layer, offset, spkt, tlayer):
        """Generates template fields for a given scapy layer."""
        fdissect = self._dissect_fields(layer, offset)
        raw = bytes(spkt)
        for f in layer.fields_desc:
            # Obtain the scapy repr of the field
            frepr = layer.getfieldval(f.name)
            # Extract the type of the field
            if type(frepr) is int:
                ftype = (int, 'big')
            else:
                frepr = str(frepr)
                ftype = (str, None)
            # Initialization of the field
            field = TField(name=str(f.name),
                           value=raw[eval(fdissect[f.name])],
                           raw=raw.hex(),
                           tslice=fdissect[f.name].encode().hex(),
                           custom=False,
                           size=eval(fdissect[f.name]).stop -
                           eval(fdissect[f.name]).start,
                           frepr=frepr,
                           ftype=ftype,
                           layer=tlayer)
            yield field

    def _tsharkfields(self, tshark_pkt, layer, scapy_pkt, fields_slices,
                      tlayer):
        """Returns the layers of a pyshark package."""
        raw = bytes(scapy_pkt)
        for sl in fields_slices:
            # Obtain the tshark repr of the field
            field = layer.get_field(sl[0])
            frepr = layer.get_field_value(sl[0])
            # Extract the type of the field
            if field.isdecimal():
                frepr = int(frepr)
                ftype = (int, 'big')
            else:
                frepr = str(frepr)
                ftype = (str, None)
            # Initialization of the tfield
            field = TField(name="_".join(sl[0].split('.')[1:]),
                           value=raw[sl[1]],
                           raw=raw.hex(),
                           tslice=str(sl[1]).encode().hex(),
                           custom=True,
                           size=sl[1].stop - sl[1].start,
                           ftype=ftype,
                           frepr=frepr,
                           layer=tlayer)
            yield field

    @staticmethod
    def _getlayers(pkt):
        """Returns the layers of a scapy package."""
        yield pkt
        while pkt.payload:
            pkt = pkt.payload
            yield pkt

    def _name(self, pkt):
        """Generates a name for each template based on the layers of the
        packet."""
        name = 'Template:'
        for l in self._getlayers(pkt):
            name += '/' + l.__class__.__name__
        return name

    @staticmethod
    def _dissect_fields(layer, offset=0):
        """Create the default layer regarding fields_desc dict."""
        diss_fields = OrderedDict()
        start = 0
        p = b""
        flist = []
        for f in layer.fields_desc:
            val = layer.getfieldval(f.name)
            p = f.addfield(layer, p, val)
            if type(p) is tuple or len(p) == 0:
                flist.append(f.name)
            elif start == len(p):
                diss_fields[f.name] = diss_fields[list(diss_fields)[-1]]
            else:
                flist.append(f.name)
                for f in flist:
                    diss_fields[f] = str(slice(start + offset,
                                               len(p) + offset))
                flist = []
                start = len(p)
        return diss_fields

    @staticmethod
    def _slices(layer, offset):
        """Get the slice of the fields in the packet."""
        slices = []
        for fname in layer.field_names:
            field = layer.get_field(fname)
            if field.size is not None and int(
                    field.size) > 0 and field.name != '':
                slices.append([
                    field.name,
                    slice(
                        int(field.pos) - offset,
                        int(field.pos) + int(field.size) - offset)
                ])
        return slices
Example #23
0
class TGenerator(object):
    """This class is responsible for generating the templates from tshark packets."""

    def __init__(self, pcapfile, userfilter=None):
        """Initialization method of the class.

        Parameters
        ----------
        pcapfile : str
            Path to a previously captured pcap.

        """
        self._tshark_pkts = FileCapture(
            input_file=pcapfile,
            keep_packets=False,
            use_json=True,
            include_raw=True,
            display_filter=userfilter)

    def __iter__(self):
        return self

    def __next__(self):
        """Generates a list of templates from a tshark file

        Returns
        -------
        :obj:`Template`
            A `Template` generated from the packets.

        """
        try:
            tshark_pkt = self._tshark_pkts.next()
            return self.tgenerate(tshark_pkt)
        except UnicodeDecodeError:
            self.__next__()
        except StopIteration:
            self._tshark_pkts.close()
            raise
        except KeyboardInterrupt:
            self._tshark_pkts.close()            
            raise StopIteration

    def tgenerate(self, tshark_pkt):
        """Generates a template from a tshark packet.

        Parameters
        ----------
        tshark_pkt : :obj:``
            The packet generated by Pyshark.

        Returns
        -------
        :obj: `Template`
            The `Tempalate` generated from the packets.

        """
        pkt_raw = tshark_pkt.get_raw_packet()
        pkt_len = len(tshark_pkt)
        # Generation of the `Template`
        template = Template(
            "Building", raw=pkt_raw, description="Template automatically generated by polymorph.")
        # Filtering and adding the `TLayer` objects to the `Template`
        tshark_layers = [
            l for l in tshark_pkt.layers if "_raw" not in l.layer_name.lower()]
        for tshark_layer in tshark_layers:
            # Generation of the `Tlayer`
            try:
                lraw = getattr(
                    tshark_pkt, tshark_layer.layer_name + "_raw").value
            except AttributeError:
                continue
            if type(lraw) is list:
                lraw = lraw[0]
            lraw = bytes.fromhex(lraw)
            tlayer_len = len(lraw)
            try:
                tlayer_start = pkt_raw.index(lraw)
                lslice = slice(tlayer_start, tlayer_start + tlayer_len)
                tlayer = TLayer(name=tshark_layer.layer_name.upper(),
                                lslice=lslice, pkt_raw=pkt_raw)
                # Filtering and adding the `TField` objects to the `TLayer`
                for f in self._get_tlayer_fields(tshark_layer, tlayer, pkt_raw):
                    tlayer.addfield(f)
            # If it corresponds to a reassembled layer
            except ValueError:
                lslice = slice(0, tlayer_len)
                lname = tshark_layer.layer_name.upper() + " (REASSEMBLED)"
                tlayer = TLayer(name=lname,
                                lslice=lslice, pkt_raw=lraw)
                # Filtering and adding the `TField` objects to the `TLayer`
                for f in self._get_tlayer_fields(tshark_layer, tlayer, lraw):
                    tlayer.addfield(f)
            # Adding the `TLayer` to the `Template`
            template.addlayer(tlayer)
        # We changed the name of the template
        template.name = self._name(template.layernames())
        return template

    def _get_tlayer_fields(self, tshark_layer, tlayer, pkt_raw):
        """Generates template fields for a given tshark layer."""
        tshark_fields = self._traverse_fields(tshark_layer._all_fields)
        for tname, tvalue in tshark_fields.items():
            # Building the TField
            tfield = TField(
                fname=tname,
                fslice=slice(tvalue[2], tvalue[2]+tvalue[3]),
                fsize=tvalue[3],
                pkt_raw=pkt_raw,
                trepr=tvalue[0],
                ttype=tvalue[5],
                tmask=tvalue[4],
                layer=tlayer)
            yield tfield

    def _traverse_fields(self, all_fields):
        """Traverse and parse all tshark fields from a tshark layer."""
        parse_fields = OrderedDict()
        # Filter all fields without _raw
        try:
            fields = [f for f in all_fields.keys(
            ) if "_raw" not in f and "_tree" not in f]
        except:
            return parse_fields
        for f in fields:
            # If not present the equivalent field with _raw it is a title
            if f + "_raw" not in all_fields.keys():
                if type(all_fields[f]) is str:
                    continue
                elif type(all_fields[f]) is list:
                    for subf in range(len(all_fields[f])):
                        newfield = self._traverse_fields(all_fields[f][subf])
                        parse_fields = self._update(parse_fields, newfield)
                    continue
                else:
                    newfield = self._traverse_fields(all_fields[f])
                    parse_fields = self._update(parse_fields, newfield)
                    continue
            # Get the _raw equivalent of the field
            if f + "_raw_raw" in all_fields.keys():
                raw_f = all_fields[f + "_raw_raw"]
            else:
                raw_f = all_fields[f + "_raw"]
            # If this condition match, f is a field
            if type(raw_f[-1]) is int and raw_f[-1] != 0:
                # Some fields can have subfields
                if type(all_fields[f]) is dict:
                    newfield = self._traverse_fields(all_fields[f])
                    parse_fields = self._update(parse_fields, newfield)
                    continue
                else:
                    new_f = f.split(".")
                    if len(new_f) == 1:
                        new_f = new_f[0]
                    elif len(new_f) > 1:
                        new_f = ".".join(new_f[1:])
                    parse_fields = self._update(
                        parse_fields, {new_f: [all_fields[f]] + raw_f})
            elif type(raw_f[-1]) is int and raw_f[-1] == 0:
                if type(all_fields[f]) is str:
                    raw_f[-1] = -1
                    newfield = self._traverse_fields({f + "_raw": raw_f,
                                                      f: all_fields[f]})
                    parse_fields = self._update(parse_fields, newfield)
                else:
                    newfield = self._traverse_fields(all_fields[f])
                    parse_fields = self._update(parse_fields, newfield)
            elif type(raw_f[-1]) is list:
                for subf in range(len(raw_f)):
                    newfield = self._traverse_fields({f + "_raw": raw_f[subf],
                                                      f: all_fields[f][subf]})
                    parse_fields = self._update(parse_fields, newfield)
            else:
                print("[ERROR] Parsing field:", f)
        # Return the parsed fields without duplicates
        return parse_fields

    def _update(self, od1, od2):
        """Updates the list of fields without duplicate names."""
        for k, v in od2.items():
            # Delete duplicate fields
            duplicate = False
            for k2, v2 in od1.items():
                if v[2] == v2[2] and v[3] == v2[3] and v[4] == v2[4]:
                    duplicate = True
            if duplicate:
                continue
            new_k = self._new_fname(k, od1)
            od1[new_k] = v
        return od1

    def _new_fname(self, fname, all_fields):
        """Generates new names for fields with duplicate name."""
        if fname in all_fields:
            if fname[-1].isnumeric():
                return self._new_fname(fname[:-1] + str(int(fname[-1]) + 1), all_fields)
            else:
                return self._new_fname(fname + str(2), all_fields)
        else:
            return fname

    def _name(self, layers):
        """Generates a name for each template based on the layers of the
        packet."""
        return "Template: " + " / ".join(layers)
Example #24
0
class PcapReader:
    def __init__(self, filename, summary=True, keep_packets=False):
        self.result = []
        self.cap = FileCapture(filename,
                               only_summaries=summary,
                               keep_packets=keep_packets)
        if filename in packet2num:
            self.length = packet2num[filename]
        else:
            self.length = self.packet_length()

    def packet_length(self):
        length = [0]

        def decode(packet):
            length[0] += 1

        self.cap.apply_on_packets(decode)
        return length[0]

    def get_specify(self, start, end):
        # page split
        def decode(packet):
            item = {
                "id": packet.no,
                "src": packet.source,
                "dst": packet.destination,
                "time": round(float(packet.time), 5),
                "protocol": packet.protocol,
                "info": packet.info,
                "length": packet.length
            }
            self.result.append(item)

        for index in range(start, end):
            pack = self.cap[index - 1]
            decode(pack)
        return self.result, self.length

    def get_detail(self, id):
        packet = self.cap[id - 1]
        old_stdout = sys.stdout
        sys.stdout = mystdout = StringIO()
        packet.pretty_print()
        sys.stdout = old_stdout
        info = mystdout.getvalue()
        detail = []
        index = -1
        # packet.pretty_print()
        for line in info.split('\n'):
            if "Layer" in line:
                index += 1
                detail.append({'layer': line, 'fields': []})
                continue
            if line.strip() in detail[index]['fields']:
                continue
            detail[index]['fields'].append(line.strip())
        return detail

    def close(self):
        self.cap.clear()
        self.cap.close()
Example #25
0
from pyshark import FileCapture

access_points = set()

cap = FileCapture('Radius.pcap',
                  display_filter='radius.User_Name == "sally.berro"')

print('user mac: ' + cap[0]['radius'].get('radius.Calling_Station_Id'))

cap = FileCapture('Radius.pcap', display_filter='radius')
for c in cap:
    access_points.add(c['radius'].get('radius.Called_Station_Id'))
access_points.remove(None)

print(len(access_points), ' access points received requests')
Example #26
0
from pyshark import FileCapture

pcap = FileCapture("incident.pcap", include_raw=True, use_json=True)

data = b''

ct = 0
for packet in pcap:
    try:
        check_type = packet.icmp
        if ct % 2 == 0:
            data += packet.get_raw_packet()[58:74]
            print(packet.get_raw_packet()[58:74])
        ct += 1
    except AttributeError:
        pass

with open("out.png", 'wb') as f:
    f.write(data)
Example #27
0
from pyshark import FileCapture
import re

# ignore stdout
import os
import sys
f = open(os.devnull, 'w')
sys.stderr = f

try:
	""" software running voip proxy """	
	cap = FileCapture('SIP.pcap', display_filter='ip.src == 10.21.128.1 && sip')
	print('proxy software:', cap[0]['sip'].get('sip.Server').split(' ')[0])
	

	""" number of voice mails for user 542 """
	cap = FileCapture('SIP.pcap', display_filter='sip.Method == NOTIFY && sip.r-uri.user == "542"')
	hdr = cap[0]['sip'].get('sip.msg_hdr')
	match = re.search(r'Voice-Message: (\d)/(\d)', hdr)
	print('number of voice mails', int(match.group(1)) + int(match.group(2)))

	cap = FileCapture('SIP.pcap', display_filter='sip.Method == INVITE')
	""" What is the SIP address of the caller in the only call? """
	print('initializer of only call:', cap[0]['sip'].get('sip.from.addr'))
	""" What is the SIP address of the recipient of the only call? """
	print('recipient of only call:', cap[0]['sip'].get('sip.to.addr'))
	""" What is the IP address of the recipient of the only call? """
	cap = FileCapture('SIP.pcap', display_filter='sip.r-uri.user == "635"')
	print('ip of recipient:', cap[0]['ip'].src)
	""" What brand of physical phone was the recipient of the call using? """
	print('type of device:', cap[0]['sip'].get('sip.User-Agent'))