DEV Community

Cover image for Changing the MAC Address using Python
Dharmil Chhadva
Dharmil Chhadva

Posted on

Changing the MAC Address using Python

Note: The following tutorial works on any Linux Distributions, but you will need the root access to execute the system commands necessary in order to change the MAC Address successfully.

What is MAC Address?

To learn how to change the MAC Address, it is essential to learn about what a MAC Address is. We all use various electronic gadgets such as smartphones, desktops, laptops, tablets, and many more to browse the internet, for entertainment, among other tasks. Each of these electronic gadgets has its own MAC Address. MAC stands for Media Access Control Address. Every device needs a MAC Address to be uniquely identified by others on the network. For instance, when you watch a video on Youtube, you send a request for the video via your device, and this request is transmitted through your default gateway (usually through a router for a private home network). The router then sends this request to the World Wide Web and receives a response. Now, the World Wide Web (which is public) does not know who you are because your device has a private IP Address that is only recognized by your router, so the response received by the router is then given to you because the router knows your MAC Address associated with the private IP Address of your device.

MAC Address is a 48-bits hardware address that is hardcoded on the Network Interface Card (NIC) at the time of manufacturing. MAC Address is also known as the Physical Address of a device. MAC Addresses are used to transmit packets within the network.

For example, 00:1A:3F:F1:4C:C6 is a MAC Address. The first three octets (00:1A:3F) of the address identifies the manufacturer and is known as OUI (Organizational Unique Identifier). **The last three octets are **Network Interface Controller Specific.

Read more about NIC here.

Why do we need to change the MAC Address?

There are several reasons why you would want to change the MAC Address of your device. Let’s look at them one by one:

  • Increase Anonymity: When on a public network, you might want to change the MAC Address to stay anonymous, if you don’t then there are chances that the network you are on might log your MAC Address and thus leaving behind a trail.

  • Impersonate other devices: When you want to carry out an attack (for testing purposes), changing the MAC Address can be useful to impersonate any legitimate device.

  • Bypassing filters: If a MAC Address is blacklisted to use the network, and to overcome this is to change the MAC Address and fool the filters.

How to change the MAC Address?

To change the MAC Address, we need to execute a few system commands. The first step is to identify the interface whose MAC Address you want to change and you can do this using the following command in Linux.

dcode@dcode-pop-os:~$ ifconfig
Enter fullscreen mode Exit fullscreen mode

The above command produces the following output.

**enp0s3:** flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.2.5  netmask 255.255.255.0  broadcast 10.0.2.255
        **ether 08:00:27:35:21:ff**  txqueuelen 1000  (Ethernet)
        RX packets 13962  bytes 17732985 (17.7 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 7969  bytes 975852 (975.8 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
Enter fullscreen mode Exit fullscreen mode

First of all, to change the MAC Address we need to know the interface name and the existing MAC Address. **This information can be obtained by executing the **ifconfig command. We can get the interface name and the existing MAC Address from the output produced by ifconfig. For instance, from the above output, enp0s3 **is the name of the **interface **and the **ether field on the third line has the MAC Address (08:00:27:35:21:ff in our case).

Now that we know the interface name whose MAC Address we want to change, we can move to the next command.

dcode@dcode-pop-os:~$ sudo ifconfig enp0s3 down
Enter fullscreen mode Exit fullscreen mode

The above command when executed, takes the interface down. What that means is you will no longer be able to connect to the internet. We need to take the interface down (disabling it) first if we need to change the MAC Address. After this, the next command to be executed will change the MAC Address.

dcode@dcode-pop-os:~$ sudo ifconfig enps03 hw ether 00:11:22:33:44:55
Enter fullscreen mode Exit fullscreen mode

The above command changes the existing MAC Address (08:00:27:35:21:FF) to a new MAC Address (00:11:22:33:44:55) specified in the command itself. Now the MAC Address of the interface enp0s3 has been changed but to use it, we need to enable the interface again using the following command.

dcode@dcode-pop-os:~$ sudo ifconfig enp0s3 up
Enter fullscreen mode Exit fullscreen mode

After executing the above command, you enable the interface again so that you can access the internet. To check whether the MAC Address was changed to what we specified, execute the ifconfig command.

dcode@dcode-pop-os:~$ ifconfig
**enp0s3:** flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.2.5  netmask 255.255.255.0  broadcast 10.0.2.255
        **ether 00:11:22:33:44:55**  txqueuelen 1000  (Ethernet)
        RX packets 13997  bytes 17737735 (17.7 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8892  bytes 1059117 (1.0 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
Enter fullscreen mode Exit fullscreen mode

From the output, we can see that the MAC Address was changed to 00:11:22:33:44:55 from 08:00:27:35:21:ff.

Using Python to change the MAC Address

Up until now, we manually typed the commands and executed them but we can automate the entire process using Python so that we just have to provide the script with the interface name and the new MAC Address.

Modules Used:

The subprocess module is used to execute system commands using Python. It contains several functions that can be used. We are going to focus on one particular function that is used to execute the system commands. It is called the **call() **function.

Usage

subprocess.call([‘ifconfig’])
Enter fullscreen mode Exit fullscreen mode

This instruction executes the ifconfig command using Python.

The **argparse **module makes it convenient to write user-friendly command-line interfaces. The program defines the arguments it requires and **argparse **will figure out how to parse these arguments. It also generates help and usage messages and issues errors when the user enters any invalid arguments.

Usage

dcode@dcode-pop-os:~$ python3 programs_name.py -op1 option -op2 option
Enter fullscreen mode Exit fullscreen mode

With the help of argparse we can provide the user with the ability to pass the input values using command-line arguments. Even if you don’t understand now, it will be clear once we start coding 😃.

Next, the re **module provides **Regular Expression matching operations. You’ll know for what we use the re module as we progress ahead.

Python Script Coding

This is where we start coding in Python.

Step 1: Import the modules discussed above.



Step 2: Implementing the functionality to allow the users to pass command line arguments.

To add this feature to our script, we’ll need to make use of the argparse module that we imported in Step 1.


The above code allows the user to provide the input for interface value and new MAC Address as follows:
dcode@dcode-pop-os:~$ python3 mac_changer.py -i interface_name -m new_mac_address
Enter fullscreen mode Exit fullscreen mode

OR

dcode@dcode-pop-os:~$ python3 mac_changer.py --interface interface_name --mac new_mac_address
Enter fullscreen mode Exit fullscreen mode

interface_name = Name of the interface whose MAC Address you want to change.

new_mac_address = MAC Address that you want to replace in place of the old one.

The **options **stores the values provided by the user. When you print it the output is as follow:

print(options)

**Output:** 
Namespace(interface='enp0s3', new_mac='00:55:22:33:44:11')
Enter fullscreen mode Exit fullscreen mode

Individually accessing the **two **arguments is done as follows:

print(options.interface)
print(options.new_mac)

**Output:** 
enp0s3
00:11:22:33:44:55
Enter fullscreen mode Exit fullscreen mode

Note: The dest **argument in the **add_argument() **method provides the name according to which the **parse_args() stores its corresponding values in the **options **variable.

The last thing in Step 2 is we created a variable command_args **and invoked the function **get_args().

command_args = get_args()
Enter fullscreen mode Exit fullscreen mode

The above statement will store the **options **returned by the **get_args() **hence giving us access to the argument values outside of the scope of the function.

Step 3: Writing a function that changes the MAC Address.

Now that we have the two values that we require to change the MAC Address (interface and new MAC Address), *we’ll write a function that changes the MAC Address using system commands.



Look at the function that we just wrote, it accepts **two **arguments *

(interface and new_mac). **The two values are provided to **change_mac()
function by command_args variable. It also checks whether the MAC Address provided is valid or not. After that, using the **subprocess **module we execute the system commands. Note: You require root access to execute these commands.

Now, at this point, we have completed a Python script that changes the MAC Address, but we still need to be sure that the new MAC Address was applied. And for that, we need a write another function that returns the current MAC Address of the interface.

Step 4: Writing a function to get the current MAC Address

This function takes interface as an input and returns the current MAC Address of that interface. We are writing this function to check whether the new MAC address was applied or not.


So, the get_current_mac() function extracts the current MAC Address of the interface provided. Now, let’s break down this function.
output = sub.check_output(['ifconfig', interface], universal_newllines = True)
Enter fullscreen mode Exit fullscreen mode

The above statement is similar to sub.call() in the change_mac() function but there is one difference. The sub.check_output() functions returns the output of the command whereas sub.call() does not return anything. The returned output is stored in the variable output.

Also, the argument universal_newlines = True **is used because if this value is set to **False then the output returned is in bytes.

Official Docs -> By default, this function will return the data as encoded bytes. The actual encoding of the output data may depend on the command being invoked, so the decoding to text will often need to be handled at the application level. This behavior may be overridden by setting universal_newlines to True

The next statement is,

search_mac = re.search(r"\w\w:\w\w:\w\w:\w\w:\w\w:\w\w", output)
Enter fullscreen mode Exit fullscreen mode

This is where the re module is being used. re stands for Regular Expressions and these are often used in string matching applications. The re.search() function accepts the regular expression and the string in which the pattern is supposed to be matched. In our case, the string is stored inside the variable output. *The *\w\w:\w\w:\w\w:\w\w:\w\w:\w\w **expression matches the MAC Address in the output variable which has the output of the **ifconfig command. See the image below to understand it better.

Regex Demonstration

As you can see that the regular expression matches the MAC Address perfectly (Highlighted in green in the Match result box). Regular Expression Cheatsheet

Furthermore, there are chances that re.search() might find more than one string that matches the regex (regular expression). Therefore, the below statement will make sure to return the first matched element only. What if it matches more than one string and returns the string which is not desired? In the output returned by ifconfig, the chances of a getting string other than the desired one is next to zero.

search_mac.group(0)
Enter fullscreen mode Exit fullscreen mode

This sums up the get_current_mac() function.

Now, the only thing remaining is to check whether the MAC Address provided by the user was applied. For this, you can see that we have called get_current_mac() function twice, once before calling change_mac() function and once after calling the change_mac() function. This ensures that we capture both the MAC Addresses (before and after change). We then compare changed_mac and **command_args.new_mac **and if both matches then the MAC Address has been changed successfully.

if changed_mac == command_args.new_mac:
    print('Successfully Changed the MAC Address')
else:
    print('Could not change the MAC Address')
Enter fullscreen mode Exit fullscreen mode

This where the script ends and to execute the script do the following: This was covered in Step 2.

dcode@dcode-pop-os:~$ python3 mac_changer.py -i interface_name -m new_mac_address

**OR**

dcode@dcode-pop-os:~$ python3 mac_changer.py --interface interface_name --mac new_mac_address
Enter fullscreen mode Exit fullscreen mode

The entire code can be found on my Github.

Top comments (0)