def m2i(self, pkt, s): family = None if pkt.type == 1: # A family = socket.AF_INET elif pkt.type in [2, 5, 12]: # NS, CNAME, PTR if hasattr(pkt, "_orig_s") and pkt._orig_s: if orb(s[0]) & 0xc0: s = dns_get_str(s, 0, pkt)[0] else: s = dns_get_str(pkt._orig_s, pkt._orig_p, _internal=True)[0] # noqa: E501 else: s = dns_get_str(s, 0)[0] elif pkt.type == 16: # TXT ret_s = list() tmp_s = s # RDATA contains a list of strings, each are prepended with # a byte containing the size of the following string. while tmp_s: tmp_len = orb(tmp_s[0]) + 1 if tmp_len > len(tmp_s): warning("DNS RR TXT prematured end of character-string (size=%i, remaining bytes=%i)" % (tmp_len, len(tmp_s))) # noqa: E501 ret_s.append(tmp_s[1:tmp_len]) tmp_s = tmp_s[tmp_len:] s = ret_s elif pkt.type == 28: # AAAA family = socket.AF_INET6 if family is not None: s = inet_ntop(family, s) return s
def dispatch_hook(cls, _pkt=None, *args, **kargs): if _pkt and len(_pkt) >= 2: version = orb(_pkt[0]) if version == 0x04: # OpenFlow 1.3 from scapy.contrib.openflow3 import OpenFlow3 return OpenFlow3.dispatch_hook(_pkt, *args, **kargs) elif version == 0x01: # OpenFlow 1.0 # port 6653 has been allocated by IANA, port 6633 should no # longer be used # OpenFlow function may be called with a None # self in OFPPacketField of_type = orb(_pkt[1]) if of_type == 1: err_type = orb(_pkt[9]) # err_type is a short int, but last byte is enough if err_type == 255: err_type = 65535 return ofp_error_cls[err_type] elif of_type == 16: mp_type = orb(_pkt[9]) if mp_type == 255: mp_type = 65535 return ofp_stats_request_cls[mp_type] elif of_type == 17: mp_type = orb(_pkt[9]) if mp_type == 255: mp_type = 65535 return ofp_stats_reply_cls[mp_type] else: return ofpt_cls[of_type] else: warning("Unknown OpenFlow packet") return _UnknownOpenFlow
def in6_getAddrType(addr): naddr = inet_pton(socket.AF_INET6, addr) paddr = inet_ntop(socket.AF_INET6, naddr) # normalize addrType = 0 # _Assignable_ Global Unicast Address space # is defined in RFC 3513 as those in 2000::/3 if ((orb(naddr[0]) & 0xE0) == 0x20): addrType = (IPV6_ADDR_UNICAST | IPV6_ADDR_GLOBAL) if naddr[:2] == b' \x02': # Mark 6to4 @ addrType |= IPV6_ADDR_6TO4 elif orb(naddr[0]) == 0xff: # multicast addrScope = paddr[3] if addrScope == '2': addrType = (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_MULTICAST) elif addrScope == 'e': addrType = (IPV6_ADDR_GLOBAL | IPV6_ADDR_MULTICAST) else: addrType = (IPV6_ADDR_GLOBAL | IPV6_ADDR_MULTICAST) elif ((orb(naddr[0]) == 0xfe) and ((int(paddr[2], 16) & 0xC) == 0x8)): addrType = (IPV6_ADDR_UNICAST | IPV6_ADDR_LINKLOCAL) elif paddr == "::1": addrType = IPV6_ADDR_LOOPBACK elif paddr == "::": addrType = IPV6_ADDR_UNSPECIFIED else: # Everything else is global unicast (RFC 3513) # Even old deprecated (RFC3879) Site-Local addresses addrType = (IPV6_ADDR_GLOBAL | IPV6_ADDR_UNICAST) return addrType
def pre_dissect(self, s): # Get the frame check sequence sty = orb(s[0]) ty = orb(s[1]) >> 2 fc = struct.unpack("!H", s[2:4])[0] length = 12 + 6 * ((ty != 1 or sty in [0x8, 0x9, 0xa, 0xb, 0xe, 0xf]) + (ty in [0, 2]) + (ty == 2 and fc & 3 == 3)) # noqa: E501 return s[:length] + s[-4:] + s[length:-4]
def dispatch_hook(cls, _pkt=None, *args, **kargs): """ If the TLS class was called on raw SSLv2 data, we want to return an SSLv2 record instance. We acknowledge the risk of SSLv2 packets with a msglen of 0x1403, 0x1503, 0x1603 or 0x1703 which will never be casted as SSLv2 records but TLS ones instead, but hey, we can't be held responsible for low-minded extensibility choices. """ if _pkt and len(_pkt) >= 2: byte0 = orb(_pkt[0]) byte1 = orb(_pkt[1]) if (byte0 not in _tls_type) or (byte1 != 3): from scapy.layers.tls.record_sslv2 import SSLv2 return SSLv2 else: s = kargs.get("tls_session", None) if s and _tls_version_check(s.tls_version, 0x0304): if s.rcs and not isinstance(s.rcs.cipher, Cipher_NULL): from scapy.layers.tls.record_tls13 import TLS13 return TLS13 if _pkt and len(_pkt) < 5: # Layer detected as TLS but too small to be a real packet (len<5). # noqa: E501 # Those packets appear when sessions are interrupted or to flush buffers. # noqa: E501 # Scapy should not try to decode them return conf.raw_layer return TLS
def obfuscate(pay, secret, session_id, version, seq): ''' Obfuscation methodology from section 3.7 https://tools.ietf.org/html/draft-ietf-opsawg-tacacs-06#section-3.7 ''' pad = b"" curr_pad = b"" # pad length must equal the payload to obfuscate. # pad = {MD5_1 [,MD5_2 [ ... ,MD5_n]]} while len(pad) < len(pay): msg = hashlib.md5() msg.update(struct.pack('!I', session_id)) msg.update(secret.encode()) msg.update(struct.pack('!BB', version, seq)) msg.update(curr_pad) curr_pad = msg.digest() pad += curr_pad # Obf/Unobfuscation via XOR operation between plaintext and pad return b"".join(chb(orb(pad[i]) ^ orb(pay[i])) for i in range(len(pay)))
def _tzsp_guess_next_tag(payload): """ :return: class representing the next tag, Raw on error, None on missing payload # noqa: E501 """ if not payload: warning('missing payload') return None tag_type = orb(payload[0]) try: tag_class_definition = _TZSP_TAG_CLASSES[tag_type] except KeyError: return _tzsp_handle_unknown_tag(payload, tag_type) if type(tag_class_definition) is not dict: return tag_class_definition try: length = orb(payload[1]) except IndexError: length = None if not length: warning('no tag length given - packet to short') return Raw try: return tag_class_definition[length] except KeyError: warning('invalid tag length {} for tag type {}'.format(length, tag_type)) # noqa: E501 return Raw
def dispatch_hook(cls, _pkt=None, *args, **kargs): if _pkt and len(_pkt) >= 4: if orb(_pkt[0]) in [0x12, 0x16, 0x17]: return IGMP elif orb(_pkt[0]) == 0x11 and len(_pkt) < 12: return IGMP return IGMPv3
def dispatch_hook(cls, _pkt=None, *args, **kargs): if _pkt: c = orb(_pkt[0]) if c in [1, 2] and len(_pkt) >= 5: t = orb(_pkt[4]) return cls.registered_methods.get(t, cls) return cls
def OpenFlow(self, payload): if self is None or self.dport == 6653 or self.dport == 6633 or self.sport == 6653 or self.sport == 6633: # noqa: E501 # port 6653 has been allocated by IANA, port 6633 should no longer be used # noqa: E501 # OpenFlow function may be called with None self in OFPPacketField of_type = orb(payload[1]) if of_type == 1: err_type = orb(payload[9]) # err_type is a short int, but last byte is enough if err_type == 255: err_type = 65535 return ofp_error_cls[err_type] elif of_type == 16: mp_type = orb(payload[9]) if mp_type == 255: mp_type = 65535 return ofp_stats_request_cls[mp_type] elif of_type == 17: mp_type = orb(payload[9]) if mp_type == 255: mp_type = 65535 return ofp_stats_reply_cls[mp_type] else: return ofpt_cls[of_type] else: return TCP_guess_payload_class_copy(self, payload)
def dispatch_hook(cls, _pkt=None, *args, **kargs): if _pkt and len(_pkt) >= 4: from scapy.contrib.igmpv3 import IGMPv3 if orb(_pkt[0]) in [0x22, 0x30, 0x31, 0x32]: return IGMPv3 if orb(_pkt[0]) == 0x11 and len(_pkt) >= 12: return IGMPv3 return IGMP
def dns_get_str(s, p, pkt=None, _internal=False): """This function decompresses a string s, from the character p. params: - s: the string to decompress - p: start index of the string - pkt: (optional) an InheritOriginDNSStrPacket packet returns: (decoded_string, end_index, left_string) """ # The _internal parameter is reserved for scapy. It indicates # that the string provided is the full dns packet, and thus # will be the same than pkt._orig_str. The "Cannot decompress" # error will not be prompted if True. max_length = len(s) name = b"" # The result = the extracted name burned = 0 # The "burned" data, used to determine the remaining bytes q = None # Will contain the index after the pointer, to be returned processed_pointers = [p] # Used to check for decompression loops while True: if abs(p) >= max_length: warning("DNS RR prematured end (ofs=%i, len=%i)" % (p, len(s))) break cur = orb(s[p]) # current value of the string at p p += 1 # p is now pointing to the value of the pointer burned += 1 if cur & 0xc0: # Label pointer if q is None: # p will follow the pointer, whereas q will not q = p + 1 if p >= max_length: warning("DNS incomplete jump token at (ofs=%i)" % p) break p = ((cur & ~0xc0) << 8) + orb(s[p]) - 12 # Follow the pointer burned += 1 if pkt and hasattr(pkt, "_orig_s") and pkt._orig_s: # There should not be a loop as pkt is None name += dns_get_str(pkt._orig_s, p, None, _internal=True)[0] if burned == max_length: break elif p in processed_pointers: warning("DNS decompression loop detected") break elif not _internal: raise Scapy_Exception("DNS message can't be compressed" + "at this point!") processed_pointers.append(p) continue elif cur > 0: # Label name += s[p:p + cur] + b"." p += cur burned += cur else: break if q is not None: # Return the real end index (not the one we followed) p = q # name, end_index, remaining return name, p, s[burned:]
def dispatch_hook(cls, _pkt=None, *args, **kargs): if _pkt and len(_pkt) >= 1: if (orb(_pkt[0]) >> 5) & 0x7 == 2: from . import gtp_v2 return gtp_v2.GTPHeader if _pkt and len(_pkt) >= 8: _gtp_type = orb(_pkt[1:2]) return GTPforcedTypes.get(_gtp_type, GTPHeader) return cls
def do_dec(cls, s, context=None, safe=False): l, s, t = cls.check_type_check_len(s) x = 0 if s: if orb(s[0]) & 0x80: # negative int x = -1 for c in s: x <<= 8 x |= orb(c) return cls.asn1_object(x), t
def decrypt(self, sa, esp, key, icv_size=None): """ Decrypt an ESP packet @param sa: the SecurityAssociation associated with the ESP packet. @param esp: an encrypted ESP packet @param key: the secret key used for encryption @param icv_size: the length of the icv used for integrity check @return: a valid ESP packet encrypted with this algorithm @raise IPSecIntegrityError: if the integrity check fails with an AEAD algorithm """ if icv_size is None: icv_size = self.icv_size if self.is_aead else 0 iv = esp.data[:self.iv_size] data = esp.data[self.iv_size:len(esp.data) - icv_size] icv = esp.data[len(esp.data) - icv_size:] if self.cipher: mode_iv = self._format_mode_iv(sa=sa, iv=iv) cipher = self.new_cipher(key, mode_iv, icv) decryptor = cipher.decryptor() if self.is_aead: # Tag value check is done during the finalize method decryptor.authenticate_additional_data( struct.pack('!LL', esp.spi, esp.seq) ) try: data = decryptor.update(data) + decryptor.finalize() except InvalidTag as err: raise IPSecIntegrityError(err) # extract padlen and nh padlen = orb(data[-2]) nh = orb(data[-1]) # then use padlen to determine data and padding data = data[:len(data) - padlen - 2] padding = data[len(data) - padlen - 2: len(data) - 2] return _ESPPlain(spi=esp.spi, seq=esp.seq, iv=iv, data=data, padding=padding, padlen=padlen, nh=nh, icv=icv)
def i2m(self, pkt, x): if any((orb(y) >= 0xc0) for y in x): # The value has already been processed. Do not process it again return x if not x or x == b".": return b"\x00" # Truncate chunks that cannot be encoded (more than 63 bytes..) x = b"".join(chb(len(y)) + y for y in (k[:63] for k in x.split(b"."))) if orb(x[-1]) != 0 and (orb(x[-2]) < 0xc0): x += b"\x00" return x
def BER_len_dec(s): tmp_len = orb(s[0]) if not tmp_len & 0x80: return tmp_len, s[1:] tmp_len &= 0x7f if len(s) <= tmp_len: raise BER_Decoding_Error( "BER_len_dec: Got %i bytes while expecting %i" % (len(s) - 1, tmp_len), remaining=s ) ll = 0 for c in s[1:tmp_len + 1]: ll <<= 8 ll |= orb(c) return ll, s[tmp_len + 1:]
def guess_payload_class(self, payload): # type is a 7-bit bitfield spanning bits 1..7 -> div 2 try: lldpdu_tlv_type = orb(payload[0]) // 2 return LLDPDU_CLASS_TYPES.get(lldpdu_tlv_type, conf.raw_layer) except IndexError: return conf.raw_layer
def parse_data_pkt(pkt, tk): """Extract data from a WPA packet @pkt with temporal key @tk""" TSC, TA, data = parse_TKIP_hdr(pkt) TK = [orb(x) for x in tk] rc4_key = gen_TKIP_RC4_key(TSC, TA, TK) return ARC4_decrypt(rc4_key, data)
def in6_getRandomizedIfaceId(ifaceid, previous=None): """ Implements the interface ID generation algorithm described in RFC 3041. The function takes the Modified EUI-64 interface identifier generated as described in RFC 4291 and an optional previous history value (the first element of the output of this function). If no previous interface identifier is provided, a random one is generated. The function returns a tuple containing the randomized interface identifier and the history value (for possible future use). Input and output values are provided in a "printable" format as depicted below. ex: >>> in6_getRandomizedIfaceId('20b:93ff:feeb:2d3') ('4c61:76ff:f46a:a5f3', 'd006:d540:db11:b092') >>> in6_getRandomizedIfaceId('20b:93ff:feeb:2d3', previous='d006:d540:db11:b092') ('fe97:46fe:9871:bd38', 'eeed:d79c:2e3f:62e') """ s = b"" if previous is None: d = b"".join(chb(x) for x in range(256)) for _ in range(8): s += chb(random.choice(d)) previous = s s = inet_pton(socket.AF_INET6, "::" + ifaceid)[8:] + previous import hashlib s = hashlib.md5(s).digest() s1, s2 = s[:8], s[8:] s1 = chb(orb(s1[0]) | 0x04) + s1[1:] s1 = inet_ntop(socket.AF_INET6, b"\xff" * 8 + s1)[20:] s2 = inet_ntop(socket.AF_INET6, b"\xff" * 8 + s2)[20:] return (s1, s2)
def _tls_del_pad(p): """ Provided with a just decrypted TLSCiphertext (now a TLSPlaintext instance) p, the function removes the trailing padding found in p.data. It also performs some sanity checks on the padding (length, content, ...). False is returned if one of the check fails. Otherwise, True is returned, indicating that p.data and p.len have been updated. """ if p.len < 1: warning("Message format is invalid (padding)") return False padlen = orb(p.data[-1]) padsize = padlen + 1 if p.len < padsize: warning("Invalid padding length") return False if p.data[-padsize:] != chb(padlen) * padsize: warning("Padding content is invalid %s", repr(p.data[-padsize:])) return False p.data = p.data[:-padsize] p.len -= padsize return True
def guess_payload_class(self, payload): pl_type = orb(payload[_SDEntry.TYPE_PAYLOAD_I]) if (pl_type in _SDEntry.TYPE_SRV): return (SDEntry_Service) elif (pl_type in _SDEntry.TYPE_EVTGRP): return (SDEntry_EventGroup)
def getmacbyip(ip, chainCC=0): """Return MAC address corresponding to a given IP address""" if isinstance(ip, Net): ip = next(iter(ip)) ip = inet_ntoa(inet_aton(ip)) tmp = [orb(e) for e in inet_aton(ip)] if (tmp[0] & 0xf0) == 0xe0: # mcast @ return "01:00:5e:%.2x:%.2x:%.2x" % (tmp[1] & 0x7f, tmp[2], tmp[3]) iff, _, gw = conf.route.route(ip) if ((iff == consts.LOOPBACK_INTERFACE) or (ip == conf.route.get_if_bcast(iff))): # noqa: E501 return "ff:ff:ff:ff:ff:ff" if gw != "0.0.0.0": ip = gw mac = conf.netcache.arp_cache.get(ip) if mac: return mac res = srp1(Ether(dst=ETHER_BROADCAST) / ARP(op="who-has", pdst=ip), type=ETH_P_ARP, iface=iff, timeout=2, verbose=0, chainCC=chainCC, nofilter=1) if res is not None: mac = res.payload.hwsrc conf.netcache.arp_cache[ip] = mac return mac return None
def compute_crc(pdu, init=0x555555): def swapbits(a): v = 0 if a & 0x80 != 0: v |= 0x01 if a & 0x40 != 0: v |= 0x02 if a & 0x20 != 0: v |= 0x04 if a & 0x10 != 0: v |= 0x08 if a & 0x08 != 0: v |= 0x10 if a & 0x04 != 0: v |= 0x20 if a & 0x02 != 0: v |= 0x40 if a & 0x01 != 0: v |= 0x80 return v state = swapbits(init & 0xff) + (swapbits((init >> 8) & 0xff) << 8) + (swapbits((init >> 16) & 0xff) << 16) # noqa: E501 lfsr_mask = 0x5a6000 for i in (orb(x) for x in pdu): for j in range(8): next_bit = (state ^ i) & 1 i >>= 1 state >>= 1 if next_bit: state |= 1 << 23 state ^= lfsr_mask return struct.pack("<L", state)[:-1]
def post_build(self, p, pay): p += pay optionlen = self.optionlen if optionlen is None: optionlen = (len(self.options) + 3) // 4 p = chb(optionlen & 0x2f | orb(p[0]) & 0xc0) + p[1:] return p
def dispatch_hook(cls, _pkt=None, *args, **kargs): if len(_pkt) >= 2: if (orb(_pkt[2]) & 0x80): # Response return LLMNRResponse else: # Query return LLMNRQuery return cls
def _extract_dot15d4address(pkt, source=True): """This function extracts the source/destination address of a 6LoWPAN from its upper Dot15d4Data (802.15.4 data) layer. params: - source: if True, the address is the source one. Otherwise, it is the destination. returns: the packed & processed address """ underlayer = pkt.underlayer while underlayer is not None and not isinstance(underlayer, Dot15d4Data): # noqa: E501 underlayer = underlayer.underlayer if type(underlayer) == Dot15d4Data: addr = underlayer.src_addr if source else underlayer.dest_addr if underlayer.underlayer.fcf_destaddrmode == 3: tmp_ip = LINK_LOCAL_PREFIX[0:8] + struct.pack(">Q", addr) # noqa: E501 # Turn off the bit 7. tmp_ip = tmp_ip[0:8] + struct.pack("B", (orb(tmp_ip[8]) ^ 0x2)) + tmp_ip[9:16] # noqa: E501 elif underlayer.underlayer.fcf_destaddrmode == 2: tmp_ip = LINK_LOCAL_PREFIX[0:8] + \ b"\x00\x00\x00\xff\xfe\x00" + \ struct.pack(">Q", addr)[6:] return tmp_ip else: # Most of the times, it's necessary the IEEE 802.15.4 data to extract this address # noqa: E501 raise Exception('Unimplemented: IP Header is contained into IEEE 802.15.4 frame, in this case it\'s not available.') # noqa: E501
def isis_str2area(s): if len(s) == 0: return "" numbytes = len(s[1:]) fmt = "%02X" + (".%02X%02X" * (numbytes // 2)) + ("" if (numbytes % 2) == 0 else ".%02X") # noqa: E501 return fmt % tuple(orb(x) for x in s)
def __init__(self, name, default, default_readable=True, context=None, implicit_tag=None, explicit_tag=None): if default is not None and default_readable: default = b"".join(binrepr(orb(x)).zfill(8).encode("utf8") for x in default) # noqa: E501 ASN1F_field.__init__(self, name, default, context=context, implicit_tag=implicit_tag, explicit_tag=explicit_tag)
def m2i(self, pkt, m): """ Try to parse one of the TLS subprotocols (ccs, alert, handshake or application_data). This is used inside a loop managed by .getfield(). """ cls = Raw if pkt.type == 22: if len(m) >= 1: msgtype = orb(m[0]) cls = _tls_handshake_cls.get(msgtype, Raw) elif pkt.type == 20: cls = TLSChangeCipherSpec elif pkt.type == 21: cls = TLSAlert elif pkt.type == 23: cls = TLSApplicationData if cls is Raw: return Raw(m) else: try: return cls(m, tls_session=pkt.tls_session) except Exception: if conf.debug_dissector: raise return Raw(m)
def m2i(self, pkt, x): list = [] v = struct.unpack("!H", x[4:6])[0] list.append(v) flags = orb(x[6]) v = (flags & 0x80) >> 7 list.append(v) v = (flags & 0x40) >> 7 list.append(v) return list
def getfield(self, pkt, s): value = 0 for offset, curbyte in enumerate(s): curbyte = orb(curbyte) value += (curbyte & 127) * (128**offset) if curbyte & 128 == 0: return s[offset + 1:], value if offset > 2: raise Scapy_Exception("%s: malformed length field" % self.__class__.__name__)
def guess_payload_class(self, payload): if len(payload) >= 1: if not self.s: return MPLS ip_version = (orb(payload[0]) >> 4) & 0xF if ip_version == 4: return IP elif ip_version == 6: return IPv6 return Padding
def m2i(self, pkt, m): cls = Raw if len(m) >= 1: msgtype = orb(m[0]) cls = _sslv2_handshake_cls.get(msgtype, Raw) if cls is Raw: return Raw(m) else: return cls(m, tls_session=pkt.tls_session)
def guess_payload_class(self, payload): if self.NextExtHdr == 0: sub_proto = orb(payload[0]) if sub_proto >= 0x45 and sub_proto <= 0x4e: return IP elif (sub_proto & 0xf0) == 0x60: return IPv6 else: return PPP return GTPHeader.guess_payload_class(self, payload)
def dispatch_hook(cls, _pkt=None, *_, **kargs): if _pkt: cmd = orb(_pkt[0]) elif "type" in kargs: cmd = kargs["type"] if isinstance(cmd, six.string_types): cmd = cls.fields_desc[0].s2i[cmd] else: return cls return SPECIFIC_CLASSES.get(cmd, cls)
def read_packet(self, size=MTU): # type: (int) -> Optional[BasePacket] """return a single packet read from the file or None if filters apply raise EOFError when no more packets are available """ line = self.f.readline() line = line.lstrip() if len(line) < 16: raise EOFError is_log_file_format = orb(line[0]) == orb(b"(") if is_log_file_format: t, intf, f = line.split() idn, data = f.split(b'#') le = None t = float(t[1:-1]) else: h, data = line.split(b']') intf, idn, le = h.split() t = None if self.ifilter is not None and \ intf.decode('ASCII') not in self.ifilter: return None data = data.replace(b' ', b'') data = data.strip() pkt = CAN(identifier=int(idn, 16), data=binascii.unhexlify(data)) if le is not None: pkt.length = int(le[1:]) else: pkt.length = len(pkt.data) if len(idn) > 3: pkt.flags = 0b100 if t is not None: pkt.time = t return pkt
def dispatch_hook(cls, _pkt=None, *args, **kargs): if _pkt: first_byte = orb(_pkt[0]) if first_byte == 0xff: return HDLC # See RFC 1661 section 2 # <https://tools.ietf.org/html/rfc1661#section-2> if first_byte & 0x01: return PPP_ return cls
def _LSAGuessPayloadClass(p, **kargs): """ Guess the correct LSA class for a given payload """ # This is heavily based on scapy-cdp.py by Nicolas Bareil and Arnaud Ebalard cls = conf.raw_layer if len(p) >= 4: typ = orb(p[3]) clsname = _OSPF_LSclasses.get(typ, "Raw") cls = globals()[clsname] return cls(p, **kargs)
def supported_responses(self): # type: () -> List[EcuResponse] supported_resps = list() all_responses = [p for p in self.__result_packets.values() if orb(bytes(p)[0]) & 0x40] for resp in all_responses: states = list(set([t.state for t in self.results_with_response if t.resp == resp])) supported_resps.append(EcuResponse(state=states, responses=resp)) return supported_resps
def getfield(self, pkt, s): if pkt.tls_session.consider_read_padding(): # This should work with SSLv3 and also TLS versions. # Note that we need to retrieve pkt.padlen beforehand, # because it's possible that the padding is followed by some data # from another TLS record (hence the last byte from s would not be # the last byte from the current record padding). tmp_len = orb(s[pkt.padlen - 1]) return s[tmp_len:], self.m2i(pkt, s[:tmp_len]) return s, None
def decompressSourceAddr(self, packet): try: tmp_ip = inet_pton(socket.AF_INET6, self.sourceAddr) except socket.error: tmp_ip = b"\x00" * 16 if self.sac == 0: if self.sam == 0x0: pass elif self.sam == 0x1: tmp_ip = LINK_LOCAL_PREFIX[0:8] + tmp_ip[ 16 - source_addr_mode2(self):16] elif self.sam == 0x2: tmp_ip = LINK_LOCAL_PREFIX[0:8] + b"\x00\x00\x00\xff\xfe\x00" + \ tmp_ip[16 - source_addr_mode2(self):16] elif self.sam == 0x3: # EXTRACT ADDRESS FROM Dot15d4 underlayer = self.underlayer if underlayer is not None: while underlayer is not None and not isinstance( underlayer, Dot15d4Data): underlayer = underlayer.underlayer assert type(underlayer) == Dot15d4Data if underlayer.underlayer.fcf_srcaddrmode == 3: tmp_ip = LINK_LOCAL_PREFIX[0:8] + struct.pack( ">Q", underlayer.src_addr) # Turn off the bit 7. tmp_ip = tmp_ip[0:8] + struct.pack( "B", (orb(tmp_ip[8]) ^ 0x2)) + tmp_ip[9:16] elif underlayer.underlayer.fcf_srcaddrmode == 2: tmp_ip = LINK_LOCAL_PREFIX[0:8] + \ b"\x00\x00\x00\xff\xfe\x00" + \ struct.pack(">Q", underlayer.src_addr)[6:] else: payload = packet.payload # Most of the times, it's necessary the IEEE 802.15.4 data to extract this address raise Exception( 'Unimplemented: IP Header is contained into IEEE 802.15.4 frame, in this case it\'s not available.' ) else: warning("Unknown source address compression mode !") else: # self.sac == 1: if self.sam == 0x0: pass elif self.sam == 0x2: # TODO: take context IID tmp_ip = LINK_LOCAL_PREFIX[0:8] + b"\x00\x00\x00\xff\xfe\x00" + \ tmp_ip[16 - source_addr_mode2(self):16] elif self.sam == 0x3: tmp_ip = LINK_LOCAL_PREFIX[ 0:8] + b"\x00" * 8 # TODO: CONTEXT ID else: print(self.sam) raise Exception('Unimplemented') self.sourceAddr = inet_ntop(socket.AF_INET6, tmp_ip) return self.sourceAddr
def m2i(self, pkt, x): opt = [] while x: o = orb(x[0]) if o == 255: opt.append("end") x = x[1:] continue if o == 0: opt.append("pad") x = x[1:] continue if len(x) < 2 or len(x) < orb(x[1]) + 2: opt.append(x) break elif o in DHCPOptions: f = DHCPOptions[o] if isinstance(f, str): olen = orb(x[1]) opt.append((f, x[2:olen + 2])) x = x[olen + 2:] else: olen = orb(x[1]) lval = [f.name] try: left = x[2:olen + 2] while left: left, val = f.getfield(pkt, left) lval.append(val) except Exception: opt.append(x) break else: otuple = tuple(lval) opt.append(otuple) x = x[olen + 2:] else: olen = orb(x[1]) opt.append((o, x[2:olen + 2])) x = x[olen + 2:] return opt
def in6_get_common_plen(a, b): # type: (str, str) -> int """ Return common prefix length of IPv6 addresses a and b. """ def matching_bits(byte1, byte2): # type: (int, int) -> int for i in range(8): cur_mask = 0x80 >> i if (byte1 & cur_mask) != (byte2 & cur_mask): return i return 8 tmpA = inet_pton(socket.AF_INET6, a) tmpB = inet_pton(socket.AF_INET6, b) for i in range(16): mbits = matching_bits(orb(tmpA[i]), orb(tmpB[i])) if mbits != 8: return 8 * i + mbits return 128
def do_dec(cls, s, context=None, safe=False): # /!\ the unused_bits information is lost after this decoding l, s, t = cls.check_type_check_len(s) if len(s) > 0: unused_bits = orb(s[0]) if safe and unused_bits > 7: raise BER_Decoding_Error( "BERcodec_BIT_STRING: too many unused_bits advertised", remaining=s ) s = "".join(binrepr(orb(x)).zfill(8) for x in s[1:]) if unused_bits > 0: s = s[:-unused_bits] return cls.tag.asn1_object(s), t else: raise BER_Decoding_Error( "BERcodec_BIT_STRING found no content " "(not even unused_bits byte)", remaining=s )
def _sdentry_class(payload, **kargs): TYPE_PAYLOAD_I = 0 pl_type = orb(payload[TYPE_PAYLOAD_I]) cls = None if pl_type in SDENTRY_TYPE_SRV: cls = SDEntry_Service elif pl_type in SDENTRY_TYPE_EVTGRP: cls = SDEntry_EventGroup return cls(payload, **kargs)
def dispatch_hook(cls, _pkt=None, *args, **kargs): """ Returns the right parameter set class. """ cls = conf.raw_layer if _pkt is not None: ptype = orb(_pkt[0]) return globals().get(_param_set_cls.get(ptype), conf.raw_layer) return cls
def dns_encode(x, check_built=False): """Encodes a bytes string into the DNS format :param x: the string :param check_built: detect already-built strings and ignore them :returns: the encoded bytes string """ if not x or x == b".": return b"\x00" if check_built and b"." not in x and (orb(x[-1]) == 0 or (orb(x[-2]) & 0xc0) == 0xc0): # The value has already been processed. Do not process it again return x # Truncate chunks that cannot be encoded (more than 63 bytes..) x = b"".join(chb(len(y)) + y for y in (k[:63] for k in x.split(b"."))) if x[-1:] != b"\x00": x += b"\x00" return x
def m2i(self, pkt, val): ret = [] for v in val: byte = orb(v) left = byte >> 4 right = byte & 0xf if left == 0xf: ret += [TBCD_TO_ASCII[right]] else: ret += [TBCD_TO_ASCII[right], TBCD_TO_ASCII[left]] return "".join(ret)
def dispatch_hook(cls, _pkt=None, *args, **kargs): if _pkt: _id = orb(_pkt[0]) if _id == 221: oui_a = orb(_pkt[2]) oui_b = orb(_pkt[3]) oui_c = orb(_pkt[4]) if oui_a == 0x00 and oui_b == 0x50 and oui_c == 0xf2: # MS OUI type_ = orb(_pkt[5]) if type_ == 0x01: # MS WPA IE return Dot11EltMicrosoftWPA else: return Dot11EltVendorSpecific else: return Dot11EltVendorSpecific else: return cls.registered_ies.get(_id, cls) return cls
def m2i(self, pkt, val): ret = [] for v in val: byte = orb(v) left = byte >> 4 right = byte & 0xf if left == 0xf: ret.append(TBCD_TO_ASCII[right:right + 1]) else: ret += [TBCD_TO_ASCII[right:right + 1], TBCD_TO_ASCII[left:left + 1]] return b"".join(ret)
def guess_payload_class(self, payload): # Snooped from Wireshark # https://github.com/boundary/wireshark/blob/07eade8124fd1d5386161591b52e177ee6ea849f/epan/dissectors/packet-gtp.c#L8195 # noqa: E501 if self.gtp_type == 255: sub_proto = orb(payload[0]) if sub_proto >= 0x45 and sub_proto <= 0x4e: return IP elif (sub_proto & 0xf0) == 0x60: return IPv6 else: return PPP return GTPHeader.guess_payload_class(self, payload)
def IE_Dispatcher(s): """Choose the correct Information Element class.""" if len(s) < 1: return Raw(s) # Get the IE type ietype = orb(s[0]) cls = ietypecls.get(ietype, Raw) # if ietype greater than 128 are TLVs if cls == Raw and ietype & 128 == 128: cls = IE_NotImplementedTLV return cls(s)
def _check_len(self, pkt): """Check for odd packet length and pad according to Cisco spec. This padding is only used for checksum computation. The original packet should not be altered.""" if len(pkt) % 2: last_chr = pkt[-1] if last_chr <= b'\x80': return pkt[:-1] + b'\x00' + last_chr else: return pkt[:-1] + b'\xff' + chb(orb(last_chr) - 1) else: return pkt
def getfield(self, pkt, s): if not s: return None prefix = orb(s[0]) # if prefix is invalid value ( 0 > prefix > 32 ) then break if prefix > 32 or prefix < 0: warning("Invalid prefix value: %d (0x%x)", prefix, prefix) return s, [] route_len = 5 + (prefix + 7) // 8 return s[route_len:], self.m2i(pkt, s[:route_len])
def dispatch_hook(cls, _pkt=None, *_, **kargs): code = None if _pkt: code = orb(_pkt[0]) elif "code" in kargs: code = kargs["code"] if isinstance(code, six.string_types): code = cls.fields_desc[0].s2i[code] if code in (1, 2): return PPP_CHAP_ChallengeResponse return cls
def BER_id_enc(n): if n < 256: # low-tag-number return chb(n) else: # high-tag-number s = BER_num_enc(n) tag = orb(s[0]) # first byte, as an int tag &= 0x07 # reset every bit from 8 to 4 tag <<= 5 # move back the info bits on top tag |= 0x1f # pad with 1s every bit from 5 to 1 return chb(tag) + s[1:]
def OpenFlow(self, payload): if self is None or self.dport == 6653 or self.dport == 6633 or self.sport == 6653 or self.sport == 6633: # port 6653 has been allocated by IANA, port 6633 should no longer be used # OpenFlow function may be called with None self in OFPPacketField of_type = orb(payload[1]) if of_type == 1: err_type = orb(payload[9]) # err_type is a short int, but last byte is enough if err_type == 255: err_type = 65535 return ofp_error_cls[err_type] elif of_type == 16: mp_type = orb(payload[9]) if mp_type == 255: mp_type = 65535 return ofp_stats_request_cls[mp_type] elif of_type == 17: mp_type = orb(payload[9]) if mp_type == 255: mp_type = 65535 return ofp_stats_reply_cls[mp_type] else: return ofpt_cls[of_type] else: return TCP_guess_payload_class_copy(self, payload)
def guess_payload_class(self, payload): pl_type = orb(payload[2]) return { _SDOption.CFG_TYPE: SDOption_Config, self.LOADBALANCE_TYPE: SDOption_LoadBalance, self.IP4_ENDPOINT_TYPE: SDOption_IP4_EndPoint, self.IP4_MCAST_TYPE: SDOption_IP4_Multicast, self.IP4_SDENDPOINT_TYPE: SDOption_IP4_SD_EndPoint, self.IP6_ENDPOINT_TYPE: SDOption_IP6_EndPoint, self.IP6_MCAST_TYPE: SDOption_IP6_Multicast, self.IP6_SDENDPOINT_TYPE: SDOption_IP6_SD_EndPoint }.get(pl_type, Raw)
def m2i(self, pkt, s): ret_s = b"" tmp_s = s while tmp_s: tmp_len = orb(tmp_s[0]) + 1 if tmp_len > len(tmp_s): warning("APN prematured end of character-string (size=%i, remaining bytes=%i)" % (tmp_len, len(tmp_s))) # noqa: E501 ret_s += tmp_s[1:tmp_len] tmp_s = tmp_s[tmp_len:] if len(tmp_s): ret_s += b"." s = ret_s return s