Ready to take Python coding to a new level? Explore our Python Code Generator. The perfect tool to get your code up and running in no time. Start now!
The MAC address is a unique identifier assigned to each network interface in any device that connects to a network. Changing this address has many benefits, including MAC address blocking prevention; if your MAC address is blocked on an access point, you simply change it to continue using that network.
This tutorial will teach you how to change your MAC address on both Windows and Linux environments using Python.
We don't have to install anything, as we'll be using the subprocess module in Python, interacting with the ifconfig
command on Linux and getmac
, reg
, and wmic
commands on Windows.
Related: Build over 35 Ethical Hacking Scripts & Tools with Python EBook
To get started, open up a new Python file and import the libraries:
import subprocess
import string
import random
import re
We will have a choice to randomize a new MAC address or change it to a specified one. As a result, let's make a function to generate and return a MAC address:
def get_random_mac_address():
"""Generate and return a MAC address in the format of Linux"""
# get the hexdigits uppercased
uppercased_hexdigits = ''.join(set(string.hexdigits.upper()))
# 2nd character must be 0, 2, 4, 6, 8, A, C, or E
mac = ""
for i in range(6):
for j in range(2):
if i == 0:
mac += random.choice("02468ACE")
else:
mac += random.choice(uppercased_hexdigits)
mac += ":"
return mac.strip(":")
We use the string module to get the hexadecimal digits used in MAC addresses; we remove the lowercase characters and use the random module to sample from those characters.
Next, let's make another function that uses the ifconfig
command to get the current MAC address of our machine:
def get_current_mac_address(iface):
# use the ifconfig command to get the interface details, including the MAC address
output = subprocess.check_output(f"ifconfig {iface}", shell=True).decode()
return re.search("ether (.+) ", output).group().split()[1].strip()
We use the check_output()
function from the subprocess module that runs the command on the default shell and returns the command output.
The MAC address is located just after the "ether"
word, we use the re.search()
method to grab that.
Now that we have our utilities, let's make the core function to change the MAC address:
def change_mac_address(iface, new_mac_address):
# disable the network interface
subprocess.check_output(f"ifconfig {iface} down", shell=True)
# change the MAC
subprocess.check_output(f"ifconfig {iface} hw ether {new_mac_address}", shell=True)
# enable the network interface again
subprocess.check_output(f"ifconfig {iface} up", shell=True)
Pretty straightforward, the change_mac_address()
function accepts the interface and the new MAC address as parameters, it disables the interface, changes the MAC address, and enables it again.
Now that we have everything, let's use the argparse module to wrap up our script:
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description="Python Mac Changer on Linux")
parser.add_argument("interface", help="The network interface name on Linux")
parser.add_argument("-r", "--random", action="store_true", help="Whether to generate a random MAC address")
parser.add_argument("-m", "--mac", help="The new MAC you want to change to")
args = parser.parse_args()
iface = args.interface
if args.random:
# if random parameter is set, generate a random MAC
new_mac_address = get_random_mac_address()
elif args.mac:
# if mac is set, use it instead
new_mac_address = args.mac
# get the current MAC address
old_mac_address = get_current_mac_address(iface)
print("[*] Old MAC address:", old_mac_address)
# change the MAC address
change_mac_address(iface, new_mac_address)
# check if it's really changed
new_mac_address = get_current_mac_address(iface)
print("[+] New MAC address:", new_mac_address)
We have a total of three parameters to pass to this script:
interface
: The network interface name you want to change the MAC address of, you can get it using ifconfig
or ip
commands in Linux.-r
or --random
: Whether we generate a random MAC address instead of a specified one.-m
or --mac
: The new MAC address we want to change to, don't use this with the -r
parameter.In the main code, we use the get_current_mac_address()
function to get the old MAC, we change the MAC, and then we run get_current_mac_address()
again to check if it's changed. Here's a run:
$ python mac_address_changer_linux.py wlan0 -r
My interface name is wlan0
, and I've chosen -r
to randomize a MAC address. Here's the output:
[*] Old MAC address: 84:76:04:07:40:59
[+] New MAC address: ee:52:93:6e:1c:f2
Let's change to a specified MAC address now:
$ python mac_address_changer_linux.py wlan0 -m 00:FA:CE:DE:AD:00
Output:
[*] Old MAC address: ee:52:93:6e:1c:f2
[+] New MAC address: 00:fa:ce:de:ad:00
The change is reflected on the machine and other machines in the same network and the router.
Read also: How to Make an HTTP Proxy in Python
On Windows, we will be using three main commands, which are:
getmac
: This command returns a list of network interfaces and their MAC addresses and transport name; the latter is not shown when an interface is not connected.reg
: This is the command used to interact with the Windows registry. We can use the winreg
module for the same purpose. However, I preferred using the reg
command.Let's get started:
import subprocess
import regex as re
import string
import random
# the registry path of network interfaces
network_interface_reg_path = r"HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}"
# the transport name regular expression, looks like {AF1B45DB-B5D4-46D0-B4EA-3E18FA49BF5F}
transport_name_regex = re.compile("{.+}")
# the MAC address regular expression
mac_address_regex = re.compile(r"([A-Z0-9]{2}[:-]){5}([A-Z0-9]{2})")
network_interface_reg_path
is the path in the registry where network interface details are located. We use transport_name_regex
and mac_address_regex
regular expressions to extract the transport name and the MAC address of each connected adapter, respectively, from the getmac
command.
Next, let's make two simple functions, one for generating random MAC addresses (like before, but in Windows format), and one for cleaning MAC addresses when the user specifies it:
def get_random_mac_address():
"""Generate and return a MAC address in the format of WINDOWS"""
# get the hexdigits uppercased
uppercased_hexdigits = ''.join(set(string.hexdigits.upper()))
# 2nd character must be 2, 4, A, or E
return random.choice(uppercased_hexdigits) + random.choice("24AE") + "".join(random.sample(uppercased_hexdigits, k=10))
def clean_mac(mac):
"""Simple function to clean non hexadecimal characters from a MAC address
mostly used to remove '-' and ':' from MAC addresses and also uppercase it"""
return "".join(c for c in mac if c in string.hexdigits).upper()
Master Ethical Hacking with Python by building 35+ Tools from scratch. Get your copy now!
Download EBookFor some reason, only 2, 4, A, and E characters work as the second character on the MAC address on Windows 10. I have tried the other even characters but with no success.
Below is the function responsible for getting the available adapters' MAC addresses:
def get_connected_adapters_mac_address():
# make a list to collect connected adapter's MAC addresses along with the transport name
connected_adapters_mac = []
# use the getmac command to extract
for potential_mac in subprocess.check_output("getmac").decode().splitlines():
# parse the MAC address from the line
mac_address = mac_address_regex.search(potential_mac)
# parse the transport name from the line
transport_name = transport_name_regex.search(potential_mac)
if mac_address and transport_name:
# if a MAC and transport name are found, add them to our list
connected_adapters_mac.append((mac_address.group(), transport_name.group()))
return connected_adapters_mac
It uses the getmac
command on Windows and returns a list of MAC addresses along with their transport name.
When the above function returns more than one adapter, we need to prompt the user to choose which adapter to change the MAC address. The below function does that:
def get_user_adapter_choice(connected_adapters_mac):
# print the available adapters
for i, option in enumerate(connected_adapters_mac):
print(f"#{i}: {option[0]}, {option[1]}")
if len(connected_adapters_mac) <= 1:
# when there is only one adapter, choose it immediately
return connected_adapters_mac[0]
# prompt the user to choose a network adapter index
try:
choice = int(input("Please choose the interface you want to change the MAC address:"))
# return the target chosen adapter's MAC and transport name that we'll use later to search for our adapter
# using the reg QUERY command
return connected_adapters_mac[choice]
except:
# if -for whatever reason- an error is raised, just quit the script
print("Not a valid choice, quitting...")
exit()
Now let's make our function to change the MAC address of a given adapter transport name that is extracted from the getmac
command:
def change_mac_address(adapter_transport_name, new_mac_address):
# use reg QUERY command to get available adapters from the registry
output = subprocess.check_output(f"reg QUERY " + network_interface_reg_path.replace("\\\\", "\\")).decode()
for interface in re.findall(rf"{network_interface_reg_path}\\\d+", output):
# get the adapter index
adapter_index = int(interface.split("\\")[-1])
interface_content = subprocess.check_output(f"reg QUERY {interface.strip()}").decode()
if adapter_transport_name in interface_content:
# if the transport name of the adapter is found on the output of the reg QUERY command
# then this is the adapter we're looking for
# change the MAC address using reg ADD command
changing_mac_output = subprocess.check_output(f"reg add {interface} /v NetworkAddress /d {new_mac_address} /f").decode()
# print the command output
print(changing_mac_output)
# break out of the loop as we're done
break
# return the index of the changed adapter's MAC address
return adapter_index
The change_mac_address()
function uses the reg QUERY
command on Windows to query the network_interface_reg_path
we specified at the beginning of the script, it will return the list of all available adapters, and we distinguish the target adapter by its transport name.
After we find the target network interface, then we use reg add
command to add a new NetworkAddress
entry in the registry specifying the new MAC address. The function also returns the adapter index, which we'll need later on the wmic
command.
Of course, the MAC address change isn't reflected immediately when the new registry entry is added. We need to disable the adapter and enable it again. Below functions do it:
def disable_adapter(adapter_index):
# use wmic command to disable our adapter so the MAC address change is reflected
disable_output = subprocess.check_output(f"wmic path win32_networkadapter where index={adapter_index} call disable").decode()
return disable_output
def enable_adapter(adapter_index):
# use wmic command to enable our adapter so the MAC address change is reflected
enable_output = subprocess.check_output(f"wmic path win32_networkadapter where index={adapter_index} call enable").decode()
return enable_output
The adapter system number is required by wmic
command, and luckily we get it from our previous change_mac_address()
function.
And we're done! Let's make our main code:
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description="Python Windows MAC changer")
parser.add_argument("-r", "--random", action="store_true", help="Whether to generate a random MAC address")
parser.add_argument("-m", "--mac", help="The new MAC you want to change to")
args = parser.parse_args()
if args.random:
# if random parameter is set, generate a random MAC
new_mac_address = get_random_mac_address()
elif args.mac:
# if mac is set, use it after cleaning
new_mac_address = clean_mac(args.mac)
connected_adapters_mac = get_connected_adapters_mac_address()
old_mac_address, target_transport_name = get_user_adapter_choice(connected_adapters_mac)
print("[*] Old MAC address:", old_mac_address)
adapter_index = change_mac_address(target_transport_name, new_mac_address)
print("[+] Changed to:", new_mac_address)
disable_adapter(adapter_index)
print("[+] Adapter is disabled")
enable_adapter(adapter_index)
print("[+] Adapter is enabled again")
Since the network interface choice is prompted after running the script (whenever two or more interfaces are detected), we don't have to add an interface argument.
The main code is simple:
get_connected_adapters_mac_address()
function.change_mac_address()
function to change the MAC address for the given adapter's transport name.disable_adapter()
and enable_adapter()
functions respectively, so the MAC address change is reflected.Alright, we're done with the script. Before you try it, you must ensure you run as an administrator. I've named the script as mac_address_changer_windows.py
:
$ python mac_address_changer_windows.py --help
Output:
usage: mac_address_changer_windows.py [-h] [-r] [-m MAC]
Python Windows MAC changer
optional arguments:
-h, --help show this help message and exit
-r, --random Whether to generate a random MAC address
-m MAC, --mac MAC The new MAC you want to change to
Let's try with a random MAC:
$ python mac_address_changer_windows.py --random
Output:
#0: EE-9C-BC-AA-AA-AA, {0104C4B7-C06C-4062-AC09-9F9B977F2A55}
#1: 02-00-4C-4F-4F-50, {DD1B45DA-B5D4-46D0-B4EA-3E07FA35BF0F}
Please choose the interface you want to change the MAC address:0
[*] Old MAC address: EE-9C-BC-AA-AA-AA
The operation completed successfully.
[+] Changed to: 5A8602E9CF3D
[+] Adapter is disabled
[+] Adapter is enabled again
I was prompted to choose the adapter, I've chosen the first, and the MAC address is changed to a random MAC address. Let's confirm with the getmac
command:
$ getmac
Output:
Physical Address Transport Name
=================== ==========================================================
5A-86-02-E9-CF-3D \Device\Tcpip_{0104C4B7-C06C-4062-AC09-9F9B977F2A55}
02-00-4C-4F-4F-50 \Device\Tcpip_{DD1B45DA-B5D4-46D0-B4EA-3E07FA35BF0F}
The operation was indeed successful! Let's try with a specified MAC:
$ python mac_address_changer_windows.py -m EE:DE:AD:BE:EF:EE
Output:
#0: 5A-86-02-E9-CF-3D, {0104C4B7-C06C-4062-AC09-9F9B977F2A55}
#1: 02-00-4C-4F-4F-50, {DD1B45DA-B5D4-46D0-B4EA-3E07FA35BF0F}
Please choose the interface you want to change the MAC address:0
[*] Old MAC address: 5A-86-02-E9-CF-3D
The operation completed successfully.
[+] Changed to: EEDEADBEEFEE
[+] Adapter is disabled
[+] Adapter is enabled again
Awesome! In this tutorial, you have learned how to make a MAC address changer on any Linux or Windows machine.
If you don't have ifconfig
command installed, you have to install it via apt install net-tools
on Debian/Ubuntu or yum install net-tools
on Fedora/CentOS.
You can get the complete code for both environments here.
Finally, we have an Ethical Hacking with Python Ebook, where we build over 35 hacking tools and scripts with Python from scratch! Make sure to check it out if you're interested.
Learn also: How to Execute Shell Commands in a Remote Machine in Python
Please note that we don't take any responsibility if you misuse the script provided in this tutorial; stay ethical!
Happy hacking ♥
Save time and energy with our Python Code Generator. Why start from scratch when you can generate? Give it a try!
View Full Code Explain The Code for Me
Got a coding query or need some guidance before you comment? Check out this Python Code Assistant for expert advice and handy tips. It's like having a coding tutor right in your fingertips!