- ▸ A network adapter (Ethernet or WiFi)
- ▸ Root privileges:
sudoor run VANTA as root
set interface eth0 set mode random run
- • Easy: random, restore, show
- • Medium: set_vendor, clone_target
- • Advanced: persist (survives reboot via systemd hook)
Overview
What mac_spoof does
mac_spoof is VANTA's network anonymity module. It manages background MAC address rotation daemons - one per interface - that continuously change the hardware address at a configurable interval. When stopped, each daemon restores the original vendor MAC automatically, leaving no trace of spoofing in the interface state.
Unlike simple one-shot MAC changers, mac_spoof uses a persistent process model with state files so you can check, pause, and resume spoofing across VANTA sessions without losing track of original addresses.
~/.vanta/mac_spoof/. Survives shell restarts. Stop any time and restore cleanly.02:00:00:xx:xx:xx - locally-administered unicast prefix avoids vendor OUI conflicts and DHCP weirdness.Quick Start
Running mac_spoof
mac_spoof requires root. Run VANTA with sudo or use sudo VANTA.
# Start spoofing wlan0 (default 0.5s interval)
sudo VANTA
vanta ❯ use mac_spoof
VANTA (mac_spoof) ❯ set iface wlan0
VANTA (mac_spoof) ❯ run target
# Check status
VANTA (mac_spoof) ❯ set action status
VANTA (mac_spoof) ❯ run target
# Stop and restore original MAC
VANTA (mac_spoof) ❯ set action stop
VANTA (mac_spoof) ❯ run target
Spoof all UP interfaces
VANTA (mac_spoof) ❯ set all_up true
VANTA (mac_spoof) ❯ run target
Dry run preview
VANTA (mac_spoof) ❯ set iface eth0,wlan0
VANTA (mac_spoof) ❯ set dry_run true
VANTA (mac_spoof) ❯ run target # shows plan without executing
Reference
Actions
The action parameter controls what mac_spoof does when run is called.
vendor param to apple, samsung, intel, cisco, or dell. Uses a real OUI prefix from that vendor's registered range.ethtool -P if no state file exists.set action stop on next boot - the state file still holds the original MAC and will restore it correctly.
Reference
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
iface |
string | — | Interface name or comma-separated list. E.g. wlan0 or eth0,wlan0. Required if all_up is false. |
all_up |
boolean | false | Auto-select all non-loopback interfaces that are currently UP. Takes precedence over iface. |
action |
string | start | Operation to perform: start, stop, status, vendor, restore, or history. |
interval |
number | 0.5 | Seconds between MAC address changes. Range: 0.1–60. Use 5+ for stable connections. |
dry_run |
boolean | false | Preview all actions without executing. Prints what would change and what original MACs would be saved. |
vendor |
string | — | Vendor name for the vendor action: apple, samsung, intel, cisco, dell |
stealth |
boolean | false | Only rotate on disconnect events instead of a fixed interval. |
persistent |
boolean | false | Write a systemd user service so the daemon starts automatically on login. |
How It Works
Process internals
Understanding the daemon lifecycle helps when debugging or integrating mac_spoof into scripts.
Daemon startup
ip link show <iface> and writes it to ~/.vanta/mac_spoof/<iface>.json along with the process PID and start timestamp. This happens before any changes are made.os.fork(), creates a new session with os.setsid(), and redirects stdin/stdout/stderr to /dev/null. The parent exits immediately - VANTA returns control to the user.ip link set <iface> down → ip link set <iface> address <mac> → ip link set <iface> up → sleep(interval). Each change takes ~100ms during which the interface is briefly down.stop action triggers via os.kill(pid, signal.SIGTERM).State file structure
State files live at ~/.vanta/mac_spoof/<iface>.json. The status action reads these to report on running daemons.
{
"interface": "wlan0",
"pid": 12345,
"original_mac": "aa:bb:cc:dd:ee:ff",
"started": 1696512345.678
}
How ip link is used
# Bring interface down before MAC change (required by most drivers)
ip link set wlan0 down
# Apply new randomly-generated MAC
ip link set wlan0 address 02:00:00:1a:2b:3c
# Bring back up - DHCP client reconnects automatically
ip link set wlan0 up
MAC Address
Generated MAC format
All generated MACs use the locally-administered unicast format:
| Octets | Value | Why |
|---|---|---|
| Octet 1 | 02 | Bit 1 set → locally administered. Bit 0 clear → unicast (not multicast). |
| Octets 2–3 | 00:00 | Consistent prefix - makes it easy to identify spoofed addresses in logs or Wireshark captures. |
| Octets 4–6 | random | 3 bytes of cryptographically random data - 16.7 million unique values per rotation cycle. |
Example: 02:00:00:1a:2b:3c
iface script - mac_spoof's built-in format prioritises avoiding conflicts over fingerprint evasion.
Detection risk
| Detection vector | Risk | Notes |
|---|---|---|
| ARP cache churn | Medium | Rapid ARP announcement pattern is unusual |
| OUI mismatch | High | 02:00:00 prefix is not a real vendor - obvious to any network scanner |
| DHCP request storm | Medium | Each MAC change triggers a new DHCP request on most systems |
| Switch port security | High | Managed switches with MAC-limit policies will trigger port shutdown |
| WiFi re-association | Low | 802.11 association uses the MAC - spoofing while connected causes brief disconnection only |
Vendor Spoofing
Vendor Spoofing
The built-in 02:00:00 prefix is easy to spot. Any network scanner or IDS that checks OUI databases will flag it immediately as locally-administered and not tied to any hardware manufacturer. Vendor spoofing replaces that prefix with a real OUI from Apple, Samsung, Intel, Cisco, or Dell, so the address looks like a legitimate device on the segment.
The first three octets come from that vendor's registered OUI range. The last three octets are random, the same as the locally-administered mode. The result passes a basic OUI lookup and blends into device pools common on most enterprise or consumer networks.
Detection risk comparison
| Detection vector | Locally-administered | Vendor-spoofed |
|---|---|---|
| OUI database lookup | Instant flag: 02:00:00 is not a real vendor | Passes: OUI matches a known manufacturer |
| Wireshark / passive capture | Labeled "Locally Administered" | Labeled with vendor name |
| 802.1X / NAC | High suspicion | Lower suspicion, still fingerprinted by other signals |
| ARP cache churn | Medium: rapid changes are unusual | Medium: same churn pattern applies |
| DHCP fingerprinting | OS/stack still visible | OS/stack still visible |
Usage
sudo VANTA
use mac_spoof
set iface wlan0
set action vendor
set vendor apple
run target
# rotate continuously with Apple OUIs
set action start
set vendor apple
set interval 60
run target
Persistence
Persistence
Setting persistent true makes mac_spoof write a systemd user service file at ~/.config/systemd/user/mac_spoof_<iface>.service, then enables and starts it with systemctl --user. The daemon will start automatically when you log in without any extra steps.
The service file is scoped to your user session. It does not require writing to system-level systemd directories, but the daemon itself still needs root for ip link operations, so the service runs with sudo internally.
Setup
sudo VANTA
use mac_spoof
set iface wlan0
set vendor apple
set interval 60
set persistent true
run target
# Verify the service is active
systemctl --user status mac_spoof_wlan0
Disable persistence
# Stop and disable the service
systemctl --user stop mac_spoof_wlan0
systemctl --user disable mac_spoof_wlan0
# Remove the unit file
rm ~/.config/systemd/user/mac_spoof_wlan0.service
systemctl --user daemon-reload
Usage
Examples
Single interface, fast rotation
sudo VANTA
vanta ❯ use mac_spoof
VANTA (mac_spoof) ❯ set iface wlan0
VANTA (mac_spoof) ❯ run target
# Output
[+] Started spoofer for wlan0 (pid 12345, interval 0.5s)
[+] Original MAC: aa:bb:cc:dd:ee:ff → saved
Multiple interfaces simultaneously
VANTA (mac_spoof) ❯ set iface eth0,wlan0
VANTA (mac_spoof) ❯ set interval 2.0
VANTA (mac_spoof) ❯ run target
All UP interfaces - one command
VANTA (mac_spoof) ❯ set all_up true
VANTA (mac_spoof) ❯ run target
Status check
VANTA (mac_spoof) ❯ set action status
VANTA (mac_spoof) ❯ set all_up true
VANTA (mac_spoof) ❯ run target
# JSON output per interface
{
"interface": "wlan0",
"running": true,
"pid": 12345,
"original_mac": "aa:bb:cc:dd:ee:ff",
"current_mac": "02:00:00:1a:2b:3c",
"uptime_seconds": 120
}
Stop and restore original MAC
VANTA (mac_spoof) ❯ set action stop
VANTA (mac_spoof) ❯ set iface wlan0
VANTA (mac_spoof) ❯ run target
# Restores aa:bb:cc:dd:ee:ff, removes state file
Slower interval for stable WiFi
VANTA (mac_spoof) ❯ set iface wlan0
VANTA (mac_spoof) ❯ set interval 5.0 # 5 seconds - keeps connection alive longer
VANTA (mac_spoof) ❯ run target
Vendor spoof - one-shot
VANTA (mac_spoof) ❯ set iface wlan0
VANTA (mac_spoof) ❯ set action vendor
VANTA (mac_spoof) ❯ set vendor samsung
VANTA (mac_spoof) ❯ run target
# Output
[+] wlan0 MAC set to 04:18:d6:3a:7f:c2 (Samsung OUI)
Restore original MAC without stopping daemon
VANTA (mac_spoof) ❯ set action restore
VANTA (mac_spoof) ❯ set iface wlan0
VANTA (mac_spoof) ❯ run target
# If no state file: falls back to ethtool -P to read the permanent address
Rotation history
VANTA (mac_spoof) ❯ set action history
VANTA (mac_spoof) ❯ set iface wlan0
VANTA (mac_spoof) ❯ run target
# Output - one entry per rotation
2026-05-04 12:01:03 02:00:00:1a:2b:3c trigger=interval
2026-05-04 12:01:33 02:00:00:4d:5e:6f trigger=interval
2026-05-04 12:02:05 04:18:d6:3a:7f:c2 trigger=vendor
Troubleshooting
Common issues
Root privileges required
# Run VANTA with sudo
sudo VANTA
Interface goes down and stays down
# Some drivers need a manual bring-up after MAC change
sudo ip link set wlan0 up
# Increase interval to give driver time to recover
VANTA (mac_spoof) ❯ set interval 5.0
Daemon died unexpectedly
# Check kernel messages for driver errors
dmesg | tail -20
journalctl -n 50
# Check if process is still alive
cat ~/.vanta/mac_spoof/wlan0.json # read the PID
ps -p <pid>
Manual cleanup if state is corrupted
# Kill any stray processes
pkill -f mac_spoof.py
# Remove state files
rm -rf ~/.vanta/mac_spoof/*.json
# Manually restore original MAC
sudo ip link set wlan0 down
sudo ip link set wlan0 address AA:BB:CC:DD:EE:FF
sudo ip link set wlan0 up
Real-time monitoring
# Watch MAC changes live
watch -n 1 'ip link show wlan0 | grep link/ether'
# Check NetworkManager logs
journalctl -u NetworkManager -f
MAC Address Internals
What is a MAC address? A Media Access Control address is a 48-bit (6-byte) identifier assigned to every network interface card (NIC) by its manufacturer. It operates at Layer 2 (Data Link layer) — the layer responsible for transferring frames between two directly connected nodes. Unlike IP addresses (Layer 3), MAC addresses are not routed across the internet — they stay within a single broadcast domain (your LAN or Wi-Fi network). Every frame your computer sends includes your MAC address as the source, making it a key identifier for network access control systems (802.1X, DHCP fingerprinting, captive portals).
MAC address byte structure
AA : BB : CC : DD : EE : FF
┌────────────┐ ┌────────────┐
│ OUI (3B) │ │ NIC (3B) │
│ Vendor ID │ │ Device ID │
└────────────┘ └────────────┘
First byte flags:
Bit 0 (LSB) = I/G bit
0 = Individual (unicast — a single device)
1 = Group (multicast or broadcast)
Bit 1 = U/L bit
0 = Universally administered (burned-in, from manufacturer)
1 = Locally administered (software-set, like mac_spoof sets)
Special MAC addresses:
FF:FF:FF:FF:FF:FF — broadcast (all devices on segment)
01:xx:xx:xx:xx:xx — multicast (I/G bit set)
33:33:xx:xx:xx:xx — IPv6 multicast
01:80:C2:00:00:00 — STP Bridge Protocol Data Units
mac_spoof sets the U/L bit to 1 on random MACs to signal
that the address is locally administered — this is normal
and expected for software-set addresses.
OUI assignments
# OUI (Organizationally Unique Identifier) — first 3 bytes
# Assigned by IEEE to manufacturers. Public lookup database:
# https://regauth.standards.ieee.org/standards-ra-web/pub/view.html#registries
Sample OUIs:
00:50:56 VMware, Inc.
00:0C:29 VMware (auto-assigned)
DC:A6:32 Raspberry Pi Trading Ltd
3C:22:FB Apple, Inc.
00:1A:11 Google Inc
00:16:3E Xensource (Xen hypervisor VMs)
08:00:27 PCS Systemtechnik GmbH (VirtualBox)
B8:27:EB Raspberry Pi Foundation
# mac_spoof set_vendor looks up the OUI from its database
# and sets only the first 3 bytes, preserving the NIC suffix.
Ethernet Frame: The Wire Format
MAC addresses live inside Ethernet frames — the actual bytes transmitted over the wire (or WiFi medium). Understanding the frame format shows exactly why MAC spoofing works: the NIC driver and kernel simply put whatever 6-byte value is in the interface's configuration into the source field of every outgoing frame.
IEEE 802.3 Ethernet II frame layout
┌─────────────────────────────────────────────────────────────┐
│ Preamble 7 bytes │ 10101010 × 7 (sync pattern) │
│ SFD 1 byte │ 10101011 (Start Frame Delimiter) │
├─────────────────────────────────────────────────────────────┤
│ Dst MAC 6 bytes │ e.g. FF:FF:FF:FF:FF:FF (broadcast) │
│ Src MAC 6 bytes │ ← YOUR MAC goes here │
│ EtherType 2 bytes │ 08 00 = IPv4, 08 06 = ARP │
│ │ 86 DD = IPv6, 81 00 = 802.1Q (VLAN)│
├─────────────────────────────────────────────────────────────┤
│ Payload 46–1500 B │ IP packet (or ARP, etc.) │
├─────────────────────────────────────────────────────────────┤
│ FCS 4 bytes │ CRC-32 checksum (hardware computed)│
└─────────────────────────────────────────────────────────────┘
# Total minimum frame: 64 bytes (padding added if payload < 46 bytes)
# Maximum frame (MTU): 1518 bytes standard, 9000 bytes (jumbo frames)
# Example ARP frame bytes (Wireshark: arp.opcode == 1):
FF FF FF FF FF FF # dst: broadcast
AA BB CC DD EE FF # src: our (possibly spoofed) MAC
08 06 # EtherType: ARP
00 01 08 00 06 04 00 01 # HTYPE=Ethernet, PTYPE=IPv4, HLEN=6, PLEN=4, OP=Request
AA BB CC DD EE FF # sender hardware address (our MAC again)
C0 A8 01 64 # sender IP: 192.168.1.100
00 00 00 00 00 00 # target hardware address (unknown)
C0 A8 01 01 # target IP: 192.168.1.1
802.11 (WiFi) MAC address usage
# WiFi frames have THREE MAC address fields (not two):
# Addr1: Receiver (BSSID or client)
# Addr2: Transmitter (your MAC — what you're spoofing)
# Addr3: Filtering address (BSSID or original destination)
# In infrastructure mode (client ↔ AP):
# From client: Addr1=BSSID, Addr2=client, Addr3=dst
# From AP: Addr1=client, Addr2=BSSID, Addr3=src
# MAC filtering on WiFi AP checks Addr2 — so spoofing Addr2
# (which is the interface MAC) bypasses MAC-based filtering
Linux Kernel: How MAC Spoofing Works
When you run ip link set eth0 address AA:BB:CC:DD:EE:FF, the kernel does not flash new firmware to the NIC — it simply updates a software field in the network device structure that is copied into every outgoing frame by the driver. Here is the exact path:
Kernel data structure
# struct net_device (include/linux/netdevice.h):
struct net_device {
char name[IFNAMSIZ]; // "eth0", "wlan0", etc.
unsigned char dev_addr[MAX_ADDR_LEN]; // ← THE MAC (6 bytes)
unsigned char perm_addr[MAX_ADDR_LEN]; // burned-in hardware MAC
...
};
# mac_spoof writes to dev_addr only — perm_addr is preserved.
# On reboot, dev_addr resets to perm_addr (unless persist is set).
# ifreq struct (from <net/if.h> — used by ioctl):
struct ifreq {
char ifr_name[IFNAMSIZ];
union {
struct sockaddr ifr_addr; // for SIOCSIFHWADDR
// ... other unions
};
};
# SIOCSIFHWADDR ioctl sets dev_addr:
int sock = socket(AF_INET, SOCK_DGRAM, 0);
struct ifreq ifr;
strncpy(ifr.ifr_name, "eth0", IFNAMSIZ);
ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
memcpy(ifr.ifr_hwaddr.sa_data, new_mac, 6);
ioctl(sock, SIOCSIFHWADDR, &ifr); // requires CAP_NET_ADMIN
mac_spoof Python implementation
# tools/network/mac_spoof/mac_spoof.py — simplified core
import subprocess, re, random
def get_current_mac(interface):
output = subprocess.check_output(["ip", "link", "show", interface]).decode()
match = re.search(r'link/ether\s+([0-9a-f:]{17})', output)
return match.group(1) if match else None
def set_mac(interface, mac):
# 1. Take interface down (kernel rejects address change on active iface)
subprocess.run(["ip", "link", "set", interface, "down"], check=True)
# 2. Set new MAC via ip link (calls SIOCSIFHWADDR ioctl internally)
subprocess.run(["ip", "link", "set", interface, "address", mac], check=True)
# 3. Bring interface back up
subprocess.run(["ip", "link", "set", interface, "up"], check=True)
return get_current_mac(interface)
def random_mac(preserve_vendor=False, interface=None):
if preserve_vendor and interface:
current = get_current_mac(interface)
vendor = current[:8] # keep first 3 bytes (OUI)
else:
vendor = None
# Set U/L bit (locally administered), clear I/G bit (unicast)
first_byte = random.randint(0, 255) | 0x02 # set bit 1
first_byte &= ~0x01 # clear bit 0
suffix = [random.randint(0, 255) for _ in range(5)]
if vendor:
parts = vendor.split(":") + [f"{b:02x}" for b in suffix[:3]]
else:
parts = [f"{first_byte:02x}"] + [f"{b:02x}" for b in suffix]
return ":".join(parts)
Netlink socket alternative (modern approach)
# Modern Linux tools use netlink (RTM_SETLINK) instead of ioctl.
# ip(8) uses libmnl / libnl internally. The sequence:
# 1. Open NETLINK_ROUTE socket
# 2. Build RTM_SETLINK message with IFLA_ADDRESS attribute
# nlmsg_type = RTM_SETLINK
# ifinfomsg.ifi_index = interface index (from if_nametoindex())
# nlattr: IFLA_ADDRESS → 6-byte MAC
# 3. sendmsg() → kernel processes in rtnl_setlink()
# 4. Kernel calls dev->ndo_set_mac_address() driver hook
# Most drivers just update dev_addr + announce via netdev_notify
# Python: use pyroute2 which wraps netlink cleanly
from pyroute2 import IPRoute
ip = IPRoute()
idx = ip.link_lookup(ifname='eth0')[0]
ip.link('set', index=idx, address='AA:BB:CC:DD:EE:FF')
ip.close()
OUI Database & Device Fingerprinting
Network access control systems don't just check if a MAC is on a whitelist — they also do MAC fingerprinting: cross-referencing the OUI against a vendor database, correlating DHCP option ordering, and checking for timing anomalies. Understanding these systems is essential for effective MAC spoofing in a red team context.
Detection methods and evasion
| Detection method | How it works | Evasion with mac_spoof |
|---|---|---|
| MAC whitelist (ACL) | Switch/AP allows only listed MACs | Clone target MAC: clone_target action |
| OUI vendor check | NAC verifies OUI matches expected device type | set_vendor with matching vendor (Apple for iPhone, Dell for laptop) |
| DHCP fingerprinting | DHCP option ordering identifies OS/device | Set MAC vendor correctly; OS fingerprint is harder to spoof |
| 802.1X / EAP | Port-based auth requires cert/credentials beyond MAC | MAC alone insufficient — need EAP credentials too |
| ARP probe timing | NAC detects two devices with same MAC (ARP collision) | Ensure original device is offline before cloning |
Choosing the right vendor to clone
# Scenario: bypassing MAC-based WiFi filtering at an office
# Step 1: Passive scan — capture beacons + probe responses
# (use wifi_monitor to capture management frames)
# Identify client MACs already associated to the AP:
# wireshark filter: wlan.fc.type_subtype == 0x08 (Beacon)
# or: wlan.fc.type_subtype == 0x04 (Probe Response)
# Step 2: Look up OUI of an allowed client
curl https://api.macvendors.com/DC:A6:32 # "Raspberry Pi Trading Ltd"
# Step 3: Clone that specific device
use mac_spoof
set action clone_target
set target_mac DC:A6:32:xx:xx:xx
set iface wlan0
run
# Or just adopt the vendor prefix and use a random suffix:
use mac_spoof
set action set_vendor
set vendor "Apple, Inc."
set iface wlan0
run
mac_spoof OUI database
# The OUI database is stored as a dict in mac_spoof.py
OUI_DB = {
"Apple, Inc.": ["3C:22:FB", "A8:51:AB", "DC:2B:2A", "F0:18:98"],
"Samsung": ["00:07:AB", "8C:C8:CD", "F4:42:8F"],
"Dell Inc.": ["00:14:22", "18:03:73", "F0:1F:AF"],
"Raspberry Pi": ["DC:A6:32", "B8:27:EB", "E4:5F:01"],
"VMware": ["00:0C:29", "00:50:56"],
"Google": ["00:1A:11", "F4:F5:E8", "54:60:09"],
# ... hundreds more
}
# set_vendor action:
def set_vendor_mac(interface, vendor_name):
ouis = OUI_DB.get(vendor_name)
if not ouis:
return {"error": f"Vendor '{vendor_name}' not in database"}
chosen_oui = random.choice(ouis)
suffix = ":".join(f"{random.randint(0,255):02x}" for _ in range(3))
new_mac = f"{chosen_oui}:{suffix}"
return set_mac(interface, new_mac)
Customization & Extension
Expanding the OUI database
# Download the full IEEE OUI registry (updated weekly):
wget https://standards-oui.ieee.org/oui/oui.csv -O oui.csv
# Parse into mac_spoof OUI_DB format:
import csv
def build_oui_db(csv_path):
db = {}
with open(csv_path) as f:
reader = csv.DictReader(f)
for row in reader:
vendor = row["Organization Name"].strip()
oui_hex = row["Assignment"].strip() # "AABBCC"
oui_fmt = ":".join(oui_hex[i:i+2] for i in range(0, 6, 2)).upper()
db.setdefault(vendor, []).append(oui_fmt)
return db
# Save as JSON for mac_spoof to load:
import json
db = build_oui_db("oui.csv")
with open("oui_db.json", "w") as f:
json.dump(db, f, indent=2)
print(f"Loaded {len(db)} vendors, {sum(len(v) for v in db.values())} OUIs")
Adding a scheduled rotation action
# Rotate MAC every N seconds — useful for survey evasion
import time, threading
def mac_rotate(interface, interval_s=300, vendor=None):
"""Rotate MAC every interval_s seconds."""
def _rotate():
while True:
if vendor:
new_mac = random_vendor_mac(vendor)
else:
new_mac = random_mac()
result = set_mac(interface, new_mac)
print(f"[+] Rotated to {result}")
time.sleep(interval_s)
t = threading.Thread(target=_rotate, daemon=True)
t.start()
return {"status": "rotating", "interval_s": interval_s}
# Add to module.json:
# { "name": "rotate", "description": "Rotate MAC every N seconds" }
# Parameters: interface, interval (default 300), vendor (optional)
Adding DHCP fingerprint spoofing
# DHCP option order is an OS fingerprint.
# Default Linux DHCP: options 1,3,6,12,15,28,51,58,59,119
# Default Windows: options 1,3,6,15,31,33,43,44,46,47,119,121,249,252
# Default iOS: options 1,3,6,15,119,252
# To spoof Windows fingerprint, use dhclient with custom conf:
cat > /tmp/dhclient_windows.conf <<'EOF'
send dhcp-client-identifier = hardware;
request subnet-mask, routers, domain-name-servers, domain-name,
netbios-name-servers, netbios-node-type, netbios-scope,
interface-mtu, classless-static-routes,
private-classless-static-routes;
EOF
dhclient -cf /tmp/dhclient_windows.conf eth0
Learning Path
Recommended resources
| Resource | Format | Focus |
|---|---|---|
| TryHackMe — Network Fundamentals | Free guided lab | OSI model, MAC vs IP, ARP, Ethernet frames |
| Wireshark Ethernet docs | Reference | Ethernet frame format, capture filters |
| Computer Networks — Tanenbaum (Ch. 4) | Book | Data Link layer, MAC addressing, 802.11 |
| IEEE 802.3 / 802.11 standards | Free PDFs | Authoritative frame format definitions |
| SANS — MAC Spoofing Intro | Whitepaper | Detection and bypass techniques |
| netdevice(7) man page | Reference | SIOCSIFHWADDR ioctl, struct ifreq |
Hands-on exercises
Exercise 1 — See your own MAC on the wire
▸ Open Wireshark on eth0 or wlan0
▸ Filter: eth.src == your_current_mac
▸ Ping your gateway — observe MAC in Ethernet header
▸ Run: mac_spoof random on your interface
▸ Wireshark: confirm src MAC changed in next ARP/ping
Exercise 2 — ARP cache poisoning awareness
▸ Check ARP table: arp -n (or ip neigh)
▸ Run mac_spoof, then ping gateway again
▸ Watch gateway ARP table update to new MAC → old entry replaced
▸ Understand: ARP has no authentication — this is why ARP spoofing works
Exercise 3 — Clone a device MAC
▸ Find the MAC of another device on your network (nmap -sn 192.168.1.0/24)
▸ mac_spoof clone_target that device's MAC (while it's offline)
▸ Observe: you now appear as that device to the switch/router
▸ Restore: mac_spoof restore when done
Exercise 4 — Captive portal bypass
▸ On a guest WiFi that uses MAC-based whitelisting after login:
▸ Connect legitimate device, note its MAC
▸ Disconnect legitimate device
▸ mac_spoof clone_target on your kali machine
▸ Connect to WiFi — portal grants access without re-authenticating
Exercise 5 — Persistence test
▸ mac_spoof persist on your test interface
▸ Reboot
▸ Confirm MAC is still the spoofed one: ip link show
▸ Inspect /etc/NetworkManager/dispatcher.d/ or systemd service created
Key tools
| Tool | Purpose | Install |
|---|---|---|
| ip (iproute2) | Set MAC: ip link set eth0 address xx:xx:xx:xx:xx:xx | built-in on all Linux |
| macchanger | Alternative MAC changer with vendor DB | pacman -S macchanger |
| Wireshark | Capture and verify Ethernet frame MACs | pacman -S wireshark-qt |
| arp-scan | ARP scan to discover MAC/IP mappings | pacman -S arp-scan |
| pyroute2 | Python netlink library for MAC changes | pip install pyroute2 |