def __init__(self, *args, **kw): if 'val' in kw: val = kw['val'] del kw['val'] else: val = None if 'sec' in kw: # used within the NAS LTE EMM stack of corenet sec = kw['sec'] del kw['sec'] else: sec = None Envelope.__init__(self, *args, **kw) self._sec = sec # build a list of (tag length, tag value) for the optional part # configure IE set by **kw as non-transparent and set their value self._opts = [] if val is None: # go faster by just looking for optional IE for ie in self._content: if isinstance(ie, (Type1TV, Type2, Type3TV, Type4TLV, Type6TLVE)): # optional IE T = ie[0] self._opts.append((T.get_bl(), T(), ie)) else: for ie in self._content: if isinstance(ie, (Type1V, Type1TV)): rawtype = integer_types else: rawtype = bytes_types if isinstance( ie, (Type1V, Type3V, Type4LV, Type6LVE)) and ie._name in val: # setting value for non-optional IE if isinstance(val[ie._name], rawtype): # setting raw value ie['V'].set_val(val[ie._name]) else: # setting embedded IE structure ie.set_IE(val=val[ie._name]) elif isinstance(ie, (Type1TV, Type3TV, Type4TLV, Type6TLVE)): # optional IE T = ie[0] self._opts.append((T.get_bl(), T(), ie)) if ie._name in val: ie._trans = False if isinstance(val[ie._name], rawtype): # setting raw value ie['V'].set_val(val[ie._name]) else: # setting embedded IE structure ie.set_IE(val=val[ie._name]) elif isinstance(ie, Type2): # optional Tag-only IE self._opts.append((8, ie[0](), ie)) if ie._name in val: ie._trans = False elif ie._name in val: ie.set_val(val[ie._name])
def _from_char(self, char): if self[0]._name != 'V': # restore the std buffer for handling the value self.unset_IE() # # TODO: investigate the cause to have this dirty patch within some pcaps # and remove it as soon as possible robl, chbl = self[0]._blauto(), char.len_bit() if chbl < robl: log('%s, _from_char: buffer not long enough, requests %i, max %i'\ % (self._name, robl, chbl)) char.append_bytes(b'\x2b' * ((robl - chbl) >> 3)) # Envelope._from_char(self, char) # in case self._IE is defined, use it to decode char instead of V if self.DECODE_INNER and self._IE_stat is not None: if self._IE is None: self._IE = self._IE_stat.clone() iebl = self[-1].get_bl() ccur, clen = char._cur, char._len_bit char._cur -= iebl char._len_bit = char._cur + iebl try: self._IE._from_char(char) except: log('%s, _from_char: unable to decode IE, %s'\ % (self._name, self._IE._name)) else: if char.len_bit() > 0: log('%s, _from_char: uncorrect decoding for IE, %s'\ % (self._name, self._IE._name)) else: # replace V with the IE structure self.replace(self[-1], self._IE) char._cur, char._len_bit = ccur, clen
def _from_char(self, char): Envelope._from_char(self, char) # in case self._IE is defined, use it to decode char instead of V if self._IE is not None: iebl = self[-1].get_bl() char_cur = char._cur char_lb = char._len_bit char._cur -= iebl char._len_bit = char._cur + iebl try: self._IE._from_char(char) except: log('%s, _from_char: unable to decode IE, %s'\ % (self._name, self._IE._name)) else: if char.len_bit() > 0: log('%s, _from_char: uncorrect decoding for IE, %s'\ % (self._name, self._IE._name)) else: # save the V buffer self._V = self[-1] # replace it with the IE structure self.replace(self[-1], self._IE) if self[-2]._name == 'L': # Type4 and Type6 self[-2].set_valauto(self[-1].get_len) char._cur = char_cur char._len_bit = char_lb
def __init__(self, *args, **kwargs): Envelope.__init__(self, *args, **kwargs) if 'val' not in kwargs or 'off' not in kwargs['val']: self['off'].set_valauto(lambda: 5 + (self['opt'].get_len() >> 2)) self['cs'].set_valauto(lambda: self.checksum()) self['opt'].set_blauto(lambda: max(0, (self['off'].get_val() - 5) << 5))
def handle_ul(self, ipbuf): # check if we have a TCP SYN ip_proto, ip_pay = ord(ipbuf[9:10]), ipbuf[20:] if ip_proto != 6: # not TCP return if ip_pay[13:14] != b'\x02': # not SYN return # build the TCP SYN-ACK: invert src / dst ports, seq num (random), # ack num (SYN seq num + 1) tcpsrc, tcpdst, seq = unpack('!HHI', ip_pay[:8]) tcp_synack = TCP(val={ 'seq': randint(1, 4294967295), 'ack': (1 + seq) % 4294967296, 'src': tcpdst, 'dst': tcpsrc, 'SYN': 1, 'ACK': 1, 'win': 0x1000 }, hier=1) # build the IPv4 header: invert src / dst addr ipsrc, ipdst = inet_ntoa(ipbuf[12:16]), inet_ntoa(ipbuf[16:20]) iphdr = IPv4(val={'src': ipdst, 'dst': ipsrc}, hier=0) # pkt = Envelope('p', GEN=(iphdr, tcp_synack)) # send back the TCP SYN-ACK self.GTPUd.transfer_to_int(pkt.to_bytes())
def _from_char(self, char): if self[-1]._name != 'V': # restore the std buffer for handling the value self.unset_IE() Envelope._from_char(self, char) # in case self._IE is defined, use it to decode char instead of V if self.DECODE_INNER and self._IE_stat is not None: if self._IE is None: self._IE = self._IE_stat.clone() iebl = self[-1].get_bl() ccur, clen = char._cur, char._len_bit char._cur -= iebl char._len_bit = char._cur + iebl try: self._IE._from_char(char) except: log('%s, _from_char: unable to decode IE, %s'\ % (self._name, self._IE._name)) else: if char.len_bit() > 0: log('%s, _from_char: uncorrect decoding for IE, %s'\ % (self._name, self._IE._name)) else: # replace V with the IE structure self.replace(self[-1], self._IE) char._cur, char._len_bit = ccur, clen
def set_val(self, vals): if isinstance(vals, dict) and 'Type' in vals: type = vals['Type'] del vals['Type'] self.encode(type, **vals) else: Envelope.set_val(self, vals)
def _from_char(self, char): # in case some optional IE are set (with transparency enabled) # they are decoded as much as the char buffer allows it # 1) decode mandatory part Envelope._from_char(self, char) # 2) decode optional part opts = self._opts[:] while char.len_bit() >= 8: T4, T8, dec = char.to_uint(4), char.to_uint(8), False for i, opt in enumerate(opts): # check the list of optional IEs in order # opt[0] is the tag length: 4 or 8 # opt[1] is the tag value: 0 <= T <= 255 if (opt[0] == 4 and opt[1] == T4) or opt[1] == T8: opt[2]._trans = False opt[2]._from_char(char) dec = True del opts[i] break if not dec: # unknown IEI if self.DEC_BREAK_ON_UNK_IE: log('%s, unknown IE remaining, not decoded' % self._name) break else: char._cur += 8 self._dec_unk_ie(T8, char)
def __init__(self, *args, **kwargs): Envelope.__init__(self, *args, **kwargs) self[2].set_valauto(self._set_hwsz_val) self[3].set_valauto(self._set_protsz_val) self[5].set_blauto(self._set_addrmac_bl) self[7].set_blauto(self._set_addrmac_bl) self[6].set_blauto(self._set_addr_bl) self[8].set_blauto(self._set_addr_bl)
def __init__(self, *args, **kw): if 'IE' in kw: if isinstance(kw['IE'], (Element, CSN1Obj)): self._IE = kw['IE'].clone() elif self._SAFE_STAT: raise(PycrateErr('IE [__init__]: IE type is {0}, expecting Element'\ .format(type(kw['IE']).__name__))) Envelope.__init__(self, *args, **kw)
def __init__(self, *args, **kwargs): if 'excl' in kwargs: self._excl = kwargs['excl'] del kwargs['excl'] Envelope.__init__(self, *args, **kwargs) self[0].set_valauto( lambda: sum([e.get_bl() for i, e in enumerate(self.get_env()._content) \ if i not in self._excl])>>3 )
def _from_char(self, char): Envelope._from_char(self, char) opts_buf = self[18].get_val() if opts_buf: opts = IPv4Options() opts.from_bytes(opts_buf) if opts.to_bytes() == opts_buf: self.replace(self[18], opts)
def __init__(self, *args, **kwargs): Envelope.__init__(self, *args, **kwargs) self[1].set_transauto(self._set_cs4_trans) self[1].set_dicauto(self._set_cs4_dic) self[2].set_transauto(self._set_cs2_trans) self[2].set_dicauto(self._set_cs2_dic) self[3].set_transauto(self._set_cs2_trans) self[3].set_dicauto(self._set_cla_dic)
def _from_char(self, char): l = char.len_bit() if l <= 32: # disable all elements after bit l self.disable_from(l) elif l > 32: # enables some spare bits at the end self[-1]._bl = l-32 Envelope._from_char(self, char)
def __init__(self, *args, **kw): if 'IE' in kw: if isinstance(kw['IE'], (Element, CSN1Obj)): self._IE_stat = kw['IE'] elif self._SAFE_STAT: raise(PycrateErr('IE [__init__]: IE type is {0}, expecting Element'\ .format(type(kw['IE']).__name__))) del kw['IE'] Envelope.__init__(self, *args, **kw) if self[-1]._name == 'V': self._V = self[-1]
def __init__(self, *args, **kwargs): Envelope.__init__(self, *args, **kwargs) # manage single / hopping channel conditional fields self[4].set_transauto(lambda: True if self[3].get_val() == 1 else False) self[5].set_transauto(lambda: True if self[3].get_val() == 1 else False) self[6].set_transauto(lambda: True if self[3].get_val() == 0 else False) self[7].set_transauto(lambda: True if self[3].get_val() == 0 else False)
class ChanDesc3(Envelope): _GEN = (Uint('TSC', bl=3), Uint('HopChan', bl=1, dic=ChanDescHop_dict), Alt(GEN={ 0: Envelope('ChanSingle', GEN=(Uint('spare', bl=2, rep=REPR_HEX), Uint('ARFCN', bl=10))), 1: Envelope('ChanHopping', GEN=(Uint('MAIO', bl=6), Uint('HSN', bl=6))) }, sel=lambda self: self.get_env()[1].get_val()))
def __init__(self, *args, **kw): if 'val' in kw: val = kw['val'] del kw['val'] else: val = None if 'sec' in kw: # used within the NAS LTE EMM stack of corenet sec = kw['sec'] del kw['sec'] else: sec = None Envelope.__init__(self, *args, **kw) self._sec = sec # build a list of (tag length, tag value) for the optional part # configure IE set by **kw as non-transparent and set their value self._opts, self._rest = [], None if val is None: # go faster by just looking for optional IE for ie in self._content: if isinstance(ie, (Type1TV, Type2, Type3TV, Type4TLV, Type6TLVE)): # optional IE T = ie[0] self._opts.append((T.get_bl(), T(), ie)) elif isinstance(ie, RestOctets): # rest octets self._rest = ie else: for ie in self._content: if isinstance( ie, (Type1V, Type3V, Type4LV, Type6LVE)) and ie._name in val: # setting value for non-optional IE ie.set_val({'V': val[ie._name]}) elif isinstance(ie, (Type1TV, Type3TV, Type4TLV, Type6TLVE)): # optional IE T = ie[0] self._opts.append((T.get_bl(), T(), ie)) if ie._name in val: ie._trans = False ie.set_val({'V': val[ie._name]}) elif isinstance(ie, Type2): # optional Tag-only IE self._opts.append((8, ie[0](), ie)) if ie._name in val: ie._trans = False elif isinstance(ie, RestOctets): self._rest = ie elif ie._name in val: ie.set_val(val[ie._name])
class GroupChanDesc(Envelope): _GEN = (Uint('ChanType', bl=5, dic=ChanDescType_dict), Uint('TN', bl=3), Uint('TSC', bl=3), Uint('HopChan', bl=1, dic=ChanDescHop_dict), Alt(GEN={ 0: Envelope('ChanSingle', GEN=(Uint('spare', bl=2, rep=REPR_HEX), Uint('ARFCN', bl=10))), 1: Envelope('ChanHopping', GEN=(Uint('MAIO', bl=6), Uint('HSN', bl=6))) }, sel=lambda self: self.get_env()[3].get_val()), BitMap('MobileAllocChan'))
class BARange(Envelope): _GEN = (Uint8('Num'), Array('Ranges', GEN=Envelope('Range', GEN=(Uint('RANGE_LOWER', bl=10), Uint('RANGE_HIGHER', bl=10)))), Buf('spare', rep=REPR_HEX))
def __init__(self, *args, **kwargs): # enable to pass IPv4 addr in human-readable format if 'val' in kwargs: if 'src' in kwargs['val'] and len(kwargs['val']['src']) != 16: try: kwargs['val']['src'] = inet_pton(AF_INET6, kwargs['val']['src']) except: pass if 'dst' in kwargs['val'] and len(kwargs['val']['dst']) != 16: try: kwargs['val']['dst'] = inet_pton(AF_INET6, kwargs['val']['dst']) except: pass Envelope.__init__(self, *args, **kwargs) if 'val' not in kwargs or 'plen' not in kwargs['val']: self[3].set_valauto(self._set_plen_val) if 'val' not in kwargs or 'next' not in kwargs['val']: self[4].set_valauto(self._set_next_val)
def encode(self, type, **kwargs): """sets the 5GS mobile identity with given type The given types correspond to the following classes: FGSIDTYPE_NO (0) -> FGSIDNone FGSIDTYPE_SUPI (1) -> FGSIDSUPI FGSIDTYPE_GUTI (2) -> FGSIDGUTI FGSIDTYPE_IMEI (3) -> FGSIDDigit FGSIDTYPE_TMSI (4) -> FGSIDTMSI FGSIDTYPE_IMEISV (5) -> FGSIDDigit FGSIDTYPE_MAC (6) -> FGSIDMAC 7 (undefined) -> FGSIDUnk """ if not isinstance(type, integer_types) or not 0 <= type <= 7: raise(PycrateErr('invalid 5GS identity type: %r' % type)) # set the appropriate content self._set_content(type) # pass the value to encode Envelope.set_val(self, kwargs)
def __init__(self, *args, **kwargs): # enable to pass IPv4 addr in human-readable format if 'val' in kwargs: if 'src' in kwargs['val'] and len(kwargs['val']['src']) > 4: try: kwargs['val']['src'] = inet_aton(kwargs['val']['src']) except: pass if 'dst' in kwargs['val'] and len(kwargs['val']['dst']) > 4: try: kwargs['val']['dst'] = inet_aton(kwargs['val']['dst']) except: pass Envelope.__init__(self, *args, **kwargs) self[1].set_valauto(self._set_hdrwlen_val) if 'val' not in kwargs or 'len' not in kwargs['val']: self[7].set_valauto(self._set_len_val) if 'val' not in kwargs or 'proto' not in kwargs['val']: self[14].set_valauto(self._set_prot_val) self[15].set_valauto(self.checksum) self[18].set_blauto(self._set_opt_bl)
def _from_char(self, char): # in case some optional IE are set (with transparency enabled) # they are decoded as much as the char buffer allows it # 1) decode mandatory part Envelope._from_char(self, char) # 2) decode optional part opts = self._opts[:] while char.len_bit() >= 8: T4, T8, dec = char.to_uint(4), char.to_uint(8), False for i, opt in enumerate(opts): # check the list of optional IEs in order if opt[1] in (T4, T8): opt[2]._trans = False opt[2]._from_char(char) dec = True del opts[i] break if not dec: # unknown IEI char._cur += 8 self._dec_unk_ie(T8, char)
def set_val(self, vals): ti, disp = None, True if isinstance(vals, integer_types): ti = vals disp = False elif isinstance(vals, dict) and 'TI' in vals: ti = vals['TI'] if ti is not None: if 0 <= ti < 7: self[1].set_val(ti) self[3].set_trans(True) self[4].set_trans(True) self[4].set_val(None) elif ti < 128: # extended self[1].set_val(7) self[3].set_trans(False) self[4].set_trans(False) self[4].set_val(ti) if disp: Envelope.set_val(self, vals)
def __init__(self, *args, **kwargs): if 'val' in kwargs: # enable to pass IPv4 addr in human-readable format and convert them if 'src' in kwargs['val'] and len(kwargs['val']['src']) > 4: try: kwargs['val']['src'] = inet_aton(kwargs['val']['src']) except Exception: pass if 'dst' in kwargs['val'] and len(kwargs['val']['dst']) > 4: try: kwargs['val']['dst'] = inet_aton(kwargs['val']['dst']) except Exception: pass Envelope.__init__(self, *args, **kwargs) self['hdr_wlen'].set_valauto(lambda: 5 + (self['opt'].get_len()>>2)) if 'val' not in kwargs or 'len' not in kwargs['val']: self['len'].set_valauto(lambda: self._len_val()) if 'val' not in kwargs or 'proto' not in kwargs['val']: self['proto'].set_valauto(lambda: self._proto_val()) self['hdr_cs'].set_valauto(lambda: checksum(self[:15].to_bytes() + b'\0\0' + self[16:].to_bytes())) self['opt'].set_blauto(lambda: max(0, (self['hdr_wlen'].get_val()-5)<<5))
def handle_ul(self, ipbuf): # check if we have an UDP/53 request ip_proto, (udpsrc, udpdst) = ord(ipbuf[9]), unpack('!HH', ipbuf[20:24]) if ip_proto != 17: # not UDP return if udpdst != 53: # not DNS return # build the UDP / DNS response: invert src / dst UDP ports if self.UDP_CS: udp = UDP(val={'src': udpdst, 'dst': udpsrc}, hier=1) else: udp = UDP(val={'src': udpdst, 'dst': udpsrc, 'cs': 0}, hier=1) # DNS request: transaction id, flags, questions, queries dnsreq = ipbuf[28:] transac_id, questions, queries = dnsreq[0:2], \ unpack('!H', dnsreq[4:6])[0], \ dnsreq[12:] if questions > 1: # not supported self._log('WNG', '%i questions, unsupported' % questions) # DNS response: transaction id, flags, questions, answer RRs, # author RRs, add RRs, queries, answers, autor nameservers, add records if self.RAND: ip_resp = _urandom(4) else: ip_resp = inet_aton(self.IP_RESP) dnsresp = b''.join( (transac_id, b'\x81\x80\0\x01\0\x01\0\0\0\0', queries, b'\xc0\x0c\0\x01\0\x01\0\0\0\x20\0\x04', ip_resp)) # build the IPv4 header: invert src / dst addr ipsrc, ipdst = inet_ntoa(ipbuf[12:16]), inet_ntoa(ipbuf[16:20]) iphdr = IPv4(val={'src': ipdst, 'dst': ipsrc}, hier=0) # pkt = Envelope('p', GEN=(iphdr, udp, Buf('dns', val=dnsresp, hier=2))) # send back the DNS response self.GTPUd.transfer_to_int(pkt.to_bytes())
def __init__(self, *args, **kwargs): Envelope.__init__(self, *args, **kwargs) self[2].set_valauto(self._set_type_val)
def __init__(self, *args, **kwargs): Envelope.__init__(self, *args, **kwargs) if 'val' not in kwargs or 'off' not in kwargs['val']: self[4].set_valauto(self._set_off_val) self[16].set_valauto(self.checksum) self[18].set_blauto(self._set_opt_bl)
def __init__(self, *args, **kwargs): Envelope.__init__(self, *args, **kwargs) if 'val' not in kwargs or 'len' not in kwargs['val']: self[2].set_valauto(self._set_len_val) self[3].set_valauto(self.checksum)