def post_build(self, pkt, pay): """ need to set the length of the whole PDU manually to avoid any bit fiddling use a dummy class to build the layer content also add padding if frame is < 64 bytes Note: padding only handles Ether/n*Dot1Q/EtherCat (no special mumbo jumbo) :param pkt: raw string containing the current layer :param pay: raw string containing the payload :return: <new current layer> + payload """ class _EtherCatLengthCalc(Packet): """ dummy class used to generate str representation easily """ fields_desc = [ LEBitField('length', None, 11), LEBitField('_reserved', 0, 1), LEBitField('type', 0, 4), ] payload_len = len(pay) # length field is 11 bit if payload_len > 2047: raise ValueError('payload size {} exceeds maximum length {} ' 'of EtherCat message.'.format(payload_len, 2047)) self.length = payload_len vlan_headers_total_size = 0 upper_layer = self.underlayer # add size occupied by VLAN tags while upper_layer and isinstance(upper_layer, Dot1Q): vlan_headers_total_size += 4 upper_layer = upper_layer.underlayer if not isinstance(upper_layer, Ether): raise Exception('missing Ether layer') pad_len = EtherCat.ETHER_FRAME_MIN_LEN - (EtherCat.ETHER_HEADER_LEN + vlan_headers_total_size + EtherCat.ETHERCAT_HEADER_LEN + # noqa: E501 payload_len + EtherCat.ETHER_FSC_LEN) if pad_len > 0: pad = Padding() pad.load = b'\x00' * pad_len return raw(_EtherCatLengthCalc(length=self.length, type=self.type)) + pay + raw(pad) return raw(_EtherCatLengthCalc(length=self.length, type=self.type)) + pay
def pad_udp(packet): if UDP in packet: # get layers after udp layer_after = packet[UDP].payload.copy() # build a padding layer pad = Padding() pad.load = '\x00' * 12 layer_before = packet.copy() layer_before[UDP].remove_payload() packet = layer_before / pad / layer_after return packet return packet
def pre_dissect(self, s): offset = 0 while offset < len(s) and s[offset] not in [0x55, 0xfe, 0xfd]: offset += 1 if offset > 0 and self.underlayer is not None: self.underlayer.add_payload(Padding(s[:offset])) return s[offset:]
def recv(self, x=CAN_FRAME_SIZE): try: pkt, sa_ll = self.ins.recvfrom(x) except BlockingIOError: # noqa: F821 warning("Captured no data, socket in non-blocking mode.") return None except socket.timeout: warning("Captured no data, socket read timed out.") return None except OSError: # something bad happened (e.g. the interface went down) warning("Captured no data.") return None # need to change the byte order of the first four bytes, # required by the underlying Linux SocketCAN frame format if not conf.contribs['CAN']['swap-bytes']: pkt = struct.pack("<I12s", *struct.unpack(">I12s", pkt)) len = pkt[4] canpkt = self.basecls(pkt[:len + 8]) canpkt.time = get_last_packet_timestamp(self.ins) if self.remove_padding: return canpkt else: return canpkt / Padding(pkt[len + 8:])
def deBuilder(self, packet, stream, genFCS): """Return the decrypted packet""" ## Remove the FCS from the old packet body postPkt = RadioTap(self.pt.byteRip(packet.copy(), chop = True, order = 'last', output = 'str', qty = 4)) ## Remove RadioTap() info if required if genFCS is False: postPkt = RadioTap()/postPkt[RadioTap].payload ## Rip off the Dot11WEP layer del postPkt[Dot11WEP] ## Add the stream to LLC decodedPkt = postPkt/LLC(str(stream)) ## Flip FCField bits accordingly if decodedPkt[Dot11].FCfield == 65: decodedPkt[Dot11].FCfield = 1 elif decodedPkt[Dot11].FCfield == 66: decodedPkt[Dot11].FCfield = 2 ## Return the decoded packet with or without FCS if genFCS is False: return decodedPkt else: return decodedPkt/Padding(load = binascii.unhexlify(self.pt.endSwap(hex(crc32(str(decodedPkt[Dot11])) & 0xffffffff)).replace('0x', '')))
def dissect(self, s): s = self.pre_dissect(s) s = self.do_dissect(s) s = self.post_dissect(s) payl, pad = self.extract_padding(s) self.do_dissect_payload(payl) if pad and conf.padding: if pad[0] in [0x55, 0xfe, 0xfd]: if self.underlayer is not None: self.underlayer.add_payload(MAVLink(pad)) else: self.add_payload(MAVLink(pad)) else: if self.underlayer is not None: self.underlayer.add_payload(Padding(pad)) else: self.add_payload(Padding(pad))
def dissect(self, s): s = self.pre_dissect(s) s = self.do_dissect(s) s = self.post_dissect(s) payl, pad = self.extract_padding(s) self.do_dissect_payload(payl) if pad and conf.padding: self.add_payload(Padding(pad))
def m2i(self, pkt, m): """ The client_kx_msg may be either None, EncryptedPreMasterSecret (for RSA encryption key exchange), ClientDiffieHellmanPublic, or ClientECDiffieHellmanPublic. When either one of them gets dissected, the session context is updated accordingly. """ l = self.length_from(pkt) tbd, rem = m[:l], m[l:] s = pkt.tls_session cls = None if s.prcs and s.prcs.key_exchange: cls = s.prcs.key_exchange.client_kx_msg_cls if cls is None: return Raw(tbd) / Padding(rem) return cls(tbd, tls_session=s) / Padding(rem)
def dissect(self, s): s = self.pre_dissect(s) s = self.do_dissect(s) s = self.post_dissect(s) payl, pad = self.extract_padding(s) self.do_dissect_payload(payl) if pad and conf.padding: if pad[0] in [0x68]: #TODO: [Luis] "self.underlayer is not None" self.add_payload(APDU(pad, _internal=1, _underlayer=self)) else: self.add_payload(Padding(pad))
def m2i(self, pkt, m): s = pkt.tls_session tmp_len = self.length_from(pkt) if s.prcs: cls = s.prcs.key_exchange.server_kx_msg_cls(m) if cls is None: return Raw(m[:tmp_len]) / Padding(m[tmp_len:]) return cls(m, tls_session=s) else: try: p = ServerDHParams(m, tls_session=s) if pkcs_os2ip(p.load[:2]) not in _tls_hash_sig: raise Exception return p except Exception: cls = _tls_server_ecdh_cls_guess(m) p = cls(m, tls_session=s) if pkcs_os2ip(p.load[:2]) not in _tls_hash_sig: return Raw(m[:tmp_len]) / Padding(m[tmp_len:]) return p
def send(self, x): try: return SuperSocket.send(self, x) except socket.error as msg: if msg.errno == 22 and len(x) < conf.min_pkt_size: padding = b"\x00" * (conf.min_pkt_size - len(x)) if isinstance(x, Packet): return SuperSocket.send(self, x / Padding(load=padding)) else: return SuperSocket.send(self, raw(x) + padding) raise
def dissect(self, s): s = self.pre_dissect(s) s = self.do_dissect(s) # pylint: disable=assignment-from-no-return s = self.post_dissect(s) payl, pad = self.extract_padding(s) self.do_dissect_payload(payl) if pad and conf.padding: if pad[0] in [0x68]: # pylint: disable=unsubscriptable-object self.add_payload(APDU(pad, _internal=1, _underlayer=self)) else: self.add_payload(Padding(pad))
def pad_udp(packet): if UDP in packet: # get layers after udp layer_after = packet[UDP].payload.copy() print("packet: ", packet) print("udp: ", packet[UDP]) print("payload: ", packet[UDP].payload) # build a padding layer pad = Padding() pad.load = '\x00' * 12 print("pad:", pad.load) layer_before = packet.copy() layer_before[UDP].remove_payload() print("remove udp payload:", layer_before) packet = layer_before / pad / layer_after return packet return packet
def protocol_frame(protocol, source='unicast', vlans=[]): """ Create a frame that has the minimum fields to be recognized as a determined protocol. It's not intended to be a valid PDU, only to be seen as one by the switch filter. @param protocol Protocol name. Valid options are: * stp, lldp, lacp, marker, oam, lbd, cdp, pagp, udld, vtp, pvst, dtp, gvrp, gmrp, dot1x @param source Name of the source interface, or source MAC address. * 'unicast' to use a random unicast address as source MAC. @param vlans [optional] List of VLAN Tags. List can be composed by single integer representing VLAN, or tuple (int, int) for VLAN and prio. Ex: [(100, 3), 20] will add two tags, one with VLAN 100, prio 3 and another with VLAN 20, prio 0. """ if protocol not in pdu_info: raise Exception("Unknown protocol name {0}".format(protocol)) info = pdu_info[protocol] # Define source MAC address. if "eth" in source: src_mac = str(mac_address(source)) elif source == 'unicast': src_mac = str(random_mac('unicast')) else: src_mac = str(source) if protocol == 'eaps': src_mac = "00:e0:2b:00:00:01" if 'type' in info or vlans: pdu = Ether(src=src_mac, dst=info['mac']) for v in vlans: if type(v) == int: pdu = pdu / Dot1Q(vlan=v) elif type(v) == tuple: pdu = pdu / Dot1Q(vlan=v[0], prio=v[1]) else: raise TypeError( "Expected list with int or tuple for VLANs parameter.") if 'type' in info: pdu.lastlayer().type = info['type'] else: pdu = Dot3(src=src_mac, dst=info['mac']) pdu = pdu / info['load'] # Process PDU so length field is correctly calculated. pdu = Ether(str(pdu)) # Add Padding and return. padding = 64 - len(pdu) + 4 #FCS if padding > 0: pdu = pdu / Padding(load='\0' * padding) return pdu
def pre_dissect(self, s): if self.underlayer is not None and has_flag_set(self.underlayer, HTTP2Flags.PADDED): padding_length = ord(s[0]) self.add_payload(Padding(load=s[-padding_length:])) s = s[:-padding_length] return s
def m2i(self, pkt, m): l = self.length_from(pkt) tbd, rem = m[:l], m[l:] return self.cls(tbd)/Padding(rem)
def m2i(self, pkt, m): tmp_len = self.length_from(pkt) tbd, rem = m[:tmp_len], m[tmp_len:] return self.cls(tbd) / Padding(rem)