Skip to content

Instantly share code, notes, and snippets.

@siraben
Last active February 9, 2021 18:59
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save siraben/c3133b39e470d1aed16fd71f42b8f273 to your computer and use it in GitHub Desktop.
Save siraben/c3133b39e470d1aed16fd71f42b8f273 to your computer and use it in GitHub Desktop.
macOS script to collect and dedup MAC addresses from a network
#!/bin/bash
# SPDX-License-Identifier: MIT
# SPDX-FileCopyrightText: 2018 Ben Siraphob <bensiraphob@gmail.com>
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