1
+ import subprocess
2
+ import regex as re
3
+ import string
4
+ import random
5
+
6
+ # the registry path of network interfaces
7
+ network_interface_reg_path = r"HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Class\\{4d36e972-e325-11ce-bfc1-08002be10318}"
8
+ # the transport name regular expression, looks like {AF1B45DB-B5D4-46D0-B4EA-3E18FA49BF5F}
9
+ transport_name_regex = re .compile ("{.+}" )
10
+ # the MAC address regular expression
11
+ mac_address_regex = re .compile (r"([A-Z0-9]{2}[:-]){5}([A-Z0-9]{2})" )
12
+
13
+ def get_random_mac_address ():
14
+ """Generate and return a MAC address in the format of WINDOWS"""
15
+ # get the hexdigits uppercased
16
+ uppercased_hexdigits = '' .join (set (string .hexdigits .upper ()))
17
+ # 2nd character must be 2, 4, A, or E
18
+ return random .choice (uppercased_hexdigits ) + random .choice ("24AE" ) + "" .join (random .sample (uppercased_hexdigits , k = 10 ))
19
+
20
+
21
+ def clean_mac (mac ):
22
+ """Simple function to clean non hexadecimal characters from a MAC address
23
+ mostly used to remove '-' and ':' from MAC addresses and also uppercase it"""
24
+ return "" .join (c for c in mac if c in string .hexdigits ).upper ()
25
+
26
+
27
+ def get_connected_adapters_mac_address ():
28
+ # make a list to collect connected adapter's MAC addresses along with the transport name
29
+ connected_adapters_mac = []
30
+ # use the getmac command to extract
31
+ for potential_mac in subprocess .check_output ("getmac" ).decode ().splitlines ():
32
+ # parse the MAC address from the line
33
+ mac_address = mac_address_regex .search (potential_mac )
34
+ # parse the transport name from the line
35
+ transport_name = transport_name_regex .search (potential_mac )
36
+ if mac_address and transport_name :
37
+ # if a MAC and transport name are found, add them to our list
38
+ connected_adapters_mac .append ((mac_address .group (), transport_name .group ()))
39
+ return connected_adapters_mac
40
+
41
+
42
+ def get_user_adapter_choice (connected_adapters_mac ):
43
+ # print the available adapters
44
+ for i , option in enumerate (connected_adapters_mac ):
45
+ print (f"#{ i } : { option [0 ]} , { option [1 ]} " )
46
+ if len (connected_adapters_mac ) <= 1 :
47
+ # when there is only one adapter, choose it immediately
48
+ return connected_adapters_mac [0 ]
49
+ # prompt the user to choose a network adapter index
50
+ try :
51
+ choice = int (input ("Please choose the interface you want to change the MAC address:" ))
52
+ # return the target chosen adapter's MAC and transport name that we'll use later to search for our adapter
53
+ # using the reg QUERY command
54
+ return connected_adapters_mac [choice ]
55
+ except :
56
+ # if -for whatever reason- an error is raised, just quit the script
57
+ print ("Not a valid choice, quitting..." )
58
+ exit ()
59
+
60
+
61
+ def change_mac_address (adapter_transport_name , new_mac_address ):
62
+ # use reg QUERY command to get available adapters from the registry
63
+ output = subprocess .check_output (f"reg QUERY " + network_interface_reg_path .replace ("\\ \\ " , "\\ " )).decode ()
64
+ for interface in re .findall (rf"{ network_interface_reg_path } \\\d+" , output ):
65
+ # get the adapter index
66
+ adapter_index = int (interface .split ("\\ " )[- 1 ])
67
+ interface_content = subprocess .check_output (f"reg QUERY { interface .strip ()} " ).decode ()
68
+ if adapter_transport_name in interface_content :
69
+ # if the transport name of the adapter is found on the output of the reg QUERY command
70
+ # then this is the adapter we're looking for
71
+ # change the MAC address using reg ADD command
72
+ changing_mac_output = subprocess .check_output (f"reg add { interface } /v NetworkAddress /d { new_mac_address } /f" ).decode ()
73
+ # print the command output
74
+ print (changing_mac_output )
75
+ # break out of the loop as we're done
76
+ break
77
+ # return the index of the changed adapter's MAC address
78
+ return adapter_index
79
+
80
+
81
+ def disable_adapter (adapter_index ):
82
+ # use wmic command to disable our adapter so the MAC address change is reflected
83
+ disable_output = subprocess .check_output (f"wmic path win32_networkadapter where index={ adapter_index } call disable" ).decode ()
84
+ return disable_output
85
+
86
+
87
+ def enable_adapter (adapter_index ):
88
+ # use wmic command to enable our adapter so the MAC address change is reflected
89
+ enable_output = subprocess .check_output (f"wmic path win32_networkadapter where index={ adapter_index } call enable" ).decode ()
90
+ return enable_output
91
+
92
+
93
+ if __name__ == "__main__" :
94
+ import argparse
95
+ parser = argparse .ArgumentParser (description = "Python Windows MAC changer" )
96
+ parser .add_argument ("-r" , "--random" , action = "store_true" , help = "Whether to generate a random MAC address" )
97
+ parser .add_argument ("-m" , "--mac" , help = "The new MAC you want to change to" )
98
+ args = parser .parse_args ()
99
+ if args .random :
100
+ # if random parameter is set, generate a random MAC
101
+ new_mac_address = get_random_mac_address ()
102
+ elif args .mac :
103
+ # if mac is set, use it after cleaning
104
+ new_mac_address = clean_mac (args .mac )
105
+
106
+ connected_adapters_mac = get_connected_adapters_mac_address ()
107
+ old_mac_address , target_transport_name = get_user_adapter_choice (connected_adapters_mac )
108
+ print ("[*] Old MAC address:" , old_mac_address )
109
+ adapter_index = change_mac_address (target_transport_name , new_mac_address )
110
+ print ("[+] Changed to:" , new_mac_address )
111
+ disable_adapter (adapter_index )
112
+ print ("[+] Adapter is disabled" )
113
+ enable_adapter (adapter_index )
114
+ print ("[+] Adapter is enabled again" )
0 commit comments