def randval(self): randchoices = [] for p in six.itervalues(self.choices): if hasattr(p, "ASN1_root"): # should be ASN1_Packet class randchoices.append(packet.fuzz(p())) elif hasattr(p, "ASN1_tag"): if isinstance( p, type ): # should be (basic) ASN1F_field class # noqa: E501 randchoices.append(p("dummy", None).randval()) else: # should be ASN1F_PACKET instance randchoices.append(p.randval()) return RandChoice(*randchoices)
def randval(self): # type: () -> RandChoice return RandChoice(True, False)
def randval(self): return RandChoice(True, False)
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