class PIMv2HelloGenerationID(_PIMv2GenericHello): name = "PIMv2 Hello Options : Generation ID" fields_desc = [ ShortField("type", 20), FieldLenField("length", None, length_of="generation_id", fmt="!H"), IntField("generation_id", RandInt()) ]
def __init__(self, interface, name=None, mac=None, vlan=None): self._mac = None self._chaddr = None self._vlan = vlan self._xid = RandInt() self._vendor_class = None self.lease = None self.lease_start_time = None # to do request for an ip (to start initial dhcp with an request instead of discover) self._yiaddr = None self._siaddr = None self.hostname = name if name is not None else 'host{}'.format(id(self)) self.setup_logger() self.log.debug("================ New host %s ==================", self.hostname) if mac is None: mac = str(RandMAC()) self.use_mac_addr(mac) if vlan: self._interface = '{}.{}'.format(interface, vlan) else: self._interface = interface
class GTPPDUNotificationRequest(Packet): # 3GPP TS 29.060 V9.1.0 (2009-12) name = "GTP PDU Notification Request" fields_desc = [PacketListField("IE_list", [IE_IMSI(), IE_TEICP(TEICI=RandInt()), IE_EndUserAddress(PDPTypeNumber=0x21), # noqa: E501 IE_AccessPointName(), IE_GSNAddress(ipv4_address="127.0.0.1"), # noqa: E501 ], IE_Dispatcher)]
def queso_sig(target, dport=80, timeout=3): p = queso_kdb.get_base() ret = [] for flags in ["S", "SA", "F", "FA", "SF", "P", "SEC"]: ans, unans = sr(IP(dst=target)/TCP(dport=dport, flags=flags, seq=RandInt()), timeout=timeout, verbose=0) if len(ans) == 0: rs = "- - - -" else: s, r = ans[0] rs = "%i" % (r.seq != 0) if not r.ack: r += " 0" elif r.ack-s.seq > 666: rs += " R" % 0 else: rs += " +%i" % (r.ack-s.seq) rs += " %X" % r.window rs += " %x" % r.payload.flags ret.append(rs) return ret
def p0f_impersonate(pkt, osgenre=None, osdetails=None, signature=None, extrahops=0, mtu=1500, uptime=None): """Modifies pkt so that p0f will think it has been sent by a specific OS. If osdetails is None, then we randomly pick up a personality matching osgenre. If osgenre and signature are also None, we use a local signature (using p0f_getlocalsigs). If signature is specified (as a tuple), we use the signature. For now, only TCP Syn packets are supported. Some specifications of the p0f.fp file are not (yet) implemented.""" pkt = pkt.copy() #pkt = pkt.__class__(raw(pkt)) while pkt.haslayer(IP) and pkt.haslayer(TCP): pkt = pkt.getlayer(IP) if isinstance(pkt.payload, TCP): break pkt = pkt.payload if not isinstance(pkt, IP) or not isinstance(pkt.payload, TCP): raise TypeError("Not a TCP/IP packet") db = p0f_selectdb(pkt.payload.flags) if osgenre: pb = db.get_base() if pb is None: pb = [] pb = [x for x in pb if x[6] == osgenre] if osdetails: pb = [x for x in pb if x[7] == osdetails] elif signature: pb = [signature] else: pb = p0f_getlocalsigs()[db] if db == p0fr_kdb: # 'K' quirk <=> RST+ACK if pkt.payload.flags & 0x4 == 0x4: pb = [x for x in pb if 'K' in x[5]] else: pb = [x for x in pb if 'K' not in x[5]] if not pb: raise Scapy_Exception("No match in the p0f database") pers = pb[random.randint(0, len(pb) - 1)] # options (we start with options because of MSS) # Take the options already set as "hints" to use in the new packet if we # can. MSS, WScale and Timestamp can all be wildcarded in a signature, so # we'll use the already-set values if they're valid integers. orig_opts = dict(pkt.payload.options) int_only = lambda val: val if isinstance(val, six.integer_types) else None mss_hint = int_only(orig_opts.get('MSS')) wscale_hint = int_only(orig_opts.get('WScale')) ts_hint = [int_only(o) for o in orig_opts.get('Timestamp', (None, None))] options = [] if pers[4] != '.': for opt in pers[4].split(','): if opt[0] == 'M': # MSS might have a maximum size because of window size # specification if pers[0][0] == 'S': maxmss = (2**16-1) // int(pers[0][1:]) else: maxmss = (2**16-1) # disregard hint if out of range if mss_hint and not 0 <= mss_hint <= maxmss: mss_hint = None # If we have to randomly pick up a value, we cannot use # scapy RandXXX() functions, because the value has to be # set in case we need it for the window size value. That's # why we use random.randint() if opt[1:] == '*': if mss_hint is not None: options.append(('MSS', mss_hint)) else: options.append(('MSS', random.randint(1, maxmss))) elif opt[1] == '%': coef = int(opt[2:]) if mss_hint is not None and mss_hint % coef == 0: options.append(('MSS', mss_hint)) else: options.append(( 'MSS', coef*random.randint(1, maxmss//coef))) else: options.append(('MSS', int(opt[1:]))) elif opt[0] == 'W': if wscale_hint and not 0 <= wscale_hint < 2**8: wscale_hint = None if opt[1:] == '*': if wscale_hint is not None: options.append(('WScale', wscale_hint)) else: options.append(('WScale', RandByte())) elif opt[1] == '%': coef = int(opt[2:]) if wscale_hint is not None and wscale_hint % coef == 0: options.append(('WScale', wscale_hint)) else: options.append(( 'WScale', coef*RandNum(min=1, max=(2**8-1)//coef))) else: options.append(('WScale', int(opt[1:]))) elif opt == 'T0': options.append(('Timestamp', (0, 0))) elif opt == 'T': # Determine first timestamp. if uptime is not None: ts_a = uptime elif ts_hint[0] and 0 < ts_hint[0] < 2**32: # Note: if first ts is 0, p0f registers it as "T0" not "T", # hence we don't want to use the hint if it was 0. ts_a = ts_hint[0] else: ts_a = random.randint(120, 100*60*60*24*365) # Determine second timestamp. if 'T' not in pers[5]: ts_b = 0 elif ts_hint[1] and 0 < ts_hint[1] < 2**32: ts_b = ts_hint[1] else: # FIXME: RandInt() here does not work (bug (?) in # TCPOptionsField.m2i often raises "OverflowError: # long int too large to convert to int" in: # oval = struct.pack(ofmt, *oval)" # Actually, this is enough to often raise the error: # struct.pack('I', RandInt()) ts_b = random.randint(1, 2**32-1) options.append(('Timestamp', (ts_a, ts_b))) elif opt == 'S': options.append(('SAckOK', '')) elif opt == 'N': options.append(('NOP', None)) elif opt == 'E': options.append(('EOL', None)) elif opt[0] == '?': if int(opt[1:]) in TCPOptions[0]: optname = TCPOptions[0][int(opt[1:])][0] optstruct = TCPOptions[0][int(opt[1:])][1] options.append((optname, struct.unpack(optstruct, RandString(struct.calcsize(optstruct))._fix()))) else: options.append((int(opt[1:]), '')) ## FIXME: qqP not handled else: warning("unhandled TCP option " + opt) pkt.payload.options = options # window size if pers[0] == '*': pkt.payload.window = RandShort() elif pers[0].isdigit(): pkt.payload.window = int(pers[0]) elif pers[0][0] == '%': coef = int(pers[0][1:]) pkt.payload.window = coef * RandNum(min=1, max=(2**16-1)//coef) elif pers[0][0] == 'T': pkt.payload.window = mtu * int(pers[0][1:]) elif pers[0][0] == 'S': ## needs MSS set mss = [x for x in options if x[0] == 'MSS'] if not mss: raise Scapy_Exception("TCP window value requires MSS, and MSS option not set") pkt.payload.window = mss[0][1] * int(pers[0][1:]) else: raise Scapy_Exception('Unhandled window size specification') # ttl pkt.ttl = pers[1]-extrahops # DF flag pkt.flags |= (2 * pers[2]) ## FIXME: ss (packet size) not handled (how ? may be with D quirk ## if present) # Quirks if pers[5] != '.': for qq in pers[5]: ## FIXME: not handled: P, I, X, ! # T handled with the Timestamp option if qq == 'Z': pkt.id = 0 elif qq == 'U': pkt.payload.urgptr = RandShort() elif qq == 'A': pkt.payload.ack = RandInt() elif qq == 'F': if db == p0fo_kdb: pkt.payload.flags |= 0x20 # U else: pkt.payload.flags |= random.choice([8, 32, 40]) # P/U/PU elif qq == 'D' and db != p0fo_kdb: pkt /= conf.raw_layer(load=RandString(random.randint(1, 10))) # XXX p0fo.fp elif qq == 'Q': pkt.payload.seq = pkt.payload.ack #elif qq == '0': pkt.payload.seq = 0 #if db == p0fr_kdb: # '0' quirk is actually not only for p0fr.fp (see # packet2p0f()) if '0' in pers[5]: pkt.payload.seq = 0 elif pkt.payload.seq == 0: pkt.payload.seq = RandInt() while pkt.underlayer: pkt = pkt.underlayer return pkt
class IE_ChargingId(IE_Base): name = "Charging ID" fields_desc = [ ByteEnumField("ietype", 127, IEType), XIntField("Charging_id", RandInt()) ]
class IE_TEICP(IE_Base): name = "Tunnel Endpoint Identifier Control Plane" fields_desc = [ ByteEnumField("ietype", 17, IEType), XIntField("TEICI", RandInt()) ]
class IE_TEIDI(IE_Base): name = "Tunnel Endpoint Identifier Data" fields_desc = [ ByteEnumField("ietype", 16, IEType), XIntField("TEIDI", RandInt()) ]
def randval(self): return RandInt()
def randval(self): # type: () -> VolatileValue return RandInt()
def randval(self): # type: () -> RandField[Any] return RandInt()
def p0f_impersonate(pkt, osgenre=None, osdetails=None, signature=None, extrahops=0, mtu=1500, uptime=None): """Modifies pkt so that p0f will think it has been sent by a specific OS. If osdetails is None, then we randomly pick up a personality matching osgenre. If osgenre and signature are also None, we use a local signature (using p0f_getlocalsigs). If signature is specified (as a tuple), we use the signature. For now, only TCP Syn packets are supported. Some specifications of the p0f.fp file are not (yet) implemented.""" pkt = pkt.copy() #pkt = pkt.__class__(str(pkt)) while pkt.haslayer(IP) and pkt.haslayer(TCP): pkt = pkt.getlayer(IP) if isinstance(pkt.payload, TCP): break pkt = pkt.payload if not isinstance(pkt, IP) or not isinstance(pkt.payload, TCP): raise TypeError("Not a TCP/IP packet") if uptime is None: uptime = random.randint(120, 100 * 60 * 60 * 24 * 365) db = p0f_selectdb(pkt.payload.flags) if osgenre: pb = db.get_base() if pb is None: pb = [] pb = filter(lambda x: x[6] == osgenre, pb) if osdetails: pb = filter(lambda x: x[7] == osdetails, pb) elif signature: pb = [signature] else: pb = p0f_getlocalsigs()[db] if db == p0fr_kdb: # 'K' quirk <=> RST+ACK if pkt.payload.flags & 0x4 == 0x4: pb = filter(lambda x: 'K' in x[5], pb) else: pb = filter(lambda x: 'K' not in x[5], pb) if not pb: raise Scapy_Exception("No match in the p0f database") pers = pb[random.randint(0, len(pb) - 1)] # options (we start with options because of MSS) ## TODO: let the options already set if they are valid options = [] if pers[4] != '.': for opt in pers[4].split(','): if opt[0] == 'M': # MSS might have a maximum size because of window size # specification if pers[0][0] == 'S': maxmss = (2**16 - 1) / int(pers[0][1:]) else: maxmss = (2**16 - 1) # If we have to randomly pick up a value, we cannot use # scapy RandXXX() functions, because the value has to be # set in case we need it for the window size value. That's # why we use random.randint() if opt[1:] == '*': options.append(('MSS', random.randint(1, maxmss))) elif opt[1] == '%': coef = int(opt[2:]) options.append( ('MSS', coef * random.randint(1, maxmss / coef))) else: options.append(('MSS', int(opt[1:]))) elif opt[0] == 'W': if opt[1:] == '*': options.append(('WScale', RandByte())) elif opt[1] == '%': coef = int(opt[2:]) options.append( ('WScale', coef * RandNum(min=1, max=(2**8 - 1) / coef))) else: options.append(('WScale', int(opt[1:]))) elif opt == 'T0': options.append(('Timestamp', (0, 0))) elif opt == 'T': if 'T' in pers[5]: # FIXME: RandInt() here does not work (bug (?) in # TCPOptionsField.m2i often raises "OverflowError: # long int too large to convert to int" in: # oval = struct.pack(ofmt, *oval)" # Actually, this is enough to often raise the error: # struct.pack('I', RandInt()) options.append( ('Timestamp', (uptime, random.randint(1, 2**32 - 1)))) else: options.append(('Timestamp', (uptime, 0))) elif opt == 'S': options.append(('SAckOK', '')) elif opt == 'N': options.append(('NOP', None)) elif opt == 'E': options.append(('EOL', None)) elif opt[0] == '?': if int(opt[1:]) in TCPOptions[0]: optname = TCPOptions[0][int(opt[1:])][0] optstruct = TCPOptions[0][int(opt[1:])][1] options.append( (optname, struct.unpack( optstruct, RandString(struct.calcsize(optstruct))._fix()))) else: options.append((int(opt[1:]), '')) ## FIXME: qqP not handled else: warning("unhandled TCP option " + opt) pkt.payload.options = options # window size if pers[0] == '*': pkt.payload.window = RandShort() elif pers[0].isdigit(): pkt.payload.window = int(pers[0]) elif pers[0][0] == '%': coef = int(pers[0][1:]) pkt.payload.window = coef * RandNum(min=1, max=(2**16 - 1) / coef) elif pers[0][0] == 'T': pkt.payload.window = mtu * int(pers[0][1:]) elif pers[0][0] == 'S': ## needs MSS set MSS = filter(lambda x: x[0] == 'MSS', options) if not filter(lambda x: x[0] == 'MSS', options): raise Scapy_Exception( "TCP window value requires MSS, and MSS option not set") pkt.payload.window = filter(lambda x: x[0] == 'MSS', options)[0][1] * int(pers[0][1:]) else: raise Scapy_Exception('Unhandled window size specification') # ttl pkt.ttl = pers[1] - extrahops # DF flag pkt.flags |= (2 * pers[2]) ## FIXME: ss (packet size) not handled (how ? may be with D quirk ## if present) # Quirks if pers[5] != '.': for qq in pers[5]: ## FIXME: not handled: P, I, X, ! # T handled with the Timestamp option if qq == 'Z': pkt.id = 0 elif qq == 'U': pkt.payload.urgptr = RandShort() elif qq == 'A': pkt.payload.ack = RandInt() elif qq == 'F': if db == p0fo_kdb: pkt.payload.flags |= 0x20 # U else: pkt.payload.flags |= RandChoice(8, 32, 40) #P / U / PU elif qq == 'D' and db != p0fo_kdb: pkt /= conf.raw_layer(load=RandString(random.randint( 1, 10))) # XXX p0fo.fp elif qq == 'Q': pkt.payload.seq = pkt.payload.ack #elif qq == '0': pkt.payload.seq = 0 #if db == p0fr_kdb: # '0' quirk is actually not only for p0fr.fp (see # packet2p0f()) if '0' in pers[5]: pkt.payload.seq = 0 elif pkt.payload.seq == 0: pkt.payload.seq = RandInt() while pkt.underlayer: pkt = pkt.underlayer return pkt
def traceroute_tcp_ipv6(destination, hops=20, resolve=False, sport=RandShort(), dport=80): """ Traceroute (ICMP) to a destination. :param destination: String (IPv4) :param resolve: Boolean (Reverse DNS the IP) :param hops: Number of maximum HOP :param sport: :param dport: :return: Dict or None """ if not destination: return values = [] for i in range(1, hops + 1): try: packet_tcp = IPv6(dst=destination, hlim=i) / TCP( seq=RandInt(), sport=sport, dport=dport) logger.debug(f"TCP packet: {packet_tcp.summary()}") except socket.gaierror: logger.error( f"Cannot create the packet due to resolve: {destination}") return logger.debug("Sending TCP packet") try: response = sr1(packet_tcp, timeout=TIMEOUT, verbose=False, filter="icmp6 or tcp") except Exception as e: logger.error(e) return logger.debug("TCP packet sent") if response: logger.debug(f"TCP response received {response.summary()}") if resolve: ptr = resolve_ip_to_ptr(response.src) else: ptr = None # Scapy get only ICMP result (can be OK or TTL or others) # scapy.layers.inet6.icmp6types -> 129: 'Echo Reply' # scapy.layers.inet6.icmp6types -> 3: 'ICMPv6TimeExceeded' if response.type == 129 or response.type == 3: logger.debug("ICMP 'echo-reply' received") value = { # 'destination': destination 'destination': response.src, 'ptr': ptr, 'ttl': i, 'icmp_type': response.type, # Time in second -> *1000 -> ms 'time': (response.time - packet_tcp.sent_time) * 1000 } values.append(value) else: logger.debug(f"Something received: {response.summary()}") # raise UnknownError() # End of the traceroute # Destination or resolver if response.src == destination: break else: logger.debug(f"Nothing received (within {TIMEOUT} secondes)") values.append({'ttl': i}) return values