mac_spoof.

Per-interface MAC address rotation daemon for Linux. Background processes, locally-administered OUI generation, real vendor OUI spoofing (Apple, Samsung, Intel, Cisco, Dell), rotation history, stealth mode, persistent systemd service.

VANTA Module Network Anonymity MAC Spoofing Daemon Mode iproute2 Python 3.6+ v0.0.1
CategoryNetwork · Anonymity
LanguagePython 3
Locationtools/network/mac_spoof/
Author0xb0rn3
PrivilegesRoot required
LicenseMIT
Beginner Startup
New to VANTA or mac_spoof? Start here.
Foundations guide →
What you need first
  • ▸ A network adapter (Ethernet or WiFi)
  • ▸ Root privileges: sudo or run VANTA as root
Your first safe command
set interface eth0
set mode random
run
Operations by difficulty
  • Easy: random, restore, show
  • Medium: set_vendor, clone_target
  • Advanced: persist (survives reboot via systemd hook)
Key terms: MAC Address — Hardware ID of a network adapter — XX:XX:XX:XX:XX:XX format  ·  OUI — First 3 bytes of MAC — identifies the manufacturer (Organizationally Unique Identifier)  ·  MAC Filtering — Network defense that only allows specific MAC addresses to connect  — Full glossary →

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.

Process
Per-Interface Daemons
Each interface gets its own detached background process - independent rotation speeds, no cross-interference.
State
Persistent State
Original MAC and PID stored in ~/.vanta/mac_spoof/. Survives shell restarts. Stop any time and restore cleanly.
Format
Locally-Admin MACs
Generated addresses use 02:00:00:xx:xx:xx - locally-administered unicast prefix avoids vendor OUI conflicts and DHCP weirdness.
Scope
Multi-Interface
Spoof a single interface, a comma-separated list, or all UP non-loopback interfaces in one command.
Safety
Dry Run Mode
Preview every action - shows what would change, what original MACs would be saved - without touching any interface.
Restore
Auto-Restoration
Stop action always brings the interface back to its original vendor MAC. State file is cleaned up automatically.
Vendor
Vendor Spoofing
Spoof as Apple, Samsung, Intel, Cisco, or Dell using a real OUI prefix. The last three octets are random so it looks like a real device on the network.
Stealth
Stealth Mode
Set stealth true and the daemon only rotates when the interface disconnects and reconnects. Useful when you need a stable IP but want a fresh MAC on every new association.

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.

start default
Start a background rotation daemon for each selected interface. Saves original MAC to state file before first change.
stop
Kill the daemon and restore the original vendor MAC from the state file. Cleans up state on success.
status
Report daemon PID, uptime, current MAC, original MAC, and rotation interval for each tracked interface.
vendor
Spoof as a real hardware vendor. Set the vendor param to apple, samsung, intel, cisco, or dell. Uses a real OUI prefix from that vendor's registered range.
restore
Restore the original MAC from state without stopping a running daemon. Falls back to ethtool -P if no state file exists.
history
Show the rotation log for the interface. Each entry has a timestamp, MAC, and how the change was triggered.
! Always stop daemons before system shutdown. If the process is killed without a clean stop, run set action stop on next boot - the state file still holds the original MAC and will restore it correctly.

Reference

Parameters

ParameterTypeDefaultDescription
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

01
Save original MAC
Reads current MAC via 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.
02
Fork and detach
The daemon forks via 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.
03
Rotation loop
Child enters an infinite loop: generate random locally-administered MAC → ip link set <iface> downip link set <iface> address <mac>ip link set <iface> up → sleep(interval). Each change takes ~100ms during which the interface is briefly down.
04
Signal handling
SIGTERM causes the daemon to restore the original MAC from the state file before exiting. This is what the 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:

OctetsValueWhy
Octet 102Bit 1 set → locally administered. Bit 0 clear → unicast (not multicast).
Octets 2–300:00Consistent prefix - makes it easy to identify spoofed addresses in logs or Wireshark captures.
Octets 4–6random3 bytes of cryptographically random data - 16.7 million unique values per rotation cycle.

Example: 02:00:00:1a:2b:3c

i Locally-administered MACs are easy to spot. If your goal is to blend in with real device traffic, consider using a known vendor OUI prefix instead and generating random last 3 bytes. That requires a custom iface script - mac_spoof's built-in format prioritises avoiding conflicts over fingerprint evasion.

Detection risk

Detection vectorRiskNotes
ARP cache churnMediumRapid ARP announcement pattern is unusual
OUI mismatchHigh02:00:00 prefix is not a real vendor - obvious to any network scanner
DHCP request stormMediumEach MAC change triggers a new DHCP request on most systems
Switch port securityHighManaged switches with MAC-limit policies will trigger port shutdown
WiFi re-associationLow802.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 vectorLocally-administeredVendor-spoofed
OUI database lookupInstant flag: 02:00:00 is not a real vendorPasses: OUI matches a known manufacturer
Wireshark / passive captureLabeled "Locally Administered"Labeled with vendor name
802.1X / NACHigh suspicionLower suspicion, still fingerprinted by other signals
ARP cache churnMedium: rapid changes are unusualMedium: same churn pattern applies
DHCP fingerprintingOS/stack still visibleOS/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
! Vendor spoofing does not make you invisible. 802.1X enterprise networks fingerprint beyond the MAC using EAP identity, DHCP options, TCP/IP stack behavior, and probe frame patterns. Use vendor spoofing to blend into expected device pools on a target segment, not as a stand-alone evasion technique.

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

About

Author

0x
0xb0rn3
Security Researcher · VANTA Developer
Security researcher and tool builder. mac_spoof is part of the VANTA offensive security framework - a modular Go shell with Python-driven modules for network recon, mobile pentesting, and C2 operations. Background in network security, red team operations, and Linux internals.

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 methodHow it worksEvasion with mac_spoof
MAC whitelist (ACL)Switch/AP allows only listed MACsClone target MAC: clone_target action
OUI vendor checkNAC verifies OUI matches expected device typeset_vendor with matching vendor (Apple for iPhone, Dell for laptop)
DHCP fingerprintingDHCP option ordering identifies OS/deviceSet MAC vendor correctly; OS fingerprint is harder to spoof
802.1X / EAPPort-based auth requires cert/credentials beyond MACMAC alone insufficient — need EAP credentials too
ARP probe timingNAC 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

ResourceFormatFocus
TryHackMe — Network FundamentalsFree guided labOSI model, MAC vs IP, ARP, Ethernet frames
Wireshark Ethernet docsReferenceEthernet frame format, capture filters
Computer Networks — Tanenbaum (Ch. 4)BookData Link layer, MAC addressing, 802.11
IEEE 802.3 / 802.11 standardsFree PDFsAuthoritative frame format definitions
SANS — MAC Spoofing IntroWhitepaperDetection and bypass techniques
netdevice(7) man pageReferenceSIOCSIFHWADDR 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

ToolPurposeInstall
ip (iproute2)Set MAC: ip link set eth0 address xx:xx:xx:xx:xx:xxbuilt-in on all Linux
macchangerAlternative MAC changer with vendor DBpacman -S macchanger
WiresharkCapture and verify Ethernet frame MACspacman -S wireshark-qt
arp-scanARP scan to discover MAC/IP mappingspacman -S arp-scan
pyroute2Python netlink library for MAC changespip install pyroute2

J1 ARP and Why MAC Matters

How Switches and Networks Use MAC Addresses

A MAC (Media Access Control) address is a 48-bit hardware identifier assigned to a network interface at the factory. It operates at Layer 2 of the OSI model (the Data Link layer), which is below IP (Layer 3). MAC addresses are how devices communicate within a single network segment - before a packet can be sent to an IP address on the same local network, the sender must know the destination's MAC.

ARP (Address Resolution Protocol)
ARP maps IP addresses to MAC addresses within a local network. When device A wants to send to 192.168.1.5, it broadcasts "who has 192.168.1.5?". The device with that IP replies "I do, and my MAC is AA:BB:CC:DD:EE:FF". A stores this in its ARP table and sends frames directly to that MAC. Switches learn MAC-to-port mappings the same way and build their forwarding tables.
How Switches Use MACs
A switch maintains a CAM (Content Addressable Memory) table that maps MAC addresses to switch ports. When a frame arrives, the switch looks up the destination MAC and forwards the frame only to the correct port. If the MAC is unknown, the switch floods the frame to all ports. By spoofing a known device's MAC, you receive traffic intended for that device.
MAC vs IP in Practice
Routers forward traffic between networks using IP addresses. Switches forward traffic within a network using MAC addresses. Your traffic always uses both: IP for routing across networks, MAC for delivery within the current network segment. Changing your MAC changes your Layer 2 identity - which affects switch CAM tables, DHCP leases, and network access control systems.
Why Spoofing MAC Changes Identity
If you spoof the MAC of a device that is authorized on the network, the switch and access control systems treat you as that authorized device. Your traffic comes from a "known good" hardware address. DHCP may assign you the same IP as the original device (or a new one). This is why mac_spoof is the first step in bypassing network access control.
# View your current MAC address
ip link show eth0 | grep ether

# View the ARP table (recently contacted IPs and their MACs)
arp -a
  # shows: hostname (IP) at MAC on interface

# Identify a target device's MAC from the ARP table
arp -a | grep 192.168.1.50

# Change MAC address (bring interface down first)
ip link set eth0 down
ip link set eth0 address AA:BB:CC:DD:EE:FF
ip link set eth0 up

# Verify the change
ip link show eth0 | grep ether

J2 802.1X Port Authentication Bypass

What is NAC and How to Bypass It With a Spoofed MAC

802.1X is an IEEE standard for port-based network access control (NAC). It forces devices to authenticate before they can access the network. Enterprise environments use it to ensure that only authorized, managed devices can connect to network ports. It works with RADIUS servers to validate credentials or certificates. MAC-based Authentication Bypass (MAB) is a common fallback that becomes the attack vector.

How 802.1X Works
When you plug into a switch port with 802.1X, the switch sends an EAP (Extensible Authentication Protocol) request. If your device has supplicant software, it responds with credentials. The switch relays these to a RADIUS server for verification. If authentication fails, the port remains in an "unauthorized" VLAN with no network access.
MAB (MAC Authentication Bypass)
For devices that cannot run 802.1X supplicant software (printers, phones, IoT devices), administrators configure MAB: the switch uses the device's MAC address as its credential. The RADIUS server checks the MAC against an allow-list. If the MAC is approved, access is granted. This creates the bypass: spoof an approved device's MAC.
Finding Approved MACs
Printers, IP phones, and badge readers are common MAB-approved devices. Their MACs are visible to anyone with network access - just scan the network or look at the ARP table. Alternatively, connect to an unsecured port (like a conference room jack), observe which devices communicate on the network, and spoof one of their MACs.
Timing the Spoof
If the legitimate device is still online and the switch sees two devices with the same MAC on different ports, it may deauthenticate both or send security alerts. The cleaner approach: wait until the device is offline (night shift for a printer, weekend for a badge reader), then spoof its MAC. Or perform a deauth/ARP spoofing attack to disconnect the real device first.
# Discover other devices on the network to find a MAB candidate
nmap -sn 192.168.1.0/24 --send-ip
  # -sn = ping scan only (no port scan)
  # shows IP and MAC of discovered hosts

# Look for printers, phones, access control devices (common MAB candidates)
nmap -sn 192.168.1.0/24 -oG - | grep "00:1E:58\|00:15:65"
  # those OUI prefixes belong to Zebra (printers) and Avocent

# Check OUI of a MAC to identify device vendor
macchanger --lookup AA:BB:CC:DD:EE:FF
  # tells you the manufacturer from the first 3 bytes (OUI)

# Spoof the identified device's MAC
ip link set eth0 down
ip link set eth0 address [TARGET_DEVICE_MAC]
ip link set eth0 up
dhclient eth0   # request a new DHCP lease with the spoofed identity

How Devices Identify Themselves Through DHCP Options

DHCP (Dynamic Host Configuration Protocol) is how devices get IP addresses automatically when they join a network. The DHCP Discover packet sent by a new device contains more than just a request for an IP - it includes options that reveal the device type, OS, and hostname. This is called DHCP fingerprinting and can both help defenders identify unauthorized devices and help attackers blend their traffic into the expected device profile.

What DHCP Options Reveal
Option 55 (Parameter Request List) is the fingerprint: different operating systems request DHCP options in different orders. Linux requests 1,28,2,3,15,6. Windows requests 1,3,6,15,31,33,43,44,46,47,252. macOS has its own distinct pattern. NAC systems use these patterns to identify device types and enforce policy (e.g. deny any non-Windows device from the corporate VLAN).
Hostname and Vendor Class
Option 12 (Hostname): the device sends its configured hostname. This reveals device names like "LAPTOP-0XB0RN3" or "Corp-Printer-02" to the DHCP server and anyone sniffing the broadcast. Option 60 (Vendor Class Identifier): Windows sends "MSFT 5.0", Cisco IP phones send their model string. These are additional fingerprints for device classification.
Blending In
If you have spoofed the MAC of a Windows workstation for 802.1X bypass, your Linux Kali machine may be detected because its DHCP fingerprint looks like Linux not Windows. Use dhclient with a custom configuration that mimics the Windows DHCP parameter request list. Or use a Windows VM for testing to produce authentic Windows DHCP traffic.
# Capture DHCP traffic on the local segment to see device fingerprints
tcpdump -i eth0 -n port 67 or port 68 -v

# In Wireshark, filter for DHCP Discover packets and inspect Option 55
# (Parameter Request List) to see what each device requests

# Customize your DHCP request to mimic a specific device type
# Create /etc/dhclient-custom.conf:
send dhcp-client-identifier = hardware;
request subnet-mask, broadcast-address, time-offset, routers,
        domain-name, domain-name-servers, netbios-name-servers,
        netbios-node-type;
  # Above mimics a basic Windows DHCP request pattern

dhclient -cf /etc/dhclient-custom.conf eth0

# Use nmap to see what DHCP fingerprints look like on your network
nmap --script broadcast-dhcp-discover -e eth0