Last active
February 9, 2021 18:59
-
-
Save siraben/c3133b39e470d1aed16fd71f42b8f273 to your computer and use it in GitHub Desktop.
macOS script to collect and dedup MAC addresses from a network
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# SPDX-License-Identifier: MIT | |
# SPDX-FileCopyrightText: 2018 Ben Siraphob <[email protected]> | |
command -v gshuf >/dev/null 2>&1 || { echo >&2 "gshuf is required but is not installed. Run \"brew install coreutils\"."; control_c; } | |
command -v spoof-mac >/dev/null 2>&1 || { echo >&2 "spoof-mac is required but is not installed. Run \"brew install spoof-mac\"."; control_c; } | |
# Colors | |
RED='\033[0;31m' | |
NC='\033[0m' | |
# Location of temporary data file during the run. | |
tmp="./.tmp" | |
# Location of where the MAC addresses (compressed) will be stored. | |
list="./list.txt" | |
# Name of the wireless network that you want the script to run. This | |
# is to prevent accidentally running this script on other networks to | |
# ruin your sweet pure MAC address collection. | |
target_net="Wireless" | |
cleanup() | |
{ | |
rm -f $tmp | |
return $? | |
} | |
control_c() | |
{ | |
(>&2 printf "\n${RED}Aborting...${NC}\n") | |
cleanup | |
exit 1 | |
} | |
# Sometimes the script may take long, so trap C-c and clean up the temporary file. | |
trap control_c SIGINT | |
# Help argument | |
[[ $1 == "--help" ]] && | |
echo "Options: | |
--help Displays this help | |
--collect-only Collects MAC addresses without spoofing | |
--spoof-only Skip collection and spoof a random address" && exit | |
# base64 + gzip reduces list size by a third. (e.g. 15 KB -> 5 KB) | |
# I used base64 encoding because A. it looks cooler but B. you can | |
# send it as plain text via any channel to help "bootstrap" other MAC | |
# address collecting computers. | |
(base64 --decode $list | gunzip) > $tmp | |
# How many MAC addresses do we have so far? | |
prev=$(cat $tmp | wc -l) | |
# If neither the --collect-only or --spoof-only options are supplied | |
# then the program collects AND spoofs. | |
# We're collecting. | |
if [[ $1 != "--spoof-only" ]]; then | |
# Handy trick to determine current network name. | |
currentNet="$(/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I | | |
awk '/ SSID/ {print substr($0, index($0, $2))}')" | |
# Don't ruin our list. Abort if we're connected to the wrong network. | |
[[ $currentNet != $target_net ]] && (>&2 echo "You need to be connected to $target_net\!") && control_c | |
echo "Collecting MAC addresses..." | |
# Easy method to filter MAC addresses of the form XX:XX:XX:XX:XX | |
# where XX is a hexadecimal number. This is often the slowest | |
# part of the script. | |
arp -a | grep -o -E '([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}' >> $tmp | |
# Scrub bad addresses | |
sed -i '' '/ff:ff:ff:ff:ff:ff/d' $tmp | |
# We determine the number of online computers by checking how many | |
# lines we've added. This may include duplicates still. | |
tmplen=$(cat $tmp | wc -l) | |
online=$(($tmplen - $prev)) | |
# Sort and remove duplicates, then compress and base64 encode. | |
(sort -u $tmp) | gzip | base64 > $list | |
new=$(sort -u $tmp | wc -l) | |
# Display status message. | |
echo "From $(($online)) online, added $(($new - $prev)) addresses. Total Collected: $(($new))" | |
fi | |
# We're spoofing. | |
if [[ $1 != "--collect-only" ]]; then | |
# This requires coreutils to be installed | |
mac=$(gshuf -n 1 $tmp) | |
echo "Attempting to spoof as $mac. A root password may be required." | |
sudo spoof-mac set $mac en0 && echo "Spoofed as $mac." | |
fi | |
cleanup | |
exit |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment