Sitemap
nick3499

nick3499

coder of JavaScript and Python

Spoof MAC Address

4 min readMay 12, 2021

--

Using Bash terminal emulator in a Linux distro

Press enter or click to view image in full size
screen capture of Python script

Not Every Hex Pair Can Be Assigned

The OUI database was used because the random number generator will occassionally return values which the Linux routing socket (RTNETLINK) is unable to assign—based on the specific bits used, and the routing rules which must be followed. So, why not use actual existing OUIs? (yeah, I know the database is excessive ☺).

Munging OUIs from OUI Database

First, I downloaded the database of OUIs from standards-oui.ieee.org/oui/oui.txt using the curl utility:

$ curl standards-oui.ieee.org/oui/oui.txt -O

Which returned a huge text database of OUIs in the wild:

...00-22-72   (hex)		American Micro-Fuel Device Corp.
002272 (base 16) American Micro-Fuel Device Corp.
2181 Buchanan Loop
Ferndale WA 98248
US

00-D0-EF (hex) IGT
00D0EF (base 16) IGT
9295 PROTOTYPE DRIVE
RENO NV 89511
US

08-61-95 (hex) Rockwell Automation
086195 (base 16) Rockwell Automation
1 Allen-Bradley Dr.
Mayfield Heights OH 44124-6118
US

F4-BD-9E (hex) Cisco Systems, Inc
F4BD9E (base 16) Cisco Systems, Inc
80 West Tasman Drive
San Jose CA 94568
US
...

Then I grepped only the lines containing hyphenated OUIs from oui.txt, and redirected that stream into another text file:

$ grep -h '[A-Z0-9][A-Z0-9]-[A-Z0-9][A-Z0-9]-[A-Z0-9][A-Z0-9]' oui.txt > oui-hyphenated.txt

Which returned a gazillion OUIs based on the format seen below:

...
10-FA-CE (hex) Reacheng Communication Technology Co.,Ltd
94-70-D2 (hex) WINFIRM TECHNOLOGY
A4-4A-D3 (hex) ST Electronics(Shanghai) Co.,Ltd
7C-B1-77 (hex) Satelco AG
CC-30-80 (hex) VAIO Corporation
58-7B-E9 (hex) AirPro Technology India Pvt. Ltd
8C-18-D9 (hex) Shenzhen RF Technology Co., Ltd
C4-BD-6A (hex) SKF GmbH
C4-01-CE (hex) PRESITION (2000) CO., LTD.
18-71-17 (hex) eta plus electronic gmbh
EC-0E-C4 (hex) Hon Hai Precision Ind. Co.,Ltd.
30-FA-B7 (hex) Tunai Creative
08-09-B6 (hex) Masimo Corp
4C-F5-A0 (hex) Scalable Network Technologies Inc
D8-FB-11 (hex) AXACORE
4C-E9-33 (hex) RailComm, LLC
CC-E1-7F (hex) Juniper Networks
...

Next, I used a standard text editor to remove all of the commas, since I was going to convert oui-hyphenated.txt into a CSV database with two columns. Then I used the text editor’s find-and-replace option to change each (hex) to a comma (including spaces):

...
10-FA-CE,Reacheng Communication Technology Co. Ltd
94-70-D2,WINFIRM TECHNOLOGY
A4-4A-D3,ST Electronics(Shanghai) Co. Ltd
7C-B1-77,Satelco AG
CC-30-80,VAIO Corporation
58-7B-E9,AirPro Technology India Pvt. Ltd
8C-18-D9,Shenzhen RF Technology Co. Ltd
C4-BD-6A,SKF GmbH
C4-01-CE,PRESITION (2000) CO. LTD.
18-71-17,eta plus electronic gmbh
EC-0E-C4,Hon Hai Precision Ind. Co. Ltd.
30-FA-B7,Tunai Creative
08-09-B6,Masimo Corp
4C-F5-A0,Scalable Network Technologies Inc
D8-FB-11,AXACORE
4C-E9-33,RailComm LLC
CC-E1-7F,Juniper Networks
...

Which left me with oui.csv—a two-column database of comma-separated values. That CSV file is then opened as a file object, see next section:

Rundown of Instructions

  • with open('csv/oui.csv') as csv_f: defines a with statement which opens csv/oui.csv and returns a file object.
  • reader(csv_file) returns a csv.reader object.
  • oui_list lists organizationally unique identifiers (OUIs).
for rec in csv_reader:
oui_list.append(rec[0])

The for loop above generates the OUI list stored in oui_list.

  • oui_list[ri(0, len(oui_list))] returns a hyphenated, pseudo-random OUI using the random.randint method.
  • since the OUIs listed in oui_list are hypenated, the pseudo-randomly-selected OUI must then replace the hyphens with colons using ':'.join(oui_h.split('-')).
  • f"{hex(ri(16, 256))[2:]}:{hex(ri(16, 256))[2:]}:{hex(ri(16, 256))[2:]}" returns the totally pseudo-random right side of the MAC address.
  • print(f"{oui}:{mac_rgt}") prints the MAC address in the terminal emulator for the user to view.
  • run(["sudo", "ip", "link", "set", "enp2s0", "address", f"{oui}:{mac_rgt}"], check=True) finally passes arguments for the terminal emulator (in this case, Bash).

csv.reader

csv.reader receives the CSV database file oui.csv, iterates over its data records, and then returns a reader object. oui.csv supports the iterator protocol and returns each record in list form each time the __next__ method is called.

>>> from csv import reader
>>> with open('csv/oui.csv') as csv_file:
··· csv_reader = reader(csv_file)
···
>>> csv_reader
<_csv.reader object at 0x7fcb8c3a8c80>

One advantage to using a with statement is that it will also close the file after it is through with it, leaving behind a _csv.reader object.

random.randint

from random import randint as ri

random.randint builds a range object and returns a pseudo-random integer from a range(start, stop) method call.

Get nick3499’s stories in your inbox

Join Medium for free to get updates from this writer.

Along with the hex method, the randint method can be used to generate two-digit hexadecimal values which are then used in the spoofed MAC address.

>>> from random import randint as ri
>>> hex(ri(16, 256))[2:]
'82'
>>> hex(ri(16, 256))[2:]
'85'
>>> hex(ri(16, 256))[2:]
'2b'
>>>

subprocess.run

from subprocess import run

subprocess.run runs the command described by args, waits for that command to complete, then returns a CompletedProcess instance.

run(["sudo", "ip", "link", "set", "enp2s0", "address", f"{oui}:{mac_rgt}"], check=True)

The args in quotes above are passed to the terminal emulator. See example below:

$ sudo ip link set enp2s0 address 00:09:03:18:23:7d

Reference Repo

--

nick3499
nick3499

Written by nick3499

coder of JavaScript and Python