Skip to content

Instantly share code, notes, and snippets.

@tonusoo
Last active January 26, 2024 10:43
Show Gist options
  • Save tonusoo/67aa0400def8e8a2ee00a034a064ffe9 to your computer and use it in GitHub Desktop.
Save tonusoo/67aa0400def8e8a2ee00a034a064ffe9 to your computer and use it in GitHub Desktop.
DHCPv4 client with "Client MAC address" set to 00:00:00:00:00:00
#!/usr/bin/env python3
"""
https://github.com/systemd/systemd/issues/27219
Usage:
# for i in {1..10}; do scapy-dhcp-client.py; done
Received 192.168.11.54/255.255.255.0 from DHCP server 192.168.11.73. Client ID was b"'\xcb\xc1\x1c.\xde\xc4c\xfbz\xff>"
Received 192.168.11.55/255.255.255.0 from DHCP server 192.168.11.73. Client ID was b'\x8f\xf1\x8fb\xfe=\x9a\xf8L\x17B\xc2'
Received 192.168.11.56/255.255.255.0 from DHCP server 192.168.11.73. Client ID was b'\xc6\xd5\xfe\x17L\x11\x99\xc9\xea\x8a\xa5\xac'
Received 192.168.11.57/255.255.255.0 from DHCP server 192.168.11.73. Client ID was b'\x12& s\xa4\xa0\xb2_\xf46n\x87'
Received 192.168.11.58/255.255.255.0 from DHCP server 192.168.11.73. Client ID was b'\x18Y\xfc\xeek\xaa\x87\xa5?L\xder'
Received 192.168.11.59/255.255.255.0 from DHCP server 192.168.11.73. Client ID was b'\x8e[\x15M\xf4O\x96u\xado\x87\x9c'
Received 192.168.11.60/255.255.255.0 from DHCP server 192.168.11.73. Client ID was b'\xbfO\x8c\x93\xadc*\x18U\x01\x1a\xd2'
Received 192.168.11.61/255.255.255.0 from DHCP server 192.168.11.73. Client ID was b'\x99\xf1\x9f\xea&\xab\x01\xea\xa2\xb2\xfc\xba'
Received 192.168.11.62/255.255.255.0 from DHCP server 192.168.11.73. Client ID was b'\xd6\x17V+\x92W\x16\r\xc3\xc1\x8a\xdd'
Received 192.168.11.63/255.255.255.0 from DHCP server 192.168.11.73. Client ID was b'\xc0\xdaB2M\xca\x91\xcef4\\\xac'
#
"""
import random
from scapy.all import conf, get_if_hwaddr, srp1, Ether, IP, UDP, BOOTP, DHCP
# https://scapy.readthedocs.io/en/latest/usage.html#discussion
conf.checkIPaddr = False
def mac_to_bytes(mac_addr: str) -> bytes:
return int(mac_addr.replace(":", ""), 16).to_bytes(6, "big")
nic = "tap3"
src_mac = get_if_hwaddr(nic)
client_id = open("/dev/urandom", "rb").read(12)
client_mac = "00:00:00:00:00:00"
dhcp_discover = (
Ether(
src=src_mac,
dst="ff:ff:ff:ff:ff:ff",
) /
IP(
src="0.0.0.0",
dst="255.255.255.255",
) /
UDP(
sport=68,
dport=67,
) /
BOOTP(
chaddr=mac_to_bytes(client_mac),
xid=random.randint(1, 2**32-1),
) /
DHCP(
options=[
("message-type", "discover"),
("client_id", client_id),
("param_req_list",
[
1, # Subnet Mask
3, # Router
12, # Host Name
15, # Domain Name
6, # Domain name Server
33, # Static Router
121, # Classless Static Router
42, # Network Time Protocol Servers
]
),
"end",
]
)
)
#print(dhcp_discover.display())
dhcp_offer = srp1(dhcp_discover, iface="tap3", verbose=0)
yiaddr = dhcp_offer[BOOTP].yiaddr
siaddr = dhcp_offer[BOOTP].siaddr
xid = dhcp_offer[BOOTP].xid
dhcp_request = (
Ether(
src=src_mac,
dst="ff:ff:ff:ff:ff:ff",
) /
IP(
src="0.0.0.0",
dst="255.255.255.255",
) /
UDP(
sport=68,
dport=67,
) /
BOOTP(
chaddr=mac_to_bytes(client_mac),
xid=xid,
) /
DHCP(
options=[
("message-type", "request"),
("client_id", client_id),
("server_id", siaddr),
("requested_addr", yiaddr),
("hostname", "foo"),
("param_req_list",
[
1, # Subnet Mask
3, # Router
12, # Host Name
15, # Domain Name
6, # Domain name Server
33, # Static Router
121, # Classless Static Router
42, # Network Time Protocol Servers
]
),
"end",
]
)
)
#print(dhcp_request.display())
dhcp_ack = srp1(dhcp_request, iface="tap3", verbose=0)
#print(dhcp_ack.display())
for option in dhcp_ack[DHCP].options:
if option[0] == "server_id":
server_id = option[1]
if option[0] == "subnet_mask":
subnet_mask = option[1]
print(f"Received {dhcp_ack[BOOTP].yiaddr}/{subnet_mask} "
f"from DHCP server {server_id}. Client ID was {client_id}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment