Modification de l'adresse MAC sous Linux
Pour commencer, ouvrez un nouveau fichier Python et importez les bibliothèques suivantes :
import re
import string
import random
import subprocess
Dans notre programme, nous aurons le choix de générer une nouvelle adresse MAC de façon aléatoire ou de la remplacer par une adresse spécifiée. Par conséquent, créons une fonction pour générer et retourner une adresse MAC :
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(":")
Nous utilisons le module string pour obtenir les caractères hexadécimaux utilisés dans les adresses MAC ; nous supprimons les caractères minuscules et utilisons le module random pour extraire ces caractères.
Ensuite, créons une autre fonction qui utilise la commande ifconfig pour obtenir l'adresse MAC actuelle de notre 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()
Nous utilisons la fonction check_output() du module subprocess qui exécute la commande sur le shell par défaut et renvoie le résultat de la commande.
L'adresse MAC est située juste après le mot "ether", nous utilisons la méthode re.search() pour la récupérer.
Maintenant que nous avons nos utilitaires, créons la fonction principale pour changer l'adresse MAC :
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)
Assez simple, la fonction change_mac_address() accepte l'interface et la nouvelle adresse MAC comme paramètres. Elle désactive l'interface, change l'adresse MAC, et la réactive.
Maintenant que nous avons tout, utilisons le module argparse pour terminer notre 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)
Nous avons un total de trois paramètres à passer à ce script :
- interface : Le nom de l'interface réseau dont vous voulez changer l'adresse MAC, vous pouvez l'obtenir en utilisant les commandes ifconfig ou ip sous Linux.
- -r ou --random : Si nous générons une adresse MAC aléatoire au lieu d'une adresse spécifiée.
- -m ou --mac : La nouvelle adresse MAC que nous voulons changer, ne l'utilisez pas avec le paramètre -r.
Dans le code principal, nous utilisons la fonction get_current_mac_address() pour obtenir l'ancienne adresse MAC. Nous changeons l'adresse MAC, puis nous exécutons à nouveau get_current_mac_address() pour vérifier si elle a changé. Voici une exécution :
$ python mac_address_changer_linux.py wlan0 -r
Mon nom d'interface est wlan0, et j'ai choisi -r pour générer une adresse MAC de façon aléatoire. Voici le résultat :
[*] Old MAC address: 84:76:04:07:40:59
[+] New MAC address: ee:52:93:6e:1c:f2
Attribuons maintenant une adresse MAC spécifique :
$ python mac_address_changer_linux.py wlan0 -m 00:FA:CE:DE:AD:00
Résultat
[*] Old MAC address: ee:52:93:6e:1c:f2
[+] New MAC address: 00:fa:ce:de:ad:00
La modification est répercutée sur la machine et les autres machines du même réseau et du routeur.
Voici le code source complet pour les environnements Linux.
mac_address_changer_linux.py
import re
import string
import random
import subprocess
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(":")
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()
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)
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)
Changer l'adresse MAC sous Windows
Sous Windows, nous allons utiliser trois commandes principales, qui sont :
- getmac : Cette commande renvoie une liste des interfaces réseau ainsi que leur adresse MAC et leur nom de transport ; ce dernier n'est pas affiché lorsqu'une interface n'est pas connectée.
- reg : C'est la commande utilisée pour interagir avec le registre de Windows. On peut utiliser le module winreg dans le même but. Cependant, j'ai préféré utiliser la commande reg.
- wmic : Nous utiliserons cette commande pour désactiver et activer la carte réseau, afin que le changement d'adresse MAC soit pris en compte.
Commençons :
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 est le chemin dans le registre où se trouvent les détails de l'interface réseau. Nous utilisons les expressions régulières transport_name_regex et mac_address_regex pour extraire le nom de transport et l'adresse MAC de chaque adaptateur connecté, respectivement, à partir de la commande getmac.
Ensuite, créons deux fonctions simples, une pour générer des adresses MAC aléatoires (comme précédemment, mais au format Windows), et une pour nettoyer les adresses MAC lorsque l'utilisateur le spécifie :
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()
Pour une raison quelconque, seuls les caractères 2, 4, A et E fonctionnent comme deuxième caractère de l'adresse MAC sous Windows 10. J'ai essayé les autres caractères pairs mais sans succès.
Vous trouverez ci-dessous la fonction responsable de l'obtention des adresses MAC des adaptateurs disponibles :
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
Elle utilise la commande getmac sous Windows et renvoie une liste d'adresses MAC ainsi que leur nom de transport.
Lorsque la fonction ci-dessus renvoie plus d'un adaptateur, nous devons demander à l'utilisateur de choisir l'adaptateur sur lequel modifier l'adresse MAC. C'est ce que fait la fonction ci-dessous :
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()
Maintenant, implémentons notre fonction pour changer l'adresse MAC d'un nom de transport d'adaptateur donné qui est extrait de la commande getmac :
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
La fonction change_mac_address() utilise la commande reg QUERY sous Windows pour interroger le chemin d'accès network_interface_reg_path que nous avons spécifié au début du script, il retournera la liste de tous les adaptateurs disponibles, et nous distinguons l'adaptateur cible par son nom de transport.
Après avoir trouvé l'interface réseau cible, nous utilisons la commande reg add pour ajouter une nouvelle entrée NetworkAddress dans le registre en spécifiant la nouvelle adresse MAC. La fonction renvoie également l'index de l'adaptateur, dont nous aurons besoin plus tard avec la commande wmic.
Bien sûr, le changement d'adresse MAC n'est pas pris en compte immédiatement lorsque la nouvelle entrée de registre est ajoutée. Nous devons désactiver l'adaptateur et le réactiver. Les fonctions ci-dessous le font :
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
Le numéro de système de l'adaptateur est requis par la commande wmic, et heureusement nous l'avons obtenu de notre fonction précédente change_mac_address().
Et nous avons terminé ! Ajoutons notre code principal :
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")
Puisque le choix de l'interface réseau est demandé après l'exécution du script (lorsque deux interfaces ou plus sont détectées), nous n'avons pas besoin d'ajouter un argument d'interface.
Le code principal est simple :
- Nous obtenons tous les adaptateurs connectés en utilisant la fonction get_connected_adapters_mac_address().
- Nous recevons l'entrée de l'utilisateur indiquant l'adaptateur à cibler.
- Nous utilisons la fonction change_mac_address() pour changer l'adresse MAC pour le nom de transport de l'adaptateur donné.
- Nous désactivons et activons l'adaptateur en utilisant respectivement les fonctions disable_adapter() et enable_adapter(), afin que le changement d'adresse MAC soit pris en compte.
Bien, nous avons fini avec le script. Avant de le tester, vous devez vous assurer que vous l'exécutez en tant qu'administrateur. J'ai nommé le script mac_address_changer_windows.py :
$ python mac_address_changer_windows.py --help
Résultat :
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
Essayons avec une adresse MAC aléatoire :
$ python mac_address_changer_windows.py --random
Résultat :
#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
Le programme me demande de choisir l'adaptateur, j'ai choisi le premier, et l'adresse MAC est changée en une adresse MAC aléatoire. Confirmons avec la commande getmac :
$ getmac
Résultat :
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}
L'opération a en effet réussi ! Essayons maintenant avec une adresse MAC spécifique :
$ python mac_address_changer_windows.py -m EE:DE:AD:BE:EF:EE
Résultat :
#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
Voici le code source complet pour les systèmes Windows.
mac_address_changer_windows.py
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})")
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()
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
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()
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
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
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")
Conclusion
Bien ! Dans ce tutoriel, vous avez appris comment créer un changeur d'adresse MAC sur n'importe quelle machine Linux ou Windows.
Si vous n'avez pas la commande ifconfig installée, vous devez l'installer via apt install net-tools sur Debian/Ubuntu ou yum install net-tools sur Fedora/CentOS.
VEUILLEZ NOTER QUE NOUS NE PRENONS AUCUNE RESPONSABILITÉ SI VOUS UTILISEZ MAL LE SCRIPT FOURNI DANS CE TUTORIEL ; RESTEZ ÉTHIQUE !