Files
local_machine/docs/security/spoof-wifi-mac.sh
2026-03-14 20:03:57 +03:00

363 lines
11 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/zsh
# Advanced Wi-Fi MAC spoofing script for macOS
# Automatically detects phone hotspot MAC or allows manual input
# Usage:
# spoof-wifi-mac.sh # auto-detect connected hotspot MAC
# spoof-wifi-mac.sh --phone-mac # detect phone MAC from hotspot
# spoof-wifi-mac.sh AA:BB:CC:DD:EE:FF # set specific MAC
# spoof-wifi-mac.sh --revert # restore original MAC
set -euo pipefail
# Get absolute path to script
if [ -n "${ZSH_VERSION:-}" ]; then
SCRIPT_PATH="${0:A}"
else
SCRIPT_PATH="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")"
fi
# Fallback if still empty
if [ -z "$SCRIPT_PATH" ] || [ ! -f "$SCRIPT_PATH" ]; then
SCRIPT_PATH="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")"
fi
STATE_FILE="/tmp/wifi_mac_spoof_state"
ORIGINAL_MAC_FILE="/tmp/wifi_mac_original"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
require_root() {
if [ "$EUID" -ne 0 ] && [ "$(id -u)" -ne 0 ]; then
echo -e "${YELLOW}Re-running with sudo...${NC}"
exec sudo -E "$0" "${@}"
fi
}
detect_wifi_if() {
local iface
iface=$(networksetup -listallhardwareports | awk '/Wi-Fi/{getline; print $2; exit}')
if [ -z "$iface" ]; then
echo -e "${RED}Error: Could not detect Wi-Fi interface${NC}"
exit 1
fi
echo "$iface"
}
get_current_mac() {
local iface="$1"
ifconfig "$iface" 2>/dev/null | awk '/ether/{print $2; exit}' || echo ""
}
get_connected_network() {
local iface="$1"
/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport -I 2>/dev/null | awk '/ SSID:/ {print substr($0, index($0,$2))}' || echo ""
}
get_connected_bssid() {
local iface="$1"
/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport -I 2>/dev/null | awk '/ BSSID:/ {print $2}' || echo ""
}
detect_phone_hotspot_mac() {
local iface="$1"
local bssid
echo -e "${BLUE}Detecting connected hotspot MAC...${NC}"
bssid=$(get_connected_bssid "$iface")
if [ -z "$bssid" ] || [ "$bssid" = "none" ]; then
echo -e "${YELLOW}Warning: Not connected to Wi-Fi or cannot detect BSSID${NC}"
return 1
fi
echo -e "${GREEN}Found hotspot BSSID: $bssid${NC}"
echo "$bssid"
return 0
}
validate_mac() {
local mac="$1"
if ! [[ "$mac" =~ ^([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}$ ]]; then
echo -e "${RED}Invalid MAC format: $mac (expected AA:BB:CC:DD:EE:FF)${NC}"
exit 1
fi
}
power_wifi() {
local iface="$1"
local state="$2" # on|off
networksetup -setairportpower "$iface" "$state" 2>/dev/null || true
sleep 1
}
save_original_mac() {
local iface="$1"
local mac="$2"
if [ ! -f "$ORIGINAL_MAC_FILE" ]; then
echo "$iface|$mac" > "$ORIGINAL_MAC_FILE"
echo -e "${GREEN}Saved original MAC for permanent restore: $mac${NC}"
fi
}
check_sip_status() {
local sip_status
sip_status=$(csrutil status 2>/dev/null | grep -i "enabled" || echo "unknown")
if [[ "$sip_status" == *"enabled"* ]]; then
return 0 # SIP enabled
else
return 1 # SIP disabled or unknown
fi
}
set_mac() {
local iface="$1"
local mac="$2"
local current_mac
current_mac=$(get_current_mac "$iface")
if [ -z "$current_mac" ]; then
echo -e "${RED}Error: Cannot read current MAC address${NC}"
exit 1
fi
echo -e "${BLUE}Current MAC: $current_mac${NC}"
echo -e "${BLUE}Target MAC: $mac${NC}"
if [ "$current_mac" = "$mac" ]; then
echo -e "${YELLOW}MAC already set to target value${NC}"
return 0
fi
# Check SIP status
if check_sip_status; then
echo -e "${YELLOW}⚠ System Integrity Protection (SIP) is enabled${NC}"
echo -e "${YELLOW}MAC spoofing may be blocked on Apple Silicon with SIP enabled${NC}"
fi
# Save original MAC if not saved
save_original_mac "$iface" "$current_mac"
# Save for revert
echo "$iface $current_mac" > "$STATE_FILE"
echo -e "${YELLOW}Turning Wi-Fi off...${NC}"
power_wifi "$iface" off
echo -e "${YELLOW}Setting MAC to $mac...${NC}"
# Try ifconfig method
local success=false
if ifconfig "$iface" ether "$mac" 2>/dev/null; then
success=true
fi
if [ "$success" = false ]; then
echo -e "${RED}✗ Error: Failed to set MAC address${NC}"
echo ""
echo -e "${BLUE}=== РЕШЕНИЕ ПРОБЛЕМЫ ===${NC}"
echo ""
if check_sip_status; then
echo -e "${YELLOW}На Apple Silicon (M1/M2/M3) с включенным SIP подмена MAC заблокирована${NC}"
echo ""
echo -e "${YELLOW}Варианты решения:${NC}"
echo "1. Отключить SIP (НЕ рекомендуется - снижает безопасность)"
echo " - Перезагрузите в Recovery Mode (Cmd+R)"
echo " - Утилиты → Терминал → csrutil disable"
echo " - Перезагрузите Mac"
echo ""
echo "2. Использовать альтернативные методы:"
echo " • VPN на телефоне (рекомендуется)"
echo " • USB Tethering вместо Wi-Fi hotspot"
echo " • Bluetooth Tethering"
echo ""
echo -e "${BLUE}Важно:${NC}"
echo "Оператор сотовой связи видит IMEI телефона, а не MAC MacBook."
echo "MAC клиента виден только на уровне локальной Wi-Fi сети."
echo "Подмена MAC не меняет идентификацию на уровне оператора."
else
echo -e "${YELLOW}Интерфейс может не поддерживать подмену MAC${NC}"
echo -e "${YELLOW}Или требуется дополнительная настройка${NC}"
fi
power_wifi "$iface" on
exit 1
fi
echo -e "${YELLOW}Turning Wi-Fi on...${NC}"
power_wifi "$iface" on
sleep 2
local new_mac
new_mac=$(get_current_mac "$iface")
if [ "$new_mac" = "$mac" ]; then
echo -e "${GREEN}✓ Success! MAC changed to: $new_mac${NC}"
else
echo -e "${RED}⚠ Warning: MAC may not have changed${NC}"
echo -e "${YELLOW}Current MAC: $new_mac${NC}"
echo -e "${YELLOW}Target MAC: $mac${NC}"
echo -e "${YELLOW}This may require disabling SIP or using a different method${NC}"
fi
}
revert_mac() {
local iface
local original_mac
if [ -f "$STATE_FILE" ]; then
read iface original_mac < "$STATE_FILE"
elif [ -f "$ORIGINAL_MAC_FILE" ]; then
local saved
saved=$(cat "$ORIGINAL_MAC_FILE")
iface=$(echo "$saved" | cut -d'|' -f1)
original_mac=$(echo "$saved" | cut -d'|' -f2)
else
echo -e "${RED}No saved MAC found. Cannot revert.${NC}"
exit 1
fi
if [ -z "${iface:-}" ] || [ -z "${original_mac:-}" ]; then
echo -e "${RED}State file is corrupted. Delete $STATE_FILE and $ORIGINAL_MAC_FILE${NC}"
exit 1
fi
echo -e "${BLUE}Restoring MAC for $iface to $original_mac...${NC}"
power_wifi "$iface" off
ifconfig "$iface" ether "$original_mac" 2>/dev/null || {
echo -e "${RED}Failed to restore MAC${NC}"
power_wifi "$iface" on
exit 1
}
power_wifi "$iface" on
sleep 2
rm -f "$STATE_FILE"
local current
current=$(get_current_mac "$iface")
echo -e "${GREEN}✓ Reverted. Current MAC: $current${NC}"
}
show_instructions() {
echo -e "${BLUE}=== ИНСТРУКЦИИ ПО ПОЛУЧЕНИЮ MAC ТЕЛЕФОНА ===${NC}"
echo ""
echo -e "${YELLOW}iPhone:${NC}"
echo "1. Настройки → Wi-Fi"
echo "2. Нажмите (i) рядом с сетью"
echo "3. Отключите 'Частный Wi-Fi адрес' (Private Wi-Fi Address)"
echo "4. MAC-адрес будет показан как 'Адрес Wi-Fi'"
echo ""
echo -e "${YELLOW}Android:${NC}"
echo "1. Настройки → О телефоне → Статус"
echo "2. Найдите 'MAC-адрес Wi-Fi'"
echo ""
echo -e "${YELLOW}Альтернативный способ (если подключены к hotspot):${NC}"
echo "Скрипт может автоматически определить MAC точки доступа"
echo "Используйте: $0 --phone-mac"
echo ""
}
main() {
# Check if we need root and restart with sudo if needed
# Skip check for help/instructions commands that don't need root
local arg="${1:-}"
local needs_root=false
if [ "$arg" != "--help" ] && [ "$arg" != "-h" ] && [ "$arg" != "--instructions" ]; then
needs_root=true
fi
if [ "$needs_root" = true ] && [ "$(id -u)" -ne 0 ]; then
echo -e "${YELLOW}Re-running with sudo...${NC}"
exec sudo -E "$SCRIPT_PATH" "${@}"
exit 0
fi
if [ "$arg" = "--help" ] || [ "$arg" = "-h" ]; then
echo "Usage: $0 [OPTIONS] [MAC_ADDRESS]"
echo ""
echo "Options:"
echo " --phone-mac Auto-detect phone hotspot MAC"
echo " --revert Restore original MAC"
echo " --instructions Show instructions for finding phone MAC"
echo " --help Show this help"
echo ""
echo "Examples:"
echo " $0 # Interactive mode"
echo " $0 --phone-mac # Auto-detect hotspot MAC"
echo " $0 AA:BB:CC:DD:EE:FF # Set specific MAC"
echo " $0 --revert # Restore original"
exit 0
fi
if [ "$arg" = "--instructions" ]; then
show_instructions
exit 0
fi
if [ "$arg" = "--revert" ]; then
revert_mac
exit 0
fi
local iface
iface=$(detect_wifi_if)
echo -e "${GREEN}Wi-Fi interface: $iface${NC}"
local target_mac=""
if [ "$arg" = "--phone-mac" ]; then
target_mac=$(detect_phone_hotspot_mac "$iface")
if [ -z "$target_mac" ]; then
echo -e "${RED}Could not detect phone hotspot MAC${NC}"
echo -e "${YELLOW}Make sure you're connected to phone hotspot and try manual input${NC}"
show_instructions
exit 1
fi
elif [ -n "$arg" ]; then
target_mac="$arg"
else
# Try auto-detect first
local detected
detected=$(detect_phone_hotspot_mac "$iface" 2>/dev/null || echo "")
if [ -n "$detected" ]; then
echo -e "${GREEN}Detected hotspot MAC: $detected${NC}"
read "confirm?Use this MAC? (y/n): "
if [[ "$confirm" =~ ^[Yy] ]]; then
target_mac="$detected"
else
read "target_mac?Enter phone Wi-Fi MAC (AA:BB:CC:DD:EE:FF): "
fi
else
show_instructions
read "target_mac?Enter phone Wi-Fi MAC (AA:BB:CC:DD:EE:FF): "
fi
fi
if [ -z "$target_mac" ]; then
echo -e "${RED}No MAC address provided${NC}"
exit 1
fi
validate_mac "$target_mac"
set_mac "$iface" "$target_mac"
echo ""
echo -e "${BLUE}=== ВАЖНО ===${NC}"
echo -e "${YELLOW}• MAC сбросится после перезагрузки или переподключения Wi-Fi${NC}"
echo -e "${YELLOW}• Используйте '$0 --revert' для восстановления${NC}"
echo -e "${YELLOW}• Для постоянной подмены может потребоваться отключение SIP${NC}"
echo -e "${YELLOW}• Оператор видит трафик через точку доступа, MAC клиента виден только на уровне Wi-Fi${NC}"
}
main "$@"