def send_probe_req(self, bssid, essid): """Send a probe request to the specified AP""" src = RandMAC() if self.mac is None else self.mac self.logger.info('[!] Sending Broadcast Probe Request: SRC=[%s] -> BSSID: %s ESSID: %s' % (src, bssid, essid)) param = Dot11ProbeReq() essid = Dot11Elt(ID='SSID', info=essid) rates = Dot11Elt(ID='Rates', info="\x03\x12\x96\x18\x24\x30\x48\x60") dsset = Dot11Elt(ID='DSset', info='\x01') pkt = RadioTap() / Dot11(type=0, subtype=4, addr1='ff:ff:ff:ff:ff:ff', addr2=src, addr3='ff:ff:ff:ff:ff:ff') / param / essid / rates / dsset try: sendp(pkt, verbose=0) except: return print ("Probing network '%s (%s)'\n" % (bssid, essid)) try: # Build a probe request packet with a SSID and a WPS information element dst = mac2str(bssid) src = mac2str("ff:ff:ff:ff:ff:ff") packet = Dot11(addr1=dst, addr2=src, addr3=dst) / Dot11ProbeReq() packet = packet / Dot11Elt(ID=0, len=len(essid), info=essid) / Dot11Elt(ID=221, len=9, info="%s\x10\x4a\x00\x01\x10" % self.wps_parser.WPS_ID) # Send it! send(packet, verbose=0) # self.probedNets[bssid] = None except Exception, e: print 'Failure sending probe request to', essid, ':', e
def gen_discover(self): """ Generate DHCP DISCOVER packet. [:rfc:`7844#section-3.1`] :: SHOULD randomize the ordering of options If this can not be implemented MAY order the options by option code number (lowest to highest). [:rfc:`7844#section-3.`] :: MAY contain the Parameter Request List option. """ dhcp_discover = ( self.gen_ether_ip() / self.gen_udp() / self.gen_bootp() / DHCP(options=[ ("message-type", "discover"), ("client_id", mac2str(self.client_mac)), ("param_req_list", self.prl), "end" ]) ) logger.debug('Generated discover %s.', dhcp_discover.summary()) return dhcp_discover
def gen_release(self): """ Generate DHCP release packet (broadcast?). [:rfc:`7844#section-3.`] :: MUST contain the Message Type option and MUST contain the Server Identifier option, .. note:: currently not being used. """ dhcp_release = ( self.gen_ether_ip() / self.gen_udp() / self.gen_bootp() / DHCP(options=[ ("message-type", "release"), ("client_id", mac2str(self.client_mac)), ("server_id", self.server_ip), "end"]) ) logger.debug('Generated release.') logger.debug(dhcp_release.summary()) return dhcp_release
def gen_request(self): """ Generate DHCP REQUEST packet. [:rfc:`7844#section-3.1`] :: SHOULD randomize the ordering of options If this can not be implemented MAY order the options by option code number (lowest to highest). [:rfc:`7844#section-3.`] :: MAY contain the Parameter Request List option. If in response to a DHCPOFFER,:: MUST contain the corresponding Server Identifier option MUST contain the Requested IP address option. If the message is not in response to a DHCPOFFER (BOUND, RENEW),:: MAY contain a Requested IP address option """ dhcp_req = ( self.gen_ether_ip() / self.gen_udp() / self.gen_bootp() / DHCP(options=[("message-type", "request"), ("client_id", mac2str(self.client_mac)), ("param_req_list", self.prl), ("requested_addr", self.lease.address), ("server_id", self.lease.server_id), "end"])) logger.debug('Generated request %s.', dhcp_req.summary()) return dhcp_req
async def send(self, pkt): tx_frame = ArpHdrTransaction() tx_frame.eth_dest_mac = int.from_bytes(mac2str(pkt[Ether].dst), 'big') tx_frame.eth_src_mac = int.from_bytes(mac2str(pkt[Ether].src), 'big') tx_frame.eth_type = pkt[Ether].type tx_frame.arp_htype = pkt[ARP].hwtype tx_frame.arp_ptype = pkt[ARP].ptype tx_frame.arp_hlen = pkt[ARP].hwlen tx_frame.arp_plen = pkt[ARP].plen tx_frame.arp_oper = pkt[ARP].op tx_frame.arp_sha = int.from_bytes(mac2str(pkt[ARP].hwsrc), 'big') tx_frame.arp_spa = atol(pkt[ARP].psrc) tx_frame.arp_tha = int.from_bytes(mac2str(pkt[ARP].hwdst), 'big') tx_frame.arp_tpa = atol(pkt[ARP].pdst) await self.source.send(tx_frame)
def get_if_raw_hwaddr(iff): """Return a tuple containing the link type and the raw hardware address corresponding to the interface 'iff'""" if iff == scapy.arch.LOOPBACK_NAME: return (ARPHDR_LOOPBACK, b'\x00' * 6) # Retrieve interface information try: tmp_intf = dnet.intf().get(iff) link_addr = tmp_intf["link_addr"] except Exception: raise Scapy_Exception("Error in attempting to get hw address" " for interface [%s]" % iff) if hasattr(link_addr, "type"): # Legacy dnet module return link_addr.type, link_addr.data else: # dumbnet module mac = mac2str(str(link_addr)) # Adjust the link type if tmp_intf["type"] == 6: # INTF_TYPE_ETH from dnet return (ARPHDR_ETHER, mac) return (tmp_intf["type"], mac)
def parse_TKIP_hdr(pkt): """Extract TSCs, TA and encoded-data from a packet @pkt""" # Note: FCS bit is not handled assert pkt.FCfield.protected # 802.11i - 8.3.2.2 tkip_layer = pkt[Dot11TKIP] payload = tkip_layer.data # IV if not tkip_layer.ext_iv: # 802.11i p. 46 raise ValueError("Extended IV must be set for TKIP") TSC0 = tkip_layer.TSC0 TSC1 = tkip_layer.TSC1 WEPseed = tkip_layer.WEPSeed # Extended IV TSC2 = tkip_layer.TSC2 TSC3 = tkip_layer.TSC3 TSC4 = tkip_layer.TSC4 TSC5 = tkip_layer.TSC5 # 802.11i p. 46 assert (TSC1 | 0x20) & 0x7f == WEPseed TA = [orb(e) for e in mac2str(pkt.addr2)] TSC = [TSC0, TSC1, TSC2, TSC3, TSC4, TSC5] return TSC, TA, payload
def get_if_raw_hwaddr(iff): """Return a tuple containing the link type and the raw hardware address corresponding to the interface 'iff'""" if iff == scapy.arch.LOOPBACK_NAME: return (ARPHDR_LOOPBACK, b'\x00'*6) # Retrieve interface information try: l = dnet.intf().get(iff) link_addr = l["link_addr"] except: raise Scapy_Exception("Error in attempting to get hw address" " for interface [%s]" % iff) if hasattr(link_addr, "type"): # Legacy dnet module return link_addr.type, link_addr.data else: # dumbnet module mac = mac2str(str(link_addr)) # Adjust the link type if l["type"] == 6: # INTF_TYPE_ETH from dnet return (ARPHDR_ETHER, mac) return (l["type"], mac)
def anonymize(self, value): binary = False if '\x00' in value: value = str(str2mac(value[0:6])) binary = True replacement = self.mac.get_replacement(value) if binary: if replacement != '': replacement = mac2str(replacement) return replacement
def init(self,macAddress_str,ipAddress_str): # Note that scapy uses these fields in network byte order, while # we assume they are in host byte order. macAddress = bytearray(mac2str(macAddress_str)[::-1]) macAddress += b'\x00\x00' ipAddress = inet_aton(ipAddress_str)[::-1] #print(macAddress, ipAddress) self.macAddress_reg.writeBytes(bytes(macAddress)) self.ipAddress_reg.writeBytes(bytes(ipAddress))
def gen_bootp_unicast(self): """Generates BOOTP layer part of unicast DHCP packet. Same comments as in gen_bootp """ bootp = (BOOTP(chaddr=[mac2str(self.client_mac)], xid=self.xid, ciaddr=self.client_ip)) return bootp
def gen_udp_bootp(self): udp_bootp = ( UDP(sport=self.client_port, dport=self.server_port) / # MAY # BOOTP(chaddr=[self.client_mac], xid=self.client_xid) / # 3.4. The presence of "Client hardware address" (chaddr) # is necessary for the proper operation of the DHCP service. BOOTP(chaddr=[mac2str(self.client_mac)]) ) return udp_bootp
def do_hwmp_prep(self, flags, hopcount, ttl, targ_sta, targ_sn, lifetime, metric, orig_sta, orig_sn, targ_ext=None): base_pkt = Dot11(addr1="00:11:22:33:44:55", addr2="00:11:22:33:44:55", addr3="00:11:22:33:44:55") \ / Dot11Action(category="Mesh") base_pkt = base_pkt / Dot11Mesh(mesh_action="HWMP") if targ_ext == None: info = struct.pack("<BBB6sIII6sI", flags, hopcount, ttl, utils.mac2str(targ_sta), targ_sn, lifetime, metric, utils.mac2str(orig_sta), orig_sn) else: info = struct.pack("<BBB6sI6sII6sI", flags, hopcount, ttl, utils.mac2str( targ_sta), targ_sn, utils.mac2str(targ_ext), lifetime, metric, utils.mac2str(orig_sta), orig_sn) pkt = base_pkt / Dot11Elt(ID="PREP", info=info) xml = self.do_tshark_xml(pkt) tree = etree.fromstring(xml) ie = self.expectTagged(tree, "wlan_mgt", "Tag: Path Reply") self.expectField(ie, 'wlan_mgt.tag.number', 'Tag Number: Path Reply (131)', 131) self.expectField(ie, 'wlan.hwmp.flags', 'HWMP Flags: 0x%02X' % flags, flags) self.expectField(ie, 'wlan.hwmp.hopcount', 'HWMP Hop Count: %d' % hopcount, hopcount) self.expectField(ie, 'wlan.hwmp.ttl', 'HWMP TTL: %d' % ttl, ttl) self.expectField(ie, 'wlan.hwmp.targ_sta', 'Target STA Address: ' + targ_sta + ' (' + targ_sta + ')', binascii.hexlify(utils.mac2str(targ_sta))) self.expectField( ie, 'wlan.hwmp.targ_sn', 'Target HWMP Sequence Number: %d' % targ_sn, htonl(targ_sn)) if targ_ext != None: self.expectField(ie, 'wlan.hwmp.targ_ext', 'Target External Address: ' + targ_ext + ' (' + targ_ext + ')', binascii.hexlify(utils.mac2str(targ_ext))) self.expectField(ie, 'wlan.hwmp.lifetime', 'HWMP Lifetime: %d' % lifetime, htonl(lifetime)) self.expectField(ie, 'wlan.hwmp.metric', 'HWMP Metric: %d' % metric, htonl(metric)) self.expectField(ie, 'wlan.hwmp.orig_sta', 'Originator STA Address: ' + orig_sta + ' (' + orig_sta + ')', binascii.hexlify(utils.mac2str(orig_sta))) self.expectField( ie, 'wlan.hwmp.orig_sn', 'HWMP Originator Sequence Number: %d' % orig_sn, htonl(orig_sn))
def gen_bootp_unicast(self): """Generates BOOTP layer part of unicast DHCP packet. Same comments as in gen_bootp """ bootp = ( BOOTP(chaddr=[mac2str(self.client_mac)], xid=self.xid, ciaddr=self.client_ip) ) return bootp
def __init__(self, bd_addr, address_type=AddressType.random): if isinstance(address_type, int): address_type = AddressType(address_type) assert isinstance(bd_addr, str) assert len(bd_addr) >= 6 if len(bd_addr) > 6: bd_addr = mac2str(bd_addr) assert len(bd_addr) == 6 self.bd_addr = bd_addr self.address_type = address_type
def do_hwmp_perr(self, ttl, targs=[]): base_pkt = Dot11(addr1="00:11:22:33:44:55", addr2="00:11:22:33:44:55", addr3="00:11:22:33:44:55") \ / Dot11Action(category="Mesh") base_pkt = base_pkt / Dot11Mesh(mesh_action="HWMP") info = struct.pack("<BB", ttl, len(targs)) for t in targs: if t["flags"] & (1 << 6): info += struct.pack("<B6sI6sH", t["flags"], utils.mac2str(t["addr"]), t["sn"], t["ext"], t["reason"]) else: info += struct.pack("<B6sIH", t["flags"], utils.mac2str(t["addr"]), t["sn"], t["reason"]) pkt = base_pkt / Dot11Elt(ID="PERR", info=info) xml = self.do_tshark_xml(pkt) tree = etree.fromstring(xml) ie = self.expectTagged(tree, "wlan_mgt", "Tag: Path Error") self.expectField(ie, 'wlan_mgt.tag.number', 'Tag Number: Path Error (132)', 132) self.expectField(ie, 'wlan.hwmp.targ_count', 'HWMP Target Count: %d' % len(targs), len(targs)) for t in targs: self.expectField(ie, 'wlan.hwmp.targ_flags', 'HWMP Per-Target Flags: 0x%02X' % t["flags"], t["flags"]) self.expectField( ie, 'wlan.hwmp.targ_sta', 'Target STA Address: ' + t["addr"] + ' (' + t["addr"] + ')', binascii.hexlify(utils.mac2str(t["addr"]))) self.expectField(ie, 'wlan.hwmp.targ_sn', 'Target HWMP Sequence Number: %d' % t["sn"], htonl(t["sn"])) self.expectField(ie, 'wlan_mgt.fixed.reason_code', None, htons(t["reason"]))
def install_unicast_keys(self, client_nonce): """Use the client nonce @client_nonce to compute and install PTK, KCK, KEK, TK, MIC (AP -> STA), MIC (STA -> AP) """ pmk = self.pmk anonce = self.anonce snonce = client_nonce amac = mac2str(self.mac) smac = mac2str(self.client) # Compute PTK self.ptk = customPRF512(pmk, amac, smac, anonce, snonce) # Extract derivated keys self.kck = self.ptk[:16] self.kek = self.ptk[16:32] self.tk = self.ptk[32:48] self.mic_ap_to_sta = self.ptk[48:56] self.mic_sta_to_ap = self.ptk[56:64] # Reset IV self.client_iv = count()
def arpleak(target, plen=255, hwlen=255, **kargs): # type: (str, int, int, **Any) -> Tuple[SndRcvList, PacketList] """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 = {} # type: Dict[str, List[Ether]] 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 dhcpRequest(dhcp_offer, src_mac_random, interface): transaction_id = dhcp_offer[0][BOOTP].xid server_id = dhcp_offer[0][DHCP].options[1][1] requested_addr = dhcp_offer[0][BOOTP].yiaddr print(requested_addr) options = [("message-type", "request"), ("server_id", server_id), ("requested_addr", requested_addr), ("end", "0")] dhcp_request = Ether(dst='ff:ff:ff:ff:ff:ff', src=src_mac_random) \ / IP(src='0.0.0.0', dst='255.255.255.255') \ / UDP(sport=68, dport=67) \ / BOOTP(chaddr=[mac2str(src_mac_random)], xid=transaction_id) \ / DHCP(options=options) sendp(dhcp_request, iface=interface) return requested_addr
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 gen_request_unicast(self): """ Generate DHCP REQUEST unicast packet. Same comments as in gen_request apply. """ dhcp_req = (self.gen_ether_ip_unicast() / self.gen_udp() / self.gen_bootp_unicast() / DHCP(options=[("message-type", "request"), ("client_id", mac2str(self.client_mac)), ("param_req_list", self.prl), "end"])) logger.debug('Generated request %s.', dhcp_req.summary()) return dhcp_req
def check_MIC_ICV(data, mic_key, source, dest): """Check MIC, ICV & return the data from a decrypted TKIP packet""" assert len(data) > 12 # DATA - MIC(DA - SA - Priority=0 - 0 - 0 - 0 - DATA) - ICV # 802.11i p.47 ICV = data[-4:] MIC = data[-12:-4] data_clear = data[:-12] expected_ICV = pack("<I", crc32(data_clear + MIC) & 0xFFFFFFFF) if expected_ICV != ICV: raise ICVError() sa = mac2str(source) # Source MAC da = mac2str(dest) # Dest MAC expected_MIC = michael(mic_key, da + sa + b"\x00" * 4 + data_clear) if expected_MIC != MIC: raise MICError() return data_clear
def gen_bootp(self): """Generates BOOTP layer part of DHCP packet. [ :rfc:`7844#section-3.4` ] :: The presence of this address is necessary for the proper operation of the DHCP service. [:rfc:`7844#section-3.`] :: MAY contain the Client Identifier option, """ bootp = (BOOTP(chaddr=[mac2str(self.client_mac)], xid=self.xid)) return bootp
def persistant(mac_and_ip, dhcp_server_ip, interface): while (True): for i in mac_and_ip: transaction_id = random.randint(1, 900000000) server_id = dhcp_server_ip requested_addr = i[0] options = [("message-type", "request"), ("server_id", server_id), ("requested_addr", requested_addr), ("end", "0")] dhcp_request = Ether(dst='ff:ff:ff:ff:ff:ff', src=i[1]) \ / IP(src=requested_addr, dst='255.255.255.255') \ / UDP(sport=68, dport=67) \ / BOOTP(chaddr=[mac2str(i[1])], xid=transaction_id) \ / DHCP(options=options) sendp(dhcp_request, iface=interface) sleep(120)
def do_hwmp_perr(self, ttl, targs=[]): base_pkt = Dot11(addr1="00:11:22:33:44:55", addr2="00:11:22:33:44:55", addr3="00:11:22:33:44:55") \ / Dot11Action(category="Mesh") base_pkt = base_pkt / Dot11Mesh(mesh_action="HWMP") info = struct.pack("<BB", ttl, len(targs)) for t in targs: if t["flags"] & (1 << 6): info += struct.pack("<B6sI6sH", t["flags"], utils.mac2str(t["addr"]), t["sn"], t["ext"], t["reason"]) else: info += struct.pack("<B6sIH", t["flags"], utils.mac2str(t["addr"]), t["sn"], t["reason"]) pkt = base_pkt / Dot11Elt(ID="PERR", info=info) xml = self.do_tshark_xml(pkt) tree = etree.fromstring(xml) ie = self.expectTagged(tree, "wlan_mgt", "Tag: Path Error") self.expectField(ie, 'wlan_mgt.tag.number', 'Tag Number: Path Error (132)', 132) self.expectField(ie, 'wlan.hwmp.targ_count', 'HWMP Target Count: %d' % len(targs), len(targs)) for t in targs: self.expectField(ie, 'wlan.hwmp.targ_flags', 'HWMP Per-Target Flags: 0x%02X' % t["flags"], t["flags"]) self.expectField(ie, 'wlan.hwmp.targ_sta', 'Target STA Address: ' + t["addr"] + ' (' + t["addr"] + ')', binascii.hexlify(utils.mac2str(t["addr"]))) self.expectField( ie, 'wlan.hwmp.targ_sn', 'Target HWMP Sequence Number: %d' % t["sn"], htonl(t["sn"])) self.expectField(ie, 'wlan_mgt.fixed.reason_code', None, htons(t["reason"]))
def _conv_str_to_val(self, mac_str): """ Convert a given mac string to numeric value. :parameters: mac_str: string String representing mac address. :raises: + :exe:'TRexError': In case of invalid string. :returns: int: mac as numeric value. """ if ':' in mac_str: mac_str = mac2str(mac_str) return mac_str_to_num(mac_str)
def gen_bootp(self): """Generates BOOTP layer part of DHCP packet. [ :rfc:`7844#section-3.4` ] :: The presence of this address is necessary for the proper operation of the DHCP service. [:rfc:`7844#section-3.`] :: MAY contain the Client Identifier option, """ bootp = ( BOOTP(chaddr=[mac2str(self.client_mac)], xid=self.xid) ) return bootp
def build_TKIP_payload(data, iv, mac, tk): """Build a TKIP header for IV @iv and mac @mac, and encrypt @data based on temporal key @tk """ TSC5, TSC4, TSC3, TSC2, TSC1, TSC0 = ((iv >> 40) & 0xFF, (iv >> 32) & 0xFF, (iv >> 24) & 0xFF, (iv >> 16) & 0xFF, (iv >> 8) & 0xFF, iv & 0xFF) bitfield = 1 << 5 # Extended IV TKIP_hdr = chb(TSC1) + chb((TSC1 | 0x20) & 0x7f) + chb(TSC0) + chb( bitfield) # noqa: E501 TKIP_hdr += chb(TSC2) + chb(TSC3) + chb(TSC4) + chb(TSC5) TA = [orb(e) for e in mac2str(mac)] TSC = [TSC0, TSC1, TSC2, TSC3, TSC4, TSC5] TK = [orb(x) for x in tk] rc4_key = gen_TKIP_RC4_key(TSC, TA, TK) return TKIP_hdr + ARC4_encrypt(rc4_key, data)
def master_filter(self, pkt): # the server may probe the offered address with an ICMP Echo Request. return (BOOTP in pkt and pkt[BOOTP].options == dhcpmagic and pkt[BOOTP].chaddr[:6] == mac2str(self.client_mac) and # NOTE: xid not being used. # Any DHCPACK messages that arrive with an 'xid' that does # not match # the 'xid' of the client's DHCPREQUEST message are silently # discarded. # pkt[BOOTP].xid == self.client_xid and pkt[UDP].sport == self.server_port and # FIXME: need to check client port? pkt[UDP].dport == self.client_port # FIXME: only for replies after bound, # this can be done with scapy conf.checkIPaddr: # and pkt[IP].dst == self.client_ip # and pkt[IP].src == self.server_ip )
def discover(): ether_layer = Ether( src=DHCP_CLIENT_MAC_ADDRESS, dst=BROADCAST_MAC_ADDRESS, ) ip_layer = IP( src=DHCP_DISCOVER_HOST_IP_ADDRESS, dst=LIMITED_BROADCAST_IP_ADDRESS, ) udp_layer = UDP( sport=DHCP_CLIENT_PORT, dport=DHCP_SERVER_PORT, ) # BOOTPの引数chaddrについて: # Scapyを使った他の実装を見たところ # (https://github.com/david415/dhcptakeover/blob/master/dhcptakeover.py)、 # scapy.all.get_if_raw_hwaddr()を使っていた # scapy.all.get_if_raw_hwaddr()の中で `mac = mac2str(str(link_addr))` しており # mac2str()関数にて、規則に従いMACアドレスを文字列化してた # コメントに「dumbnet module」とあったので、使用モジュールの関係上、このロジックとなっているのかもしれない chaddr = mac2str(DHCP_CLIENT_MAC_ADDRESS) # なお、単にMACアドレスそのものを渡してもOKだが、その場合には同一のDHCPサーバから複数レスポンスが返ってくる # chaddr = DHCP_CLIENT_MAC_ADDRESS bootp_layer = BOOTP(chaddr=chaddr) dhcp_layer = DHCP(options=[('message-type', 'discover'), 'end']) discover_packet = ether_layer / ip_layer / udp_layer / bootp_layer / dhcp_layer # 作成したパケットを念のため確認 discover_packet.show() # Scapyのドキュメント通りに設定して送信 # http://scapy.readthedocs.io/en/latest/usage.html#identifying-rogue-dhcp-servers-on-your-lan conf.checkIPaddr = False answers, _ = srp(discover_packet, iface=USB_INTERFACE_NAME, multi=True) for send_packet, recv_packet in answers: print 'DHCP Server - MAC: {}, IP: {}'.format(recv_packet[Ether].src, recv_packet[IP].src)
def gen_inform(self): """ Generate DHCP inform packet (unicast). [:rfc:`7844#section-3.`] :: MUST contain the Message Type option, .. note:: currently not being used. """ dhcp_inform = ( self.gen_ether_ip_unicast() / self.gen_udp() / self.gen_bootp_unicast() / DHCP(options=[("message-type", "inform"), ("client_id", mac2str(self.client_mac)), "end"])) logger.debug('Generated inform.') logger.debug(dhcp_inform.summary()) return dhcp_inform
def gen_request_unicast(self): """ Generate DHCP REQUEST unicast packet. Same comments as in gen_request apply. """ dhcp_req = ( self.gen_ether_ip_unicast() / self.gen_udp() / self.gen_bootp_unicast() / DHCP(options=[ ("message-type", "request"), ("client_id", mac2str(self.client_mac)), ("param_req_list", self.prl), "end"]) ) logger.debug('Generated request %s.', dhcp_req.summary()) return dhcp_req
def __init__(self, mac, ip, ap_info): """Create the basic info for an AP. Args: mac: mac address of the client in string format ip: ipv4 address of the client in string format, or None if DHCP ap_info: APInfo of the AP attached to the client """ super().__init__(identifier=mac) # Mandatory parameters if any([p is None for p in (mac, ap_info)]): raise ValueError( "ClientInfo should be instanciated with values for (mac, ap_info)" ) if not isinstance(ap_info, APInfo): raise ValueError("ClientInfo should be instanciated with a APInfo") self.ap_info = ap_info # MAC addresses check check_mac_addr(mac) self.mac_bytes = mac2str(mac) self.mac = mac if ip: # IP address check check_ipv4_addr(ip) self.ip_bytes = socket.inet_aton(ip) self.ip = ip else: self.ip = None self.ip_bytes = None self.name = "Client {} - {}".format(mac, ip) self.got_disconnect = False self.is_associated = False self.seen_arp_reply = False self.state = ClientState.ASSOCIATION self.retries = 0 self.gateway_ip = self.ap_info.gateway_ip
def gen_release(self): """ Generate DHCP release packet (broadcast?). [:rfc:`7844#section-3.`] :: MUST contain the Message Type option and MUST contain the Server Identifier option, .. note:: currently not being used. """ dhcp_release = (self.gen_ether_ip() / self.gen_udp() / self.gen_bootp() / DHCP(options=[("message-type", "release"), ("client_id", mac2str(self.client_mac)), ("server_id", self.server_ip), "end"])) logger.debug('Generated release.') logger.debug(dhcp_release.summary()) return dhcp_release
def _extract_upperaddress(pkt, source=True): """This function extracts the source/destination address of a 6LoWPAN from its upper layer. (Upper layer could be 802.15.4 data, Ethernet...) params: - source: if True, the address is the source one. Otherwise, it is the destination. returns: (upper_address, ipv6_address) """ # https://tools.ietf.org/html/rfc6282#section-3.2.2 SUPPORTED_LAYERS = (Ether, Dot15d4Data) underlayer = pkt.underlayer while underlayer and not isinstance(underlayer, SUPPORTED_LAYERS): underlayer = underlayer.underlayer # Extract and process address if type(underlayer) == Ether: addr = mac2str(underlayer.src if source else underlayer.dst) # https://tools.ietf.org/html/rfc2464#section-4 return LINK_LOCAL_PREFIX[:8] + addr[:3] + b"\xff\xfe" + addr[3:] elif type(underlayer) == Dot15d4Data: addr = underlayer.src_addr if source else underlayer.dest_addr addr = struct.pack(">Q", addr) if underlayer.underlayer.fcf_destaddrmode == 3: # Extended/long tmp_ip = LINK_LOCAL_PREFIX[0:8] + addr # Turn off the bit 7. return tmp_ip[0:8] + struct.pack("B", (orb(tmp_ip[8]) ^ 0x2)) + tmp_ip[9:16] # noqa: E501 elif underlayer.underlayer.fcf_destaddrmode == 2: # Short return ( LINK_LOCAL_PREFIX[0:8] + b"\x00\x00\x00\xff\xfe\x00" + addr[6:] ) else: # Most of the times, it's necessary the IEEE 802.15.4 data to extract # this address, sometimes another layer. warning( 'Unimplemented: Unsupported upper layer: %s' % type(underlayer) ) return b"\x00" * 16
def gen_request(self): """ Generate DHCP REQUEST packet. [:rfc:`7844#section-3.1`] :: SHOULD randomize the ordering of options If this can not be implemented MAY order the options by option code number (lowest to highest). [:rfc:`7844#section-3.`] :: MAY contain the Parameter Request List option. If in response to a DHCPOFFER,:: MUST contain the corresponding Server Identifier option MUST contain the Requested IP address option. If the message is not in response to a DHCPOFFER (BOUND, RENEW),:: MAY contain a Requested IP address option """ dhcp_req = ( self.gen_ether_ip() / self.gen_udp() / self.gen_bootp() / DHCP(options=[ ("message-type", "request"), ("client_id", mac2str(self.client_mac)), ("param_req_list", self.prl), ("requested_addr", self.lease.address), ("server_id", self.lease.server_id), "end"]) ) logger.debug('Generated request %s.', dhcp_req.summary()) return dhcp_req
def gen_discover(self): """ Generate DHCP DISCOVER packet. [:rfc:`7844#section-3.1`] :: SHOULD randomize the ordering of options If this can not be implemented MAY order the options by option code number (lowest to highest). [:rfc:`7844#section-3.`] :: MAY contain the Parameter Request List option. """ dhcp_discover = (self.gen_ether_ip() / self.gen_udp() / self.gen_bootp() / DHCP(options=[("message-type", "discover"), ("client_id", mac2str(self.client_mac)), ("param_req_list", self.prl), "end"])) logger.debug('Generated discover %s.', dhcp_discover.summary()) return dhcp_discover
def gen_inform(self): """ Generate DHCP inform packet (unicast). [:rfc:`7844#section-3.`] :: MUST contain the Message Type option, .. note:: currently not being used. """ dhcp_inform = ( self.gen_ether_ip_unicast() / self.gen_udp() / self.gen_bootp_unicast() / DHCP(options=[ ("message-type", "inform"), ("client_id", mac2str(self.client_mac)), "end"]) ) logger.debug('Generated inform.') logger.debug(dhcp_inform.summary()) return dhcp_inform
# Checking/setting for monitor mode will slow down the process, and the # common is case is not to use monitor mode kw_monitor = kargs.get("monitor", None) if conf.use_npcap and kw_monitor is not None and iface is not None: monitored = iface.ismonitor() if kw_monitor is not monitored: # The monitor param is specified, and not matching the current # interface state iface.setmonitor(kw_monitor) return _orig_open_pcap(iface_pcap_name, *args, **kargs) pcapdnet.open_pcap = open_pcap get_if_raw_hwaddr = pcapdnet.get_if_raw_hwaddr = lambda iface, *args, **kargs: ( # noqa: E501 ARPHDR_ETHER, mac2str(IFACES.dev_from_pcapname(pcapname(iface)).mac)) def _read_routes_c_v1(): """Retrieve Windows routes through a GetIpForwardTable call. This is compatible with XP but won't get IPv6 routes.""" def _extract_ip(obj): return inet_ntop(socket.AF_INET, struct.pack("<I", obj)) routes = [] for route in GetIpForwardTable(): ifIndex = route['ForwardIfIndex'] dest = route['ForwardDest'] netmask = route['ForwardMask'] nexthop = _extract_ip(route['ForwardNextHop'])
def do_hwmp_preq(self, flags, hopcount, ttl, pdid, orig_sta, orig_sn, lifetime, metric, orig_ext=None, targs=[]): base_pkt = Dot11(addr1="00:11:22:33:44:55", addr2="00:11:22:33:44:55", addr3="00:11:22:33:44:55") \ / Dot11Action(category="Mesh") base_pkt = base_pkt / Dot11Mesh(mesh_action="HWMP") if orig_ext == None: info = struct.pack("<BBBI6sIIIB", flags, hopcount, ttl, pdid, utils.mac2str(orig_sta), orig_sn, lifetime, metric, len(targs)) else: info = struct.pack("<BBBI6sI6sIIB", flags, hopcount, ttl, pdid, utils.mac2str(orig_sta), orig_sn, utils.mac2str(orig_ext), lifetime, metric, len(targs)) for t in targs: info += struct.pack("<B6sI", t["flags"], utils.mac2str(t["addr"]), t["sn"]) pkt = base_pkt / Dot11Elt(ID="PREQ", info=info) xml = self.do_tshark_xml(pkt) tree = etree.fromstring(xml) ie = self.expectTagged(tree, "wlan_mgt", "Tag: Path Request") self.expectField(ie, 'wlan_mgt.tag.number', 'Tag Number: Path Request (130)', 130) self.expectField(ie, 'wlan.hwmp.flags', 'HWMP Flags: 0x%02X' % flags, flags) self.expectField(ie, 'wlan.hwmp.hopcount', 'HWMP Hop Count: %d' % hopcount, hopcount) self.expectField(ie, 'wlan.hwmp.ttl', 'HWMP TTL: %d' % ttl, ttl) self.expectField(ie, 'wlan.hwmp.pdid', 'HWMP Path Discovery ID: %d' % pdid, htonl(pdid)) self.expectField(ie, 'wlan.hwmp.orig_sta', 'Originator STA Address: ' + orig_sta + ' (' + orig_sta + ')', binascii.hexlify(utils.mac2str(orig_sta))) self.expectField( ie, 'wlan.hwmp.orig_sn', 'HWMP Originator Sequence Number: %d' % orig_sn, htonl(orig_sn)) if orig_ext != None: self.expectField(ie, 'wlan.hwmp.orig_ext', 'Originator External Address: ' + orig_ext + ' (' + orig_ext + ')', binascii.hexlify(utils.mac2str(orig_ext))) self.expectField(ie, 'wlan.hwmp.lifetime', 'HWMP Lifetime: %d' % lifetime, htonl(lifetime)) self.expectField(ie, 'wlan.hwmp.metric', 'HWMP Metric: %d' % metric, htonl(metric)) self.expectField(ie, 'wlan.hwmp.targ_count', 'HWMP Target Count: %d' % len(targs), len(targs)) for t in targs: self.expectField(ie, 'wlan.hwmp.targ_flags', 'HWMP Per-Target Flags: 0x%02X' % t["flags"], t["flags"]) self.expectField(ie, 'wlan.hwmp.targ_sta', 'Target STA Address: ' + t["addr"] + ' (' + t["addr"] + ')', binascii.hexlify(utils.mac2str(t["addr"]))) self.expectField( ie, 'wlan.hwmp.targ_sn', 'Target HWMP Sequence Number: %d' % t["sn"], htonl(t["sn"]))
def i2m(self, pkt, x): if x is None: return b"\0\0\0\0\0\0" return mac2str(x)[::-1]
def get_if_raw_hwaddr(iface): iface = resolve_iface(iface) return ARPHDR_ETHER, mac2str(iface.mac)
def i2m(self, pkt, x): if x is None: return b"\0\0\0\0\0\0" return mac2str(':'.join(x.split(':')[::-1]))
async def run_test(dut, idle_inserter=None, backpressure_inserter=None): tb = TB(dut) await tb.reset() tb.set_idle_generator(idle_inserter) tb.set_backpressure_generator(backpressure_inserter) local_mac = 'DA:D1:D2:D3:D4:D5' local_ip = '192.168.1.101' gateway_ip = '192.168.1.1' subnet_mask = '255.255.255.0' dut.local_mac <= int.from_bytes(mac2str(local_mac), 'big') dut.local_ip <= atol(local_ip) dut.gateway_ip <= atol(gateway_ip) dut.subnet_mask <= atol(subnet_mask) for k in range(10): await RisingEdge(dut.clk) tb.log.info("test ARP request") eth = Ether(src='5A:51:52:53:54:55', dst='FF:FF:FF:FF:FF:FF') arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=1, hwsrc='5A:51:52:53:54:55', psrc='192.168.1.100', hwdst='00:00:00:00:00:00', pdst='192.168.1.101') test_pkt = eth / arp await tb.send(test_pkt) rx_pkt = await tb.recv() tb.log.info("RX packet: %s", repr(rx_pkt)) assert rx_pkt[Ether].dst.casefold() == test_pkt[Ether].src.casefold() assert rx_pkt[Ether].src.casefold() == local_mac.casefold() assert rx_pkt[Ether].type == test_pkt[Ether].type assert rx_pkt[ARP].hwtype == test_pkt[Ether].hwtype assert rx_pkt[ARP].ptype == test_pkt[Ether].ptype assert rx_pkt[ARP].hwlen == test_pkt[Ether].hwlen assert rx_pkt[ARP].plen == test_pkt[Ether].plen assert rx_pkt[ARP].op == 2 assert rx_pkt[ARP].hwsrc.casefold() == local_mac.casefold() assert rx_pkt[ARP].psrc == local_ip assert rx_pkt[ARP].hwdst.casefold() == test_pkt[ARP].hwsrc.casefold() assert rx_pkt[ARP].pdst == test_pkt[ARP].psrc tb.log.info("Cached read") await tb.arp_req_source.send(ArpReqTransaction(ip=atol('192.168.1.100'))) resp = await tb.arp_resp_sink.recv() tb.log.info("Read value: %s", resp) assert not resp.error assert resp.mac == int.from_bytes(mac2str(test_pkt[Ether].src), 'big') tb.log.info("Uncached read, inside subnet") await tb.arp_req_source.send(ArpReqTransaction(ip=atol('192.168.1.102'))) # wait for ARP request rx_pkt = await tb.recv() tb.log.info("RX packet: %s", repr(rx_pkt)) assert rx_pkt[Ether].dst.casefold() == "ff:ff:ff:ff:ff:ff".casefold() assert rx_pkt[Ether].src.casefold() == local_mac.casefold() assert rx_pkt[Ether].type == 0x0806 assert rx_pkt[ARP].hwtype == 0x0001 assert rx_pkt[ARP].ptype == 0x0800 assert rx_pkt[ARP].hwlen == 6 assert rx_pkt[ARP].plen == 4 assert rx_pkt[ARP].op == 1 assert rx_pkt[ARP].hwsrc.casefold() == local_mac.casefold() assert rx_pkt[ARP].psrc == local_ip assert rx_pkt[ARP].hwdst.casefold() == "00:00:00:00:00:00".casefold() assert rx_pkt[ARP].pdst == '192.168.1.102' # generate response eth = Ether(src='6A:61:62:63:64:65', dst=local_mac) arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, hwsrc='6A:61:62:63:64:65', psrc='192.168.1.102', hwdst=local_mac, pdst=local_ip) test_pkt = eth / arp await tb.send(test_pkt) resp = await tb.arp_resp_sink.recv() tb.log.info("Read value: %s", resp) assert not resp.error assert resp.mac == int.from_bytes(mac2str(test_pkt[Ether].src), 'big') tb.log.info("Uncached read, outside of subnet") await tb.arp_req_source.send(ArpReqTransaction(ip=atol('8.8.8.8'))) # wait for ARP request rx_pkt = await tb.recv() tb.log.info("RX packet: %s", repr(rx_pkt)) assert rx_pkt[Ether].dst.casefold() == "ff:ff:ff:ff:ff:ff".casefold() assert rx_pkt[Ether].src.casefold() == local_mac.casefold() assert rx_pkt[Ether].type == 0x0806 assert rx_pkt[ARP].hwtype == 0x0001 assert rx_pkt[ARP].ptype == 0x0800 assert rx_pkt[ARP].hwlen == 6 assert rx_pkt[ARP].plen == 4 assert rx_pkt[ARP].op == 1 assert rx_pkt[ARP].hwsrc.casefold() == local_mac.casefold() assert rx_pkt[ARP].psrc == local_ip assert rx_pkt[ARP].hwdst.casefold() == "00:00:00:00:00:00".casefold() assert rx_pkt[ARP].pdst == gateway_ip # generate response eth = Ether(src='AA:BB:CC:DD:EE:FF', dst=local_mac) arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, hwsrc='AA:BB:CC:DD:EE:FF', psrc='192.168.1.1', hwdst=local_mac, pdst=local_ip) test_pkt = eth / arp await tb.send(test_pkt) resp = await tb.arp_resp_sink.recv() tb.log.info("Read value: %s", resp) assert not resp.error assert resp.mac == int.from_bytes(mac2str(test_pkt[Ether].src), 'big') tb.log.info("Uncached read, timeout") await tb.arp_req_source.send(ArpReqTransaction(ip=atol('192.168.1.103'))) # wait for ARP request for k in range(4): rx_pkt = await tb.recv() tb.log.info("RX packet: %s", repr(rx_pkt)) assert rx_pkt[Ether].dst.casefold() == "ff:ff:ff:ff:ff:ff".casefold() assert rx_pkt[Ether].src.casefold() == local_mac.casefold() assert rx_pkt[Ether].type == 0x0806 assert rx_pkt[ARP].hwtype == 0x0001 assert rx_pkt[ARP].ptype == 0x0800 assert rx_pkt[ARP].hwlen == 6 assert rx_pkt[ARP].plen == 4 assert rx_pkt[ARP].op == 1 assert rx_pkt[ARP].hwsrc.casefold() == local_mac.casefold() assert rx_pkt[ARP].psrc == local_ip assert rx_pkt[ARP].hwdst.casefold() == "00:00:00:00:00:00".casefold() assert rx_pkt[ARP].pdst == '192.168.1.103' resp = await tb.arp_resp_sink.recv() tb.log.info("Read value: %s", resp) assert resp.error tb.log.info("Broadcast") await tb.arp_req_source.send(ArpReqTransaction(ip=atol('192.168.1.255'))) resp = await tb.arp_resp_sink.recv() tb.log.info("Read value: %s", resp) assert not resp.error assert resp.mac == int.from_bytes(mac2str('FF:FF:FF:FF:FF:FF'), 'big') await tb.arp_req_source.send(ArpReqTransaction(ip=atol('255.255.255.255'))) resp = await tb.arp_resp_sink.recv() tb.log.info("Read value: %s", resp) assert not resp.error assert resp.mac == int.from_bytes(mac2str('FF:FF:FF:FF:FF:FF'), 'big') assert tb.header_sink.empty() assert tb.payload_sink.empty() await RisingEdge(dut.clk) await RisingEdge(dut.clk)