-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathM474.py
More file actions
325 lines (275 loc) · 11.5 KB
/
Copy pathM474.py
File metadata and controls
325 lines (275 loc) · 11.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
import subprocess
import os
import random
import re
import requests
import platform
import sys
import json
# Terminal colors
class Colors:
GREEN = '\033[92m'
RED = '\033[91m'
YELLOW = '\033[93m'
NC = '\033[0m'
BANNER = Colors.YELLOW + r"""
... .. ..
x*8888x.:*8888: -"888: xeee dL ud8Nu :8c xeee
X 48888X `8888H 8888 d888R 8Fd888888L %8 d888R
X8x. 8888X 8888X !888> d8888R 4N88888888cuR d8888R
X8888 X8888 88888 "*8%- @ 8888R 4F ^""%""d @ 8888R
'*888!X8888> X8888 xH8> .P 8888R d .z8 .P 8888R
`?8 `8888 X888X X888> :F 8888R ^ z888 :F 8888R
-^ '888" X888 8888> x" 8888R d8888' x" 8888R
dx '88~x. !88~ 8888> d8eeeee88888eer 888888 d8eeeee88888eer
.8888Xf.888x:! X888X.: 8888R :888888 8888R
:""888":~"888" `888*" 8888R 888888 8888R
"~' "~ "" "*%%%%%%**~ '%**% "*%%%%%%**~
""" + Colors.NC
SEP = Colors.GREEN + "=" * 67 + Colors.NC
BACKUP_FILE = os.path.expanduser("~/.mac_spoofer_backup.json")
# ---------- Backup helpers ----------
def load_backup():
if not os.path.exists(BACKUP_FILE):
return {}
try:
with open(BACKUP_FILE, "r", encoding="utf-8") as f:
return json.load(f)
except Exception:
return {}
def save_backup(data):
try:
with open(BACKUP_FILE, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2)
except Exception as e:
print(Colors.RED + f"[!] Failed to save backup file: {e}" + Colors.NC)
# ---------- IP helpers ----------
def get_internal_ip():
system = platform.system()
try:
if system == "Windows":
output = subprocess.check_output(["ipconfig"], encoding="utf-8", errors="ignore")
matches = re.findall(r"IPv4 Address[^\n:]*:\s*([\d.]+)", output)
# skip APIPA 169.254.x.x
for ip in matches:
if not ip.startswith("169.254."):
return ip
return matches[0] if matches else None
else:
output = subprocess.check_output(["hostname", "-I"], encoding="utf-8")
ips = [ip for ip in output.split() if ip and not ip.startswith("127.")]
return ips[0] if ips else None
except Exception as e:
print(Colors.RED + f"[!] Error getting internal IP: {e}" + Colors.NC)
return None
def get_external_ip(timeout=5):
try:
resp = requests.get("https://api.ipify.org", timeout=timeout)
resp.raise_for_status()
return resp.text.strip()
except requests.RequestException as e:
print(Colors.RED + f"[!] Error fetching external IP: {e}" + Colors.NC)
return None
# ---------- Linux interface / MAC helpers ----------
def detect_primary_interface_linux():
# Prefer `ip` output
try:
output = subprocess.check_output(["ip", "-o", "link", "show"], encoding="utf-8")
candidates = []
for line in output.splitlines():
m = re.match(r"\d+:\s+([^:]+):\s+<([^>]+)>", line)
if not m:
continue
name, flags = m.group(1), m.group(2).split(",")
if name == "lo":
continue
candidates.append((name, flags))
# Prefer interfaces that are UP
for name, flags in candidates:
if "UP" in flags:
return name
# Fallback: first non-lo
return candidates[0][0] if candidates else None
except Exception:
# Fallback to ifconfig
try:
output = subprocess.check_output(["ifconfig"], encoding="utf-8", errors="ignore")
blocks = re.split(r"\n(?=\S)", output)
for block in blocks:
if block.startswith("lo"):
continue
name = block.split()[0]
return name
except Exception:
return None
return None
def get_current_mac_linux(iface):
# Try sysfs first
path = f"/sys/class/net/{iface}/address"
try:
with open(path, "r", encoding="utf-8") as f:
mac = f.read().strip()
if mac:
return mac
except Exception:
pass
# Fallback to `ip`
try:
output = subprocess.check_output(["ip", "link", "show", iface], encoding="utf-8", errors="ignore")
m = re.search(r"link/\w+\s+([0-9a-fA-F:]{17})", output)
if m:
return m.group(1)
except Exception:
pass
return None
def generate_random_mac():
# Locally administered unicast MAC (LAA)
# 1st octet: set local bit (0x02), ensure unicast (LSB = 0)
first_octet = 0x02
mac_bytes = [first_octet] + [random.randint(0x00, 0xFF) for _ in range(5)]
return ":".join(f"{b:02x}" for b in mac_bytes)
def change_mac_linux(iface):
original_mac = get_current_mac_linux(iface)
if not original_mac:
print(Colors.RED + f"[!] Could not determine current MAC for {iface}" + Colors.NC)
return None, None
backup = load_backup()
if iface not in backup:
backup[iface] = original_mac
save_backup(backup)
new_mac = generate_random_mac()
try:
subprocess.run(["ip", "link", "set", "dev", iface, "down"], check=True)
subprocess.run(["ip", "link", "set", "dev", iface, "address", new_mac], check=True)
subprocess.run(["ip", "link", "set", "dev", iface, "up"], check=True)
return original_mac, new_mac
except subprocess.CalledProcessError as e:
print(Colors.RED + f"[!] Failed to change MAC on {iface}: {e}" + Colors.NC)
return None, None
def revert_mac_linux(iface):
backup = load_backup()
original_mac = backup.get(iface)
if not original_mac:
print(Colors.RED + f"[!] No backup MAC found for {iface}. Cannot revert." + Colors.NC)
return False
try:
subprocess.run(["ip", "link", "set", "dev", iface, "down"], check=True)
subprocess.run(["ip", "link", "set", "dev", iface, "address", original_mac], check=True)
subprocess.run(["ip", "link", "set", "dev", iface, "up"], check=True)
print(Colors.GREEN + f"[+] Reverted {iface} MAC to {original_mac}" + Colors.NC)
return True
except subprocess.CalledProcessError as e:
print(Colors.RED + f"[!] Failed to revert MAC on {iface}: {e}" + Colors.NC)
return False
# ---------- IP renew ----------
def renew_ip(system, iface=None):
print(Colors.YELLOW + "[*] Renewing IP address..." + Colors.NC)
try:
if system == "Windows":
subprocess.run(["ipconfig", "/release"], check=False)
subprocess.run(["ipconfig", "/renew"], check=False)
else:
# Best-effort: try iface-specific dhclient, then generic
if iface:
subprocess.run(["dhclient", "-r", iface], check=False)
subprocess.run(["dhclient", iface], check=False)
else:
subprocess.run(["dhclient", "-r"], check=False)
subprocess.run(["dhclient"], check=False)
except Exception as e:
print(Colors.RED + f"[!] Error renewing IP: {e}" + Colors.NC)
# ---------- Main ----------
def main():
import argparse
parser = argparse.ArgumentParser(description="Simple IP & MAC changer")
parser.add_argument("--revert", action="store_true",
help="Revert MAC to original (Linux only)")
parser.add_argument("--iface",
help="Network interface to use (Linux only, auto-detected if omitted)")
parser.add_argument("--no-ip-renew", action="store_true",
help="Do not renew IP after MAC change/revert")
args = parser.parse_args()
system = platform.system()
print(BANNER)
print(SEP)
is_linux = (system == "Linux")
if is_linux:
if hasattr(os, "geteuid") and os.geteuid() != 0:
print(Colors.RED + "[!] This script should be run as root on Linux for MAC/IP changes." + Colors.NC)
print(Colors.YELLOW + "[i] It will still show info but will NOT modify MAC/IP." + Colors.NC)
can_modify = False
else:
can_modify = True
else:
can_modify = False # MAC spoofing not implemented for Windows in this script
iface = None
if is_linux:
iface = args.iface or detect_primary_interface_linux()
if not iface:
print(Colors.RED + "[!] Could not detect a primary network interface." + Colors.NC)
else:
print(Colors.GREEN + f"[+] Using interface: {iface}" + Colors.NC)
# Show current MAC (Linux) or adapters (Windows)
if is_linux and iface:
cur_mac = get_current_mac_linux(iface)
if cur_mac:
print("Current MAC address:", Colors.GREEN + cur_mac + Colors.NC)
elif system == "Windows":
try:
output = subprocess.check_output(["getmac"], encoding="utf-8", errors="ignore")
print("Current MAC addresses:\n" + Colors.GREEN + output + Colors.NC)
except Exception as e:
print(Colors.RED + f"[!] Failed to get MAC addresses on Windows: {e}" + Colors.NC)
# IP info (before)
internal_ip = get_internal_ip()
external_ip = get_external_ip()
if internal_ip:
print("Internal IP address:", Colors.GREEN + internal_ip + Colors.NC)
if external_ip:
print("External IP address:", Colors.GREEN + external_ip + Colors.NC)
print(SEP)
# ----- Revert flow -----
if args.revert:
if not is_linux or not iface:
print(Colors.RED + "[!] Revert is only supported on Linux with a valid interface." + Colors.NC)
sys.exit(1)
if not can_modify:
print(Colors.RED + "[!] Cannot revert MAC without root privileges." + Colors.NC)
sys.exit(1)
revert_mac_linux(iface)
if not args.no_ip_renew:
renew_ip(system, iface)
print(SEP)
new_internal = get_internal_ip()
new_external = get_external_ip()
if new_internal:
print("Current internal IP:", Colors.GREEN + new_internal + Colors.NC)
if new_external:
print("Current external IP:", Colors.GREEN + new_external + Colors.NC)
return
# ----- Change MAC (Linux only) -----
if is_linux and iface and can_modify:
orig_mac, new_mac = change_mac_linux(iface)
if new_mac:
print("New MAC address:", Colors.GREEN + new_mac + Colors.NC)
else:
print(Colors.RED + "[!] MAC was not changed." + Colors.NC)
elif is_linux and not can_modify:
print(Colors.YELLOW + "[i] Skipping MAC change because we are not root." + Colors.NC)
else:
print(Colors.YELLOW + "[i] MAC spoofing is not supported on this OS in this script." + Colors.NC)
# Renew IP unless disabled
if not args.no_ip_renew and (is_linux and can_modify or system == "Windows"):
renew_ip(system, iface if is_linux else None)
print(SEP)
# Show updated IP info
new_internal = get_internal_ip()
new_external = get_external_ip()
if new_internal:
print("New internal IP address:", Colors.GREEN + new_internal + Colors.NC)
if new_external:
print("New external IP address:", Colors.GREEN + new_external + Colors.NC)
if is_linux and iface:
print(Colors.YELLOW + f"\nTo revert {iface} MAC to the original, run this script with --revert" + Colors.NC)
if __name__ == "__main__":
main()