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 post_build(self, p, pay): if self.length is None: tmp_len = len(p) tmp_pay = p[:2] + chb((tmp_len >> 8) & 0xff) p = tmp_pay + chb(tmp_len & 0xff) + p[4:] p += pay return p
def post_build(self, pkt, pay): if self.len is None: # len should be a FieldLenField but has an unsupported # format (14 bits) flags = orb(pkt[0]) & 0xc0 length = len(self.value) pkt = chb(flags + (length >> 8)) + chb(length % 256) + pkt[2:] return pkt + pay
def post_build(self, pkt, pay): if self.descs_count is None: # descs_count should be a FieldLenField but has an # unsupported format (14 bits) flags = orb(pkt[0]) & 0xc0 count = len(self.descs_list) pkt = chb(flags + (count >> 8)) + chb(count % 256) + pkt[2:] return pkt + pay
def post_build(self, p, pay): p += pay if self.keysize is None: keysize = len(self.authdata) p = p[:6] + chb((keysize >> 8) & 0xff) + chb(keysize & 0xff) + p[8:] # noqa: E501 return p
def get_raw(self): raw = '' raw += chb((self.length & 0xFF00) >> 8) raw += chb(self.length & 0xFF) if self.content != '': raw += self.content return raw
def post_build(self, p, pay): p += pay if self.len is None: l = len(p) p = p[:2] + chb((l >> 8) & 0xff) + chb(l & 0xff) + p[4:] return p
def post_build(self, p, pay): # type: (bytes, bytes) -> bytes p += pay if self.payload_len is None: pay_len = len(pay) p = p[:4] + chb((pay_len >> 8) & 0xff) + chb(pay_len & 0xff) + p[6:] # noqa: E501 return p
def post_build(self, p, pay): p += pay if self.keysize is None: keysize = len(self.authdata) p = p[:6] + chb((keysize >> 8) & 0xff) + chb(keysize & 0xff) + p[8:] return p
def decompressDestAddr(self, packet): # https://tools.ietf.org/html/rfc6282#section-3.1.1 try: tmp_ip = inet_pton(socket.AF_INET6, self.dst) except socket.error: tmp_ip = b"\x00" * 16 if self.m == 0 and self.dac == 0: if self.dam == 0: # Address fully carried pass elif self.dam == 1: tmp_ip = LINK_LOCAL_PREFIX[0:8] + tmp_ip[-8:] elif self.dam == 2: tmp_ip = LINK_LOCAL_PREFIX[ 0:8] + b"\x00\x00\x00\xff\xfe\x00" + tmp_ip[ -2:] # noqa: E501 elif self.dam == 3: tmp_ip = _extract_upperaddress(self, source=False) elif self.m == 0 and self.dac == 1: if self.dam == 0: # reserved pass elif self.dam == 0x3: # should use context IID + encapsulating header tmp_ip = _extract_upperaddress(self, source=False) elif self.dam not in [0x1, 0x2]: # https://tools.ietf.org/html/rfc6282#page-9 # Should use context information: unimplemented pass elif self.m == 1 and self.dac == 0: if self.dam == 0: # Address fully carried pass elif self.dam == 1: tmp = b"\xff" + chb(tmp_ip[16 - dest_addr_size(self)]) tmp_ip = tmp + b"\x00" * 9 + tmp_ip[-5:] elif self.dam == 2: tmp = b"\xff" + chb(tmp_ip[16 - dest_addr_size(self)]) tmp_ip = tmp + b"\x00" * 11 + tmp_ip[-3:] else: # self.dam == 3: tmp_ip = b"\xff\x02" + b"\x00" * 13 + tmp_ip[-1:] elif self.m == 1 and self.dac == 1: if self.dam == 0x0: # https://tools.ietf.org/html/rfc6282#page-10 # https://github.com/wireshark/wireshark/blob/f54611d1104d85a425e52c7318c522ed249916b6/epan/dissectors/packet-6lowpan.c#L2149-L2166 # Format: ffXX:XXLL:PPPP:PPPP:PPPP:PPPP:XXXX:XXXX # P and L should be retrieved from context P = b"\x00" * 16 L = b"\x00" X = tmp_ip[-6:] tmp_ip = b"\xff" + X[:2] + L + P[:8] + X[2:6] else: # all the others values: reserved pass self.dst = inet_ntop(socket.AF_INET6, tmp_ip) return self.dst
def post_build(self, p, pay): p += pay if self.Length is None: l = len(p) p = p[:6] + chb((l >> 8) & 0xff) + chb(l & 0xff) + p[8:] if self.chksum is None: ck = checksum(p) p = p[:2] + chb(ck >> 8) + chb(ck & 0xff) + p[4:] return p
def post_build(self, p, pay): p += pay if self.len is None: tmp_len = len(p) tmp_p = p[:2] + chb((tmp_len >> 8) & 0xff) p = tmp_p + chb(tmp_len & 0xff) + p[4:] return p
def decompressDestinyAddr(self, packet): try: tmp_ip = inet_pton(socket.AF_INET6, self.destinyAddr) except socket.error: tmp_ip = b"\x00" * 16 if self.m == 0 and self.dac == 0: if self.dam == 0: pass elif self.dam == 1: tmp_ip = LINK_LOCAL_PREFIX[0:8] + tmp_ip[-8:] elif self.dam == 2: tmp_ip = LINK_LOCAL_PREFIX[0:8] + b"\x00\x00\x00\xff\xfe\x00" + tmp_ip[-2:] # noqa: E501 """else: #self.dam == 3 raise Exception('Unimplemented')""" elif self.m == 0 and self.dac == 1: if self.dam == 0: raise Exception('Reserved') elif self.dam == 0x3: underlayer = self.underlayer while underlayer is not None and not isinstance(underlayer, Dot15d4Data): # noqa: E501 underlayer = underlayer.underlayer if type(underlayer) == Dot15d4Data: if underlayer.underlayer.fcf_destaddrmode == 3: tmp_ip = LINK_LOCAL_PREFIX[0:8] + struct.pack(">Q", underlayer.dest_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", underlayer.dest_addr)[6:] 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 elif self.dam not in [0x1, 0x2]: warning("Unknown destiny address compression mode !") elif self.m == 1 and self.dac == 0: if self.dam == 0: raise Exception("unimplemented") elif self.dam == 1: tmp = b"\xff" + chb(tmp_ip[16 - destiny_addr_mode(self)]) tmp_ip = tmp + b"\x00" * 9 + tmp_ip[-5:] elif self.dam == 2: tmp = b"\xff" + chb(tmp_ip[16 - destiny_addr_mode(self)]) tmp_ip = tmp + b"\x00" * 11 + tmp_ip[-3:] else: # self.dam == 3: tmp_ip = b"\xff\x02" + b"\x00" * 13 + tmp_ip[-1:] elif self.m == 1 and self.dac == 1: if self.dam == 0x0: raise Exception("Unimplemented: I didnt understand the 6lowpan specification") # noqa: E501 else: # all the others values raise Exception("Reserved value by specification.") self.destinyAddr = inet_ntop(socket.AF_INET6, tmp_ip) return self.destinyAddr
def load_winpcapy(): """This functions calls Winpcap/Npcap pcap_findalldevs function, and extracts and parse all the data scapy will need to use it: - the Interface List - the IPv4 addresses - the IPv6 addresses This data is stored in their respective conf.cache_* subfields: conf.cache_iflist conf.cache_ipaddrs conf.cache_in6_getifaddr """ err = create_string_buffer(PCAP_ERRBUF_SIZE) devs = POINTER(pcap_if_t)() if_list = [] ip_addresses = {} ip6_addresses = [] if pcap_findalldevs(byref(devs), err) < 0: return try: p = devs # Iterate through the different interfaces while p: if_list.append(plain_str(p.contents.name)) a = p.contents.addresses while a: # IPv4 address if a.contents.addr.contents.sa_family == socket.AF_INET: # noqa: E501 ap = a.contents.addr val = cast(ap, POINTER(sockaddr_in)) if_raw_addr = b"".join( chb(x) for x in val.contents.sin_addr[:4]) # noqa: E501 if if_raw_addr != b'\x00\x00\x00\x00': ip_addresses[plain_str( p.contents.name )] = if_raw_addr # noqa: E501 # IPv6 address if a.contents.addr.contents.sa_family == socket.AF_INET6: # noqa: E501 ap = a.contents.addr val = cast(ap, POINTER(sockaddr_in6)) addr = inet_ntop(socket.AF_INET6, b"".join( chb(x) for x in val.contents.sin6_addr[:])) # noqa: E501 scope = scapy.utils6.in6_getscope(addr) ip6_addresses.append( (addr, scope, plain_str(p.contents.name))) # noqa: E501 a = a.contents.next p = p.contents.next conf.cache_iflist = if_list conf.cache_ipaddrs = ip_addresses conf.cache_in6_getifaddr = ip6_addresses except Exception: raise finally: pcap_freealldevs(devs)
def post_build(self, p, pay): p += pay if self.Length is None: tmp_len = len(p) tmp_p = p[:6] + chb((tmp_len >> 8) & 0xff) + chb(tmp_len & 0xff) p = tmp_p + p[8:] if self.chksum is None: ck = checksum(p) p = p[:2] + chb(ck >> 8) + chb(ck & 0xff) + p[4:] return p
def enc(cls, s): # /!\ this is DER encoding (bit strings are only zero-bit padded) s = raw(s) if len(s) % 8 == 0: unused_bits = 0 else: unused_bits = 8 - len(s) % 8 s += b"0" * unused_bits s = b"".join(chb(int(b"".join(chb(y) for y in x), 2)) for x in zip(*[iter(s)] * 8)) # noqa: E501 s = chb(unused_bits) + s return chb(hash(cls.tag)) + BER_len_enc(len(s)) + s
def BER_len_enc(ll, size=0): if ll <= 127 and size == 0: return chb(ll) s = b"" while ll or size > 0: s = chb(ll & 0xff) + s ll >>= 8 size -= 1 if len(s) > 127: raise BER_Exception("BER_len_enc: Length too long (%i) to be encoded [%r]" % (len(s), s)) # noqa: E501 return chb(len(s) | 0x80) + s
def post_build(self, p, pay): if self.chksum is None: if isinstance(self.underlayer, IP): ck = in4_chksum(112, self.underlayer, p) elif isinstance(self.underlayer, IPv6): ck = in6_chksum(112, self.underlayer, p) else: warning("No IP(v6) layer to compute checksum on VRRP. Leaving null") # noqa: E501 ck = 0 p = p[:6] + chb(ck >> 8) + chb(ck & 0xff) + p[8:] return p
def i2m(self, pkt, val): if not isinstance(val, bytes): val = bytes_encode(val) ret_string = b"" for i in range(0, len(val), 2): tmp = val[i:i + 2] if len(tmp) == 2: ret_string += chb(int(tmp[::-1], 16)) else: ret_string += chb(int(b"F" + tmp[:1], 16)) return ret_string
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 post_build(self, p, pay): if self.chksum is None: if isinstance(self.underlayer, IP): ck = in4_chksum(112, self.underlayer, p) elif isinstance(self.underlayer, IPv6): ck = in6_chksum(112, self.underlayer, p) else: warning("No IP(v6) layer to compute checksum on VRRP. " "Leaving null") ck = 0 p = p[:6] + chb(ck >> 8) + chb(ck & 0xff) + p[8:] return p
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 = orb(pkt[-1]) if last_chr <= 0x80: return pkt[:-1] + b'\x00' + chb(last_chr) else: return pkt[:-1] + b'\xff' + chb(orb(last_chr) - 1) else: return pkt
def enc(cls, s): # /!\ this is DER encoding (bit strings are only zero-bit padded) s = raw(s) if len(s) % 8 == 0: unused_bits = 0 else: unused_bits = 8 - len(s) % 8 s += b"0" * unused_bits s = b"".join(chb(int(b"".join(chb(y) for y in x), 2)) for x in zip(*[iter(s)] * 8)) s = chb(unused_bits) + s return chb(hash(cls.tag)) + BER_len_enc(len(s)) + s
def post_build(self, p, pay): """Called implicitly before a packet is sent to compute and place IGMP checksum. Parameters: self The instantiation of an IGMP class p The IGMP message in hex in network byte order pay Additional payload for the IGMP message """ p += pay if self.chksum is None: ck = checksum(p) p = p[:2] + chb(ck >> 8) + chb(ck & 0xff) + p[4:] return p
def post_build(self, p, pay): ihl = self.ihl p += b"\0" * ((-len(p)) % 4) # pad IP options if needed if ihl is None: ihl = len(p) // 4 p = chb(((self.version & 0xf) << 4) | ihl & 0x0f) + p[1:] if self.len is None: tmp_len = len(p) + len(pay) p = p[:2] + struct.pack("!H", tmp_len) + p[4:] if self.chksum is None: ck = checksum(p) p = p[:10] + chb(ck >> 8) + chb(ck & 0xff) + p[12:] return p + pay
def generate(self, req): if not self.is_valid(req): return _ObdResponseGenerator._generate_invalid(req) payload = _ObdResponseGenerator.\ generate_packet_with_random_values(OBD_DTC) byte_string = chb(req.service + 0x40) + chb(self.count) for _ in range(self.count): byte_string += bytes(payload) packet = OBD(byte_string) return packet
def post_build(self, p, pay): """Called implicitly before a packet is sent to compute and place IGMP checksum. # noqa: E501 Parameters: self The instantiation of an IGMP class p The IGMP message in hex in network byte order pay Additional payload for the IGMP message """ p += pay if self.chksum is None: ck = checksum(p) p = p[:2] + chb(ck >> 8) + chb(ck & 0xff) + p[4:] return p
def customPRF512(key, amac, smac, anonce, snonce): """Source https://stackoverflow.com/questions/12018920/""" A = b"Pairwise key expansion" B = b"".join(sorted([amac, smac]) + sorted([anonce, snonce])) blen = 64 i = 0 R = b'' while i <= ((blen * 8 + 159) // 160): hmacsha1 = hmac.new(key, A + chb(0x00) + B + chb(i), hashlib.sha1) i += 1 R = R + hmacsha1.digest() return R[:blen]
def enc(cls, _s): # type: (AnyStr) -> bytes # /!\ this is DER encoding (bit strings are only zero-bit padded) s = bytes_encode(_s) if len(s) % 8 == 0: unused_bits = 0 else: unused_bits = 8 - len(s) % 8 s += b"0" * unused_bits s = b"".join(chb(int(b"".join(chb(y) for y in x), 2)) for x in zip(*[iter(s)] * 8)) s = chb(unused_bits) + s return chb(hash(cls.tag)) + BER_len_enc(len(s)) + s
def BER_len_enc(ll, size=0): if ll <= 127 and size == 0: return chb(ll) s = b"" while ll or size > 0: s = chb(ll & 0xff) + s ll >>= 8 size -= 1 if len(s) > 127: raise BER_Exception( "BER_len_enc: Length too long (%i) to be encoded [%r]" % (len(s), s) ) return chb(len(s) | 0x80) + s
def decompressDestinyAddr(self, packet): try: tmp_ip = inet_pton(socket.AF_INET6, self.destinyAddr) except socket.error: tmp_ip = b"\x00" * 16 if self.m == 0 and self.dac == 0: if self.dam == 0: pass elif self.dam == 1: tmp_ip = LINK_LOCAL_PREFIX[0:8] + tmp_ip[-8:] elif self.dam == 2: tmp_ip = LINK_LOCAL_PREFIX[ 0:8] + b"\x00\x00\x00\xff\xfe\x00" + tmp_ip[ -2:] # noqa: E501 elif self.dam == 3: # TODO May need some extra changes, we are copying # (self.m == 0 and self.dac == 1) tmp_ip = _extract_upperaddress(self, source=False) elif self.m == 0 and self.dac == 1: if self.dam == 0: raise Exception('Reserved') elif self.dam == 0x3: tmp_ip = _extract_upperaddress(self, source=False) elif self.dam not in [0x1, 0x2]: warning("Unknown destiny address compression mode !") elif self.m == 1 and self.dac == 0: if self.dam == 0: raise Exception("unimplemented") elif self.dam == 1: tmp = b"\xff" + chb(tmp_ip[16 - destiny_addr_mode(self)]) tmp_ip = tmp + b"\x00" * 9 + tmp_ip[-5:] elif self.dam == 2: tmp = b"\xff" + chb(tmp_ip[16 - destiny_addr_mode(self)]) tmp_ip = tmp + b"\x00" * 11 + tmp_ip[-3:] else: # self.dam == 3: tmp_ip = b"\xff\x02" + b"\x00" * 13 + tmp_ip[-1:] elif self.m == 1 and self.dac == 1: if self.dam == 0x0: # See https://tools.ietf.org/html/rfc6282#page-9 raise Exception( "Unimplemented: I didn't understand the 6lowpan specification" ) # noqa: E501 else: # all the others values raise Exception("Reserved value by specification.") self.destinyAddr = inet_ntop(socket.AF_INET6, tmp_ip) return self.destinyAddr
def enc(cls, i): s = [] while True: s.append(i & 0xff) if -127 <= i < 0: break if 128 <= i <= 255: s.append(0) i >>= 8 if not i: break s = [chb(hash(c)) for c in s] s.append(BER_len_enc(len(s))) s.append(chb(hash(cls.tag))) s.reverse() return b"".join(s)
def next(self): c = pcap_next_ex(self.pcap, byref(self.header), byref(self.pkt_data)) # noqa: E501 if not c > 0: return ts = self.header.contents.ts.tv_sec + float(self.header.contents.ts.tv_usec) / 1000000 # noqa: E501 pkt = b"".join(chb(i) for i in self.pkt_data[:self.header.contents.len]) # noqa: E501 return ts, pkt
def _scan_id_service(socket, timeout, service_class, id_numbers, verbose): """ Queries certain PIDs and stores their return value Args: socket: is the ISOTPSocket, over which the OBD-Services communicate. the id 0x7df acts as a broadcast address for all obd-supporting ECUs. timeout: only required for the OBD Simulator, since it might tell it supports a PID, while it actually doesn't and won't respond to this PID. If this happens with a real ECU, it is an implementation error. service_class: specifies, which OBD-Service should be queried. id_numbers: a set of PIDs, which should be queried by the method. verbose: specifies, whether the sr1()-method gives feedback or not. This method queries the specified id_numbers and stores their responses in a dictionary, which is then returned. """ data = dict() for id_number in id_numbers: id_byte = chb(id_number) # assemble request packet pkt = OBD() / service_class(id_byte) resp = socket.sr1(pkt, timeout=timeout, verbose=verbose) if resp is not None: data[id_number] = bytes(resp) return data
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 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 _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 in6_getRandomizedIfaceId(ifaceid, previous=None): # type: (str, Optional[str]) -> Tuple[str, str] """ 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: b_previous = bytes(RandBin(8)) else: b_previous = inet_pton(socket.AF_INET6, "::" + previous)[8:] s = inet_pton(socket.AF_INET6, "::" + ifaceid)[8:] + b_previous import hashlib s = hashlib.md5(s).digest() s1, s2 = s[:8], s[8:] s1 = chb(orb(s1[0]) & (~0x04)) + s1[1:] # set bit 6 to 0 bs1 = inet_ntop(socket.AF_INET6, b"\xff" * 8 + s1)[20:] bs2 = inet_ntop(socket.AF_INET6, b"\xff" * 8 + s2)[20:] return (bs1, bs2)
def generate(self, req): if not self.is_valid(req): return _ObdResponseGenerator._generate_invalid(req) full_payload = b'' for r in req.payload.requests: id_field_name = r.fields_desc[0].name one_id = r.getfieldval(id_field_name) try: class_name = _ObdResponseGeneratorId.get_class_name( id_field_name, one_id) payload = _ObdResponseGenerator.\ generate_packet_with_random_values(class_name) full_payload += bytes(r) + bytes(payload) except NameError: # appears when PID/IID etc. not supported # do not respond, OBD spec conform print("{0} {1:#04x} not supported".format( id_field_name.upper(), one_id)) if len(full_payload) == 0: # if no payload, do not generate/send an empty answer return None packet = OBD(chb(req.service + 0x40) + full_payload) return packet
def post_build(self, p, pay): # This just forces destaddrmode to None for Ack frames. if self.fcf_frametype == 2 and self.fcf_destaddrmode != 0: self.fcf_destaddrmode = 0 return p[:1] + \ chb((self.fcf_srcaddrmode << 6) + (self.fcf_framever << 4)) \ + p[2:] + pay else: return p + pay
def BER_num_enc(ll, size=1): x = [] while ll or size > 0: x.insert(0, ll & 0x7f) if len(x) > 1: x[0] |= 0x80 ll >>= 7 size -= 1 return b"".join(chb(k) for k in x)
def post_build(self, p, pay): if self.headerLen is None: headerLen = len(p) if isinstance(self.payload, (USBpcapTransferIsochronous, USBpcapTransferInterrupt, USBpcapTransferControl)): headerLen += len(self.payload) - len(self.payload.payload) p = chb(headerLen) + p[1:] return p + pay
def decompressDestinyAddr(self, packet): try: tmp_ip = inet_pton(socket.AF_INET6, self.destinyAddr) except socket.error: tmp_ip = b"\x00" * 16 if self.m == 0 and self.dac == 0: if self.dam == 0: pass elif self.dam == 1: tmp_ip = LINK_LOCAL_PREFIX[0:8] + tmp_ip[-8:] elif self.dam == 2: tmp_ip = LINK_LOCAL_PREFIX[0:8] + b"\x00\x00\x00\xff\xfe\x00" + tmp_ip[-2:] # noqa: E501 elif self.dam == 3: # TODO May need some extra changes, we are copying # (self.m == 0 and self.dac == 1) tmp_ip = _extract_dot15d4address(self, source=False) elif self.m == 0 and self.dac == 1: if self.dam == 0: raise Exception('Reserved') elif self.dam == 0x3: tmp_ip = _extract_dot15d4address(self, source=False) elif self.dam not in [0x1, 0x2]: warning("Unknown destiny address compression mode !") elif self.m == 1 and self.dac == 0: if self.dam == 0: raise Exception("unimplemented") elif self.dam == 1: tmp = b"\xff" + chb(tmp_ip[16 - destiny_addr_mode(self)]) tmp_ip = tmp + b"\x00" * 9 + tmp_ip[-5:] elif self.dam == 2: tmp = b"\xff" + chb(tmp_ip[16 - destiny_addr_mode(self)]) tmp_ip = tmp + b"\x00" * 11 + tmp_ip[-3:] else: # self.dam == 3: tmp_ip = b"\xff\x02" + b"\x00" * 13 + tmp_ip[-1:] elif self.m == 1 and self.dac == 1: if self.dam == 0x0: raise Exception("Unimplemented: I didn't understand the 6lowpan specification") # noqa: E501 else: # all the others values raise Exception("Reserved value by specification.") self.destinyAddr = inet_ntop(socket.AF_INET6, tmp_ip) return self.destinyAddr
def post_build(self, p, pay): p += pay if self.Length is None: if len(pay) > 2: l = len(pay) else: l = 0 p = p[:1] + chb(l & 0x3f) + p[2:] if not isinstance(self.underlayer, BTLE): self.add_underlayer(BTLE) return p
def enc(cls, oid): oid = raw(oid) if oid: lst = [int(x) for x in oid.strip(b".").split(b".")] else: lst = list() if len(lst) >= 2: lst[1] += 40 * lst[0] del(lst[0]) s = b"".join(BER_num_enc(k) for k in lst) return chb(hash(cls.tag)) + BER_len_enc(len(s)) + s
def _tls_add_pad(p, block_size): """ Provided with cipher block size parameter and current TLSCompressed packet p (after MAC addition), the function adds required, deterministic padding to p.data before encryption step, as it is defined for TLS (i.e. not SSL and its allowed random padding). The function has no return value. """ padlen = -p.len % block_size padding = chb(padlen) * (padlen + 1) p.len += len(padding) p.data += padding
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 build_GTK_KDE(self): """Build the Key Data Encapsulation for GTK KeyID: 0 Ref: 802.11i p81 """ return b''.join([ b'\xdd', # Type KDE chb(len(self.gtk_full) + 6), b'\x00\x0f\xac', # OUI b'\x01', # GTK KDE b'\x00\x00', # KeyID - Tx - Reserved x2 self.gtk_full, ])
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