def _dissect(self, buf): # Withdrawn Routes # logger.debug("Dissecting BGP update") off = 4 off_end = off + unpack_H(buf[:2])[0] while off < off_end: rlen = 3 + 0 route = Route(buf[off:]) self.wroutes.append(route) off += rlen # Path attributes off_end = off + unpack_H(buf[2:4])[0] # logger.debug("Unpacking attributes") while off < off_end: alen = 3 + buf[off + 2] # logger.debug("bytes for attribute: %r" % buf[off: off + alen]) attr = BGP.Update.Attribute(buf[off:off + alen]) self.pathattrs.append(attr) off += alen # Announced routes off_end = len(buf) # logger.debug("Unpacking routes") while off + 3 <= off_end: rlen = 3 + 0 # logger.debug("bytes for route: %r" % buf[off:off + rlen]) route = Route(buf[off:off + rlen]) self.anncroutes.append(route) off += rlen # logger.debug("Finished, off=%d off_end=%d" % (off, off_end)) return off
def _dissect(self, buf): # update dynamic header parts. buf: 1010???? -clear reserved-> 1010 -> *4 ol = ((buf[12] >> 4) << 2) - 20 # dataoffset - TCP-standard length if ol > 0: # parse options, add offset-length to standard-length opts_bytes = buf[20:20 + ol] self._init_triggerlist("opts", opts_bytes, self._parse_opts) elif ol < 0: raise Exception("invalid header length") ports = [unpack_H(buf[0:2])[0], unpack_H(buf[2:4])[0]] try: # source or destination port should match # logger.debug("TCP handler: %r" % self._id_handlerclass_dct[TCP]) htype = [x for x in ports if x in self._id_handlerclass_dct[TCP]][0] # logger.debug("TCP: trying to set handler, type: %d = %s" % # (type, self._id_handlerclass_dct[TCP][type])) self._init_handler(htype, buf[20 + ol:]) except: # no type found pass return 20 + ol
def _dissect(self, buf): pnamelen = unpack_H(buf[:2])[0] self.pname = buf[2: 2 + pnamelen] off_clientidlen = 2 + pnamelen + 1 + 1 + 2 clientidlen = unpack_H(buf[off_clientidlen: off_clientidlen + 2])[0] off_clientid = off_clientidlen + 2 self.clientid = buf[off_clientid: off_clientid + clientidlen] return 8 + pnamelen + clientidlen
def _dissect(self, buf): ports = [unpack_H(buf[0:2])[0], unpack_H(buf[2:4])[0]] try: # source or destination port should match htype = [ x for x in ports if x in packetracer.Packet._id_handlerclass_dct[UDP] ][0] self._init_handler(htype, buf[8:]) except: # no type found # logger.debug("could not parse type: %d because: %s" % (type, e)) pass return 8
def fletcher32(data_to_checksum, amount_words): # 1 word = 2 Bytes sum1 = 0xFFFF sum2 = 0xFFFF datapos = 0 while amount_words > 0: tlen = 359 if amount_words > 359 else amount_words amount_words -= tlen while tlen > 0: # sum1 += unpack_word_be(data_to_checksum[datapos:datapos+2])[0] # print("%d" % sum1) sum1 += unpack_H(data_to_checksum[datapos:datapos + 2])[0] datapos += 2 sum2 += sum1 # print("%d" % sum1) # print("%d" % sum2) # print("--") tlen -= 1 sum1 = (sum1 & 0xFFFF) + (sum1 >> 16) sum2 = (sum2 & 0xFFFF) + (sum2 >> 16) # Second reduction step to reduce sums to 16 bits sum1 = (sum1 & 0xFFFF) + (sum1 >> 16) sum2 = (sum2 & 0xFFFF) + (sum2 >> 16) return (sum2 << 16) | sum1
def count_and_dissect_tlvs(buf): """ Count and dissect TLVs. Return length of LLDP layer buf -- buffer to dissect return -- parsed_bytes_total, [(clz, bts), ...] """ shift = 0 tlv_type, tlv_len = 1, 1 clz_bts_list = [] while (tlv_type | tlv_len) != 0: type_and_len = unpack_H(buf[shift:shift + TLV_HEADER_LEN])[0] # get tlv length and type tlv_type = (type_and_len & TYPE_MASK) >> LENGTH_FIELD_BITS tlv_len = type_and_len & LENGTH_MASK if tlv_type != ORG_SPEC_TYPE: clz = LLDP_TLV_CLS.get(tlv_type, LLDPGeneric) else: oui_subtype = unpack_I( buf[shift + TLV_HEADER_LEN:shift + ORG_SPEC_HEADER_LEN + TLV_HEADER_LEN])[0] oui = (oui_subtype & OUI_MASK) >> SUBTYPE_LEN_BITS subtype = oui_subtype & SUBTYPE_MASK clz = LLDP_ORG_SPEC_TLV_CLS.get((oui, subtype), LLDPOrgSpecGeneric) # get body bytes tlv_body = buf[shift:tlv_len + shift + TLV_HEADER_LEN] # update shift to begin of next TLV (TLV_HEADER_LEN:2 + content:x) shift += TLV_HEADER_LEN + tlv_len clz_bts_list.append((clz, tlv_body)) return shift, clz_bts_list
def _dissect(self, buf): if buf[0] == 170: # = 0xAA # SNAP is following ctrl htype = unpack_H(buf[5:7])[0] self._init_handler(htype, buf[8:]) else: # deactivate SNAP self.snap = None return 8
def _dissect(self, buf): name_end = DNS.get_dns_length(buf) self.name = buf[:name_end] # needed set format start = name_end + 8 addr_len = unpack_H(buf[start:start + 2])[0] self.address = buf[start + 2:start + 2 + addr_len] # logger.debug("address: %s" % self.address) return start + 2 + addr_len
def _parse_icmp6opt(buf): opts = [] off = 0 while off < len(buf): optlen = unpack_H(buf[1:3])[0] * 8 opt = ICMP6.ICMPv6Opt(buf[off: off + optlen]) opts.append(opt) off += optlen return opts
def _dissect(self, buf): # logger.debug("Starting to dissect") # self.type/self.subtype use self.framectl, no unpack will happen in dissect so this has # to be done manually self.framectl = unpack_H(buf[0:2])[0] # logger.debug("ieee80211 bytes=%X, type/subtype is=%X/%X, handler=%r" % # (self.framectl, self.type, self.subtype, # packetracer.Packet._id_handlerclass_dct[self.__class__][TYPE_FACTORS[self.type] + self.subtype])) self._init_handler(TYPE_FACTORS[self.type] + self.subtype, buf[4:]) # logger.debug("Finished IEEE dissect") return 4
def __parse_extension(buf): extensions = [] offset = 0 buflen = len(buf) while offset < buflen: ext_content_len = unpack_H(buf[offset + 2:offset + 4])[0] ext_len = 4 + ext_content_len extensions.append(Extension(buf[offset:offset + ext_len])) offset += ext_len return extensions
def _dissect(self, buf): offset = 1 ppp_type = buf[0] if buf[0] & PFC_BIT == 0: ppp_type = unpack_H(buf[:2])[0] offset = 2 self.p.append(buf[0:2]) else: self.p.append(buf[0:1]) self._init_handler(ppp_type, buf[offset:]) return offset
def _dissect(self, buf): # parse chunks chunks = [] off = 12 blen = len(buf) # logger.debug("SCTP: parsing chunks") chunktype = -1 # TODO: use lazy dissect, possible? while off + 4 < blen: dlen = unpack_H(buf[off + 2:off + 4])[0] # check for padding (this should be a data chunk) if off + dlen < blen: self.padding = buf[off + dlen:] # logger.debug("found padding: %s" % self.padding) chunk = Chunk(buf[off:off + dlen]) # logger.debug("SCTP: Chunk; %s " % chunk) chunks.append(chunk) # get payload chunktype from DATA chunks if chunk.type == 0: chunktype = unpack_I(buf[off + chunk.header_len + 8:off + chunk.header_len + 8 + 4])[0] # logger.debug("got DATA chunk, chunktype: %d" % chunktype) # remove data from chunk: use bytes for handler chunk.body_bytes = b"" off += len(chunk) # assume DATA is the last chunk break off += dlen self.chunks.extend(chunks) chunktype = unpack_H(buf[2:4])[0] self._init_handler(chunktype, buf[off:-len(self.padding)]) return off
def __parse_attrs(buf): attributes = [] off = 0 # t:2 l:2 v:x while off < len(buf): l_content = unpack_H(buf[off + 2:off + 4])[0] padding = (4 - (l_content % 4)) % 4 l_total = l_content + padding + 2 + 2 # logger.debug("STUN attr l_content: %d, padding: %d, value: %s" % # (l_content, padding, buf[off : off + l_total])) attributes.append(StunAttr(buf[off:off + l_total])) off += l_total return attributes
def _dissect(self, buf): hlen = 2 opcode = unpack_H(buf[: 2]) # logger.debug("opcode: %d" % opcode) if opcode in OPCODES_DATA_ACK: pass elif opcode in OPCODES_READ_WRITE: self.block = None file, ttype = split_nullbyte(buf[2:], maxsplit=2) # logger.debug("file/ttype = %r / %r" % (file, ttype)) self.file = file + b"\x00" self.ttype = ttype + b"\x00" hlen = 2 + len(self.file) + len(self.ttype) elif opcode == OP_ERR: pass return hlen
def _dissect(self, buf): # logger.debug("parsing SSL") # parse all records out of message # possible types are Client/Sevrer Hello, Change Cipher Spec etc. records = [] offset = 0 dlen = len(buf) # records is the only header so it's ok to avoid lazy dissecting while offset < dlen: record_len = unpack_H(buf[offset + 3:offset + 5])[0] record = Record(buf[offset:offset + 5 + record_len]) records.append(record) offset += 5 + record_len # logger.debug("adding %d records", len(records)) self.records.extend(records) return dlen
def _set_msgtype_full(self, msgtype): self.typeinfo = unpack_H(pack_H_le(msgtype))[0]
def _dissect(self, buf): topiclen = unpack_H(buf[:2])[0] self.topic = buf[2: 2 + topiclen] return 2 + topiclen
def __get_time(self): return [unpack_H(x)[0] for x in self.time]
def _dissect(self, buf): topiclen = unpack_H(buf[2: 4])[0] self.topic = buf[4: 4 + topiclen] return 5 + topiclen
def _dissect(self, buf): hlen = 14 # Ethernet formats: # RFC 894 (Ethernet II) -> type = -> value >1500 # 802.[2,3] (LLC format) -> type = length field -> value <=1500, not supported eth_type = unpack_H(buf[hlen - 2:hlen])[0] # any VLAN tag present? in this case: type field is actually a vlan tag if eth_type in VLAN_TAG_START: # TODO: use _init_triggerlist() if eth_type == ETH_TYPE_8021Q: # logger.debug(">>> got vlan tag") vlan_tag = Dot1Q(buf[12:16]) self.vlan.append(vlan_tag) hlen += 4 # get real higher layer type eth_type = unpack_H(buf[16:18])[0] # 802.1ad: support up to 2 tags (double tagging aka QinQ) else: # logger.debug(">>> got vlan tag") vlan_tag1 = Dot1Q(buf[12:16]) vlan_tag2 = Dot1Q(buf[16:20]) self.vlan.extend([vlan_tag1, vlan_tag2]) hlen += 8 # get real higher layer type eth_type = unpack_H(buf[20:22])[0] # logger.debug("eth type is: %d" % eth_type) # handle ethernet-padding: remove it but save for later use # don't use headers for this because this is a rare situation dlen = len(buf) - hlen # data length [+ padding?] # assume padding only present if len(higher_layer.bin()) <= 46 if dlen <= 46: try: # this will only work on complete headers: Ethernet + IP + ... # handle padding using IPv4, IPv6 etc (min size "eth + ..." = 60 bytes) # logger.debug(">>> checking for padding") if eth_type == ETH_TYPE_IP: dlen_ip = unpack_H(buf[hlen + 2:hlen + 4])[0] # real data length if dlen_ip < dlen: # padding found self._padding = buf[hlen + dlen_ip:] # logger.debug("got padding for IPv4: %r" % self._padding) dlen = dlen_ip # handle padding using IPv6 # IPv6 is a piece of sh$§! payloadlength (in header) = exclusive standard header # but INCLUSIVE options! elif eth_type == ETH_TYPE_IP6: dlen_ip = unpack_H(buf[hlen + 4:hlen + 6])[0] # real data length # logger.debug("eth.hlen=%d, data length based on header: %d" % (hlen, dlen_ip)) if 40 + dlen_ip < dlen: # padding found self._padding = buf[hlen + 40 + dlen_ip:] # logger.debug("got padding for IPv6: %r" % self._padding) dlen = 40 + dlen_ip elif eth_type == ETH_TYPE_LLDP: # this is a bit redundant as we re-parse TLV when accessing the LLDP layer dlen_lldp, _ = lldp.count_and_dissect_tlvs(buf[hlen:]) self._padding = buf[hlen + dlen_lldp:] dlen = dlen_lldp elif eth_type == ETH_TYPE_SP: lacppdu_len = 110 self._padding = buf[hlen + lacppdu_len:] dlen = lacppdu_len except: # Could not extract padding info, assuming incomplete ethernet frame. # Init of handler will take place after all. pass # logger.debug("len(buf)=%d, len(higher)=%d" % (len(buf), dlen)) self._init_handler(eth_type, buf[hlen:hlen + dlen]) return hlen
def _dissect(self, buf): # unpack basic data to get things done quests_amount, ans_amount, authserver_amount, addreq_amount = unpack_HHHH( buf[4:12]) # Sanity check: assume max amount of 50 addresses if quests_amount > 50 or ans_amount > 50 or authserver_amount > 50 or addreq_amount > 50: raise Exception("Adress count too high, invalid packet") off = 12 # TODO: use lazy dissect, dns seems to be too shitty for this # # parse queries # # logger.debug(">>> parsing questions: %d" % quests_amount) while quests_amount > 0 and off < len(buf): # find name by 0-termination q_end = off + DNS.get_dns_length(buf[off:]) + 4 # logger.debug("name is: %s" % buf[off: q_end-4]) # logger.debug("Query is: %s" % buf[off: q_end]) # logger.debug(len(buf[off: q_end])) q = DNS.Query(buf[off:q_end]) q.dns_bytes = buf # logger.debug("query is following..") # logger.debug("Query: %s" % q) # logger.debug("query name format: %s" % q._name_format) self.queries.append(q) off = q_end quests_amount -= 1 # # parse answers # # logger.debug(">>> parsing answers: %d" % ans_amount) while ans_amount > 0 and off < len(buf): # find name by label/0-termination # DNS name:x + type:2 + class:2 + ttl:4 a_end = off + DNS.get_dns_length(buf[off:]) + 2 + 2 + 4 # logger.debug("name is: %s" % buf[off: a_end-8]) dlen = unpack_H(buf[a_end:a_end + 2])[0] # logger.debug("dlen: %d", dlen) # dlen header: 2 + dlen a_end += (2 + dlen) # logger.debug("Answer is: %r" % buf[off: a_end]) a = DNS.Answer(buf[off:a_end]) a.dns_bytes = buf # logger.debug("Answer: %s" % a) self.answers.append(a) off = a_end ans_amount -= 1 # # parse authorative servers # # logger.debug(">>> parsing authorative servers: %d" % authserver_amount) while authserver_amount > 0 and off < len(buf): dlen = unpack_H(buf[off + 10:off + 12])[0] authlen = 12 + dlen # logger.debug("Auth: %r" % buf[off: off + authlen]) a = DNS.Auth(buf[off:off + authlen]) a.dns_bytes = buf # logger.debug("Auth server: %s" % a) self.auths.append(a) off += authlen authserver_amount -= 1 # # parse additional requests # # logger.debug(">>> parsing additional records: %d" % addreq_amount) while addreq_amount > 0 and off < len(buf): if buf[off:off + 3] == b"\x00\x00\x29": a = DNS.AddRecordRoot(buf[off:off + 11]) off += 11 else: # logger.debug(buf[idx:]) # logger.debug(buf[off:]) # logger.debug("data length via: %r" % buf[idx + 9: idx + 11]) dlen = unpack_H(buf[off + 10:off + 10 + 2])[0] # logger.debug("AddRecord: %s" % buf[off: off + 12 + dlen]) a = DNS.AddRecord(buf[off:off + 12 + dlen]) # logger.debug("Additional Record: %s" % a) off += 12 + dlen self.addrecords.append(a) addreq_amount -= 1 # logger.debug("dns: %s" % self) return off
def _dissect(self, buf): htype = unpack_H(buf[14:16])[0] # logger.debug("type: %X" % type) self._init_handler(htype, buf[16:]) return 16
def _get_mvflen_be(self): return unpack_H(pack_H_le(self.mvflen))[0]
def _set_mvflen_be(self, val): self.mvflen = unpack_H(pack_H_le(val))[0]
def _get_msgtype(self): typetmp = self.typeinfo & MASK_MSGTYPE_LE return unpack_H(pack_H_le(typetmp))[0]
def _set_msgtype(self, msgtype): typetmp = unpack_H(pack_H_le(msgtype))[0] self.typeinfo = (self.typeinfo & ~MASK_MSGTYPE_LE) | (typetmp & MASK_MSGTYPE_LE)
def _get_msgtype_full(self): return unpack_H(pack_H_le(self.typeinfo))[0]