spoof-d 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/README.md +250 -0
- package/bin/cmd.js +313 -0
- package/index.js +1115 -0
- package/package.json +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) Feross Aboukhadijeh
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
7
|
+
the Software without restriction, including without limitation the rights to
|
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
10
|
+
subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# spoof-d
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/spoof-d)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](https://github.com/TT5H/spoof-d/network)
|
|
6
|
+
[](https://github.com/TT5H/spoof-d/stargazers)
|
|
7
|
+
|
|
8
|
+
> **✅ Cross-Platform Support**: This is a modernized fork of the original `spoof` project, updated for compatibility with modern macOS (Sequoia 15.4+, Tahoe 26+), Windows 10/11, and Linux. All platforms are now fully supported!
|
|
9
|
+
|
|
10
|
+
### Easily spoof your MAC address on macOS, Windows, and Linux!
|
|
11
|
+
|
|
12
|
+
A Node.js utility for changing MAC addresses across all major platforms. Features reliable macOS support, modern Windows PowerShell integration, and Linux `ip link` commands. This fork includes enhanced error handling, automatic verification, retry logic, and improved cross-platform compatibility.
|
|
13
|
+
|
|
14
|
+
## About This Fork
|
|
15
|
+
|
|
16
|
+
This repository ([TT5H/spoof-d](https://github.com/TT5H/spoof-d)) is a fork of [basedbytes/spoofy](https://github.com/basedbytes/spoofy), which itself is a fork of the original `spoof` project. This fork extends the functionality with full cross-platform support and enhanced features.
|
|
17
|
+
|
|
18
|
+
### What's Changed
|
|
19
|
+
|
|
20
|
+
- **✅ Full Cross-Platform Support**: Complete Windows 10/11 and Linux support (not just macOS)
|
|
21
|
+
- **Modern macOS Support**: Fixed MAC spoofing for macOS Sequoia 15.4+ and Tahoe 26+
|
|
22
|
+
- **Windows Support**: Full Windows 10/11 support using PowerShell and registry methods with automatic fallback
|
|
23
|
+
- **Linux Support**: Modern Linux support using `ip link` commands (replaces deprecated `ifconfig`)
|
|
24
|
+
- **Enhanced Error Handling**: Custom error classes with actionable suggestions and better error messages
|
|
25
|
+
- **Automatic Verification**: Verifies MAC address changes after setting them
|
|
26
|
+
- **Retry Logic**: Automatic retry with exponential backoff for transient failures
|
|
27
|
+
- **Timeout Handling**: Prevents hanging operations with configurable timeouts
|
|
28
|
+
- **Better Validation**: Comprehensive input validation with helpful error messages
|
|
29
|
+
- **Removed `airport` dependency**: The deprecated `airport -z` command has been replaced with modern `networksetup` commands
|
|
30
|
+
- **Timing-sensitive MAC changes**: WiFi MAC addresses are now changed in the brief window after power-on but before network connection
|
|
31
|
+
- **Improved interface detection**: Better cross-platform interface detection using modern system commands
|
|
32
|
+
- **Cleaner codebase**: Removed deprecated code paths and unnecessary constants
|
|
33
|
+
|
|
34
|
+
## Key Features
|
|
35
|
+
|
|
36
|
+
### Enhanced Error Handling
|
|
37
|
+
- **Custom error classes** with specific error types (ValidationError, PermissionError, NetworkError, etc.)
|
|
38
|
+
- **Actionable suggestions** provided with every error message
|
|
39
|
+
- **Better error context** to help diagnose issues quickly
|
|
40
|
+
|
|
41
|
+
### Reliability Features
|
|
42
|
+
- **Automatic verification** of MAC address changes after setting them
|
|
43
|
+
- **Retry logic** with exponential backoff for transient failures
|
|
44
|
+
- **Timeout handling** to prevent hanging operations
|
|
45
|
+
- **Comprehensive validation** of inputs before attempting changes
|
|
46
|
+
|
|
47
|
+
### Cross-Platform Excellence
|
|
48
|
+
- **Windows**: PowerShell integration with registry fallback
|
|
49
|
+
- **macOS**: Modern networksetup commands with WiFi timing handling
|
|
50
|
+
- **Linux**: Modern ip link commands with ifconfig fallback
|
|
51
|
+
- **Unified API** across all platforms
|
|
52
|
+
|
|
53
|
+
## Installation
|
|
54
|
+
|
|
55
|
+
### From npm (recommended)
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm install -g spoof-d
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
After installation, use the `spoofy` command (the package name is `spoof-d`, but the command is still `spoofy`).
|
|
62
|
+
|
|
63
|
+
After installation, you can use the `spoofy` command from anywhere.
|
|
64
|
+
|
|
65
|
+
### From source
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
git clone https://github.com/TT5H/spoof-d.git
|
|
69
|
+
cd spoof-d
|
|
70
|
+
npm install
|
|
71
|
+
npm install -g .
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
This gives you the latest development version with all the latest features.
|
|
75
|
+
|
|
76
|
+
## Quick Start
|
|
77
|
+
|
|
78
|
+
### List network interfaces
|
|
79
|
+
|
|
80
|
+
**macOS/Linux:**
|
|
81
|
+
```bash
|
|
82
|
+
spoofy list
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Windows (run PowerShell as Administrator):**
|
|
86
|
+
```powershell
|
|
87
|
+
spoofy list
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Randomize MAC address
|
|
91
|
+
|
|
92
|
+
**macOS (WiFi is typically `en0`):**
|
|
93
|
+
```bash
|
|
94
|
+
sudo spoofy randomize en0
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Windows:**
|
|
98
|
+
```powershell
|
|
99
|
+
# Run PowerShell as Administrator
|
|
100
|
+
spoofy randomize "Ethernet"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Linux:**
|
|
104
|
+
```bash
|
|
105
|
+
sudo spoofy randomize eth0
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Note:** WiFi will disconnect briefly and may need to reconnect to networks. On Windows, ensure you're running as Administrator.
|
|
109
|
+
|
|
110
|
+
## Usage
|
|
111
|
+
|
|
112
|
+
You can always see up-to-date usage instructions by running `spoofy --help`.
|
|
113
|
+
|
|
114
|
+
### List available devices
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
spoofy list
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Output:
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
- "Ethernet" on device "en4" with MAC address 70:56:51:BE:B3:00
|
|
124
|
+
- "Wi-Fi" on device "en0" with MAC address 70:56:51:BE:B3:01 currently set to 70:56:51:BE:B3:02
|
|
125
|
+
- "Bluetooth PAN" on device "en1"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### List only Wi-Fi devices
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
spoofy list --wifi
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Randomize MAC address _(requires root)_
|
|
135
|
+
|
|
136
|
+
Using hardware port name:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
sudo spoofy randomize wi-fi
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Or using device name:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
sudo spoofy randomize en0
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Set specific MAC address _(requires root)_
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
sudo spoofy set 00:11:22:33:44:55 en0
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Reset to original MAC address _(requires root)_
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
sudo spoofy reset wi-fi
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Note**: On macOS, restarting your computer will also reset your MAC address to the original hardware address.
|
|
161
|
+
|
|
162
|
+
## Platform Support
|
|
163
|
+
|
|
164
|
+
### macOS ✅
|
|
165
|
+
|
|
166
|
+
- ✅ **Fully supported** and tested on macOS Tahoe 26.2
|
|
167
|
+
- ✅ Works on macOS Sequoia 15.4+
|
|
168
|
+
- ⚠️ Older versions may work but are untested
|
|
169
|
+
- Uses `networksetup` and `ifconfig` commands
|
|
170
|
+
- Special handling for WiFi interfaces on modern macOS
|
|
171
|
+
|
|
172
|
+
### Windows ✅
|
|
173
|
+
|
|
174
|
+
- ✅ **Fully supported** on Windows 10 and Windows 11
|
|
175
|
+
- ✅ Uses PowerShell `Get-NetAdapter` and `Set-NetAdapter` commands
|
|
176
|
+
- ✅ Falls back to registry method for compatibility
|
|
177
|
+
- ⚠️ Requires Administrator privileges (run PowerShell/CMD as Administrator)
|
|
178
|
+
- Some network adapters may not support MAC address changes (hardware limitation)
|
|
179
|
+
|
|
180
|
+
**Windows Usage:**
|
|
181
|
+
```powershell
|
|
182
|
+
# Run PowerShell or CMD as Administrator
|
|
183
|
+
spoofy list
|
|
184
|
+
spoofy randomize "Ethernet"
|
|
185
|
+
spoofy set 00:11:22:33:44:55 "Wi-Fi"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Linux ✅
|
|
189
|
+
|
|
190
|
+
- ✅ **Fully supported** using modern `ip link` commands
|
|
191
|
+
- ✅ Falls back to `ifconfig` if `ip` command is not available
|
|
192
|
+
- ⚠️ Requires root privileges (use `sudo`)
|
|
193
|
+
- Works with most modern Linux distributions
|
|
194
|
+
|
|
195
|
+
**Linux Usage:**
|
|
196
|
+
```bash
|
|
197
|
+
sudo spoofy list
|
|
198
|
+
sudo spoofy randomize eth0
|
|
199
|
+
sudo spoofy set 00:11:22:33:44:55 wlan0
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Known Issues
|
|
203
|
+
|
|
204
|
+
- WiFi will briefly disconnect when changing MAC address
|
|
205
|
+
- Some network restrictions or hardware may prevent MAC spoofing
|
|
206
|
+
- Requires sudo/root privileges for all MAC address changes
|
|
207
|
+
|
|
208
|
+
## Troubleshooting
|
|
209
|
+
|
|
210
|
+
### macOS
|
|
211
|
+
1. Make sure you're running with `sudo` (required for network changes)
|
|
212
|
+
2. Ensure WiFi is turned on before attempting to change MAC
|
|
213
|
+
3. On modern macOS, you may need to reconnect to WiFi after the change
|
|
214
|
+
4. Try running `networksetup -detectnewhardware` if changes don't take effect
|
|
215
|
+
|
|
216
|
+
### Windows
|
|
217
|
+
1. **Run as Administrator**: Right-click PowerShell or Command Prompt and select "Run as Administrator"
|
|
218
|
+
2. Some network adapters don't support MAC address changes (hardware limitation)
|
|
219
|
+
3. If `Set-NetAdapter` fails, the tool will automatically try the registry method
|
|
220
|
+
4. You may need to disable and re-enable the adapter manually if changes don't take effect
|
|
221
|
+
5. Check adapter compatibility: Some virtual adapters and certain hardware may not support MAC spoofing
|
|
222
|
+
|
|
223
|
+
### Linux
|
|
224
|
+
1. Make sure you're running with `sudo` (required for network changes)
|
|
225
|
+
2. Ensure the `ip` command is available (usually in `iproute2` package)
|
|
226
|
+
3. Some network interfaces may be managed by NetworkManager - you may need to disable it temporarily
|
|
227
|
+
4. Virtual interfaces and certain hardware may not support MAC address changes
|
|
228
|
+
|
|
229
|
+
## Contributing
|
|
230
|
+
|
|
231
|
+
This is an active fork. Contributions, bug reports, and feature requests are welcome!
|
|
232
|
+
|
|
233
|
+
To contribute:
|
|
234
|
+
1. Fork this repository
|
|
235
|
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
236
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
237
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
238
|
+
5. Open a Pull Request
|
|
239
|
+
|
|
240
|
+
## License
|
|
241
|
+
|
|
242
|
+
MIT License (inherited from original project)
|
|
243
|
+
|
|
244
|
+
## Credits
|
|
245
|
+
|
|
246
|
+
- **This fork**: [TT5H/spoof-d](https://github.com/TT5H/spoof-d) - Enhanced cross-platform support with improved error handling
|
|
247
|
+
- **Parent fork**: [basedbytes/spoofy](https://github.com/basedbytes/spoofy) - Modernized macOS support
|
|
248
|
+
- **Original project**: `spoof` by Feross Aboukhadijeh
|
|
249
|
+
|
|
250
|
+
This fork maintains compatibility with modern operating systems and extends support to Windows and Linux.
|
package/bin/cmd.js
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const chalk = require("chalk");
|
|
4
|
+
const minimist = require("minimist");
|
|
5
|
+
const spoof = require("../");
|
|
6
|
+
const { stripIndent } = require("common-tags");
|
|
7
|
+
const cp = require("child_process");
|
|
8
|
+
|
|
9
|
+
const argv = minimist(process.argv.slice(2), {
|
|
10
|
+
alias: {
|
|
11
|
+
v: "version",
|
|
12
|
+
},
|
|
13
|
+
boolean: ["version"],
|
|
14
|
+
});
|
|
15
|
+
const cmd = argv._[0];
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
init();
|
|
19
|
+
} catch (err) {
|
|
20
|
+
handleError(err);
|
|
21
|
+
process.exitCode = -1;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function handleError(err) {
|
|
25
|
+
if (err.code) {
|
|
26
|
+
// Custom error with code and suggestions
|
|
27
|
+
console.error(chalk.red(`✗ ${err.name || "Error"}:`), err.message);
|
|
28
|
+
|
|
29
|
+
if (err.suggestions && err.suggestions.length > 0) {
|
|
30
|
+
console.error(chalk.yellow("\nSuggestions:"));
|
|
31
|
+
err.suggestions.forEach((suggestion, index) => {
|
|
32
|
+
console.error(chalk.gray(` ${index + 1}. ${suggestion}`));
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
} else {
|
|
36
|
+
// Standard error
|
|
37
|
+
console.error(chalk.red("✗ Error:"), err.message);
|
|
38
|
+
|
|
39
|
+
// Provide helpful suggestions for common errors
|
|
40
|
+
if (err.message.includes("ENOENT") || err.message.includes("spawn")) {
|
|
41
|
+
console.error(chalk.yellow("\nThis might be a system command issue. Suggestions:"));
|
|
42
|
+
if (process.platform === "linux") {
|
|
43
|
+
console.error(chalk.gray(" • Install iproute2: sudo apt-get install iproute2"));
|
|
44
|
+
} else if (process.platform === "win32") {
|
|
45
|
+
console.error(chalk.gray(" • Ensure PowerShell is installed and in PATH"));
|
|
46
|
+
}
|
|
47
|
+
} else if (err.message.includes("permission") || err.message.includes("Permission")) {
|
|
48
|
+
console.error(chalk.yellow("\nPermission issue. Suggestions:"));
|
|
49
|
+
if (process.platform === "win32") {
|
|
50
|
+
console.error(chalk.gray(" • Run PowerShell/CMD as Administrator"));
|
|
51
|
+
} else {
|
|
52
|
+
console.error(chalk.gray(" • Use sudo: sudo spoofy <command>"));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (process.env.DEBUG) {
|
|
58
|
+
console.error(chalk.gray("\nStack trace:"));
|
|
59
|
+
console.error(err.stack);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function init() {
|
|
64
|
+
if (cmd === "version" || argv.version) {
|
|
65
|
+
version();
|
|
66
|
+
} else if (cmd === "list" || cmd === "ls") {
|
|
67
|
+
list();
|
|
68
|
+
} else if (cmd === "set") {
|
|
69
|
+
const mac = argv._[1];
|
|
70
|
+
const devices = argv._.slice(2);
|
|
71
|
+
set(mac, devices);
|
|
72
|
+
} else if (cmd === "randomize") {
|
|
73
|
+
const devices = argv._.slice(1);
|
|
74
|
+
randomize(devices);
|
|
75
|
+
} else if (cmd === "reset") {
|
|
76
|
+
const devices = argv._.slice(1);
|
|
77
|
+
reset(devices);
|
|
78
|
+
} else if (cmd === "normalize") {
|
|
79
|
+
const mac = argv._[1];
|
|
80
|
+
normalize(mac);
|
|
81
|
+
} else {
|
|
82
|
+
help();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function help() {
|
|
87
|
+
const platform = process.platform;
|
|
88
|
+
let example = "";
|
|
89
|
+
let note = "";
|
|
90
|
+
|
|
91
|
+
if (platform === "win32") {
|
|
92
|
+
example = ` spoofy randomize "Ethernet"`;
|
|
93
|
+
note = "\n Note: On Windows, run PowerShell or CMD as Administrator.";
|
|
94
|
+
} else if (platform === "darwin") {
|
|
95
|
+
example = ` spoofy randomize en0`;
|
|
96
|
+
note = "\n Note: On macOS/Linux, use sudo for MAC address changes.";
|
|
97
|
+
} else {
|
|
98
|
+
example = ` sudo spoofy randomize eth0`;
|
|
99
|
+
note = "\n Note: On Linux, use sudo for MAC address changes.";
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const message = stripIndent`
|
|
103
|
+
spoofy - Cross-platform MAC address spoofing utility
|
|
104
|
+
|
|
105
|
+
Example (randomize MAC address):
|
|
106
|
+
${example}${note}
|
|
107
|
+
|
|
108
|
+
Usage:
|
|
109
|
+
spoofy list [--wifi] List available devices.
|
|
110
|
+
spoofy set <mac> <devices>... Set device MAC address.
|
|
111
|
+
spoofy randomize [--local] <devices>... Set device MAC address randomly.
|
|
112
|
+
spoofy reset <devices>... Reset device MAC address to default.
|
|
113
|
+
spoofy normalize <mac> Given a MAC address, normalize it.
|
|
114
|
+
spoofy help Shows this help message.
|
|
115
|
+
spoofy version | --version | -v Show package version.
|
|
116
|
+
|
|
117
|
+
Options:
|
|
118
|
+
--wifi Try to only show wireless interfaces.
|
|
119
|
+
--local Set the locally administered flag on randomized MACs.
|
|
120
|
+
|
|
121
|
+
Platform Support:
|
|
122
|
+
✅ macOS (Sequoia 15.4+, Tahoe 26+)
|
|
123
|
+
✅ Windows 10/11
|
|
124
|
+
✅ Linux (modern distributions)
|
|
125
|
+
`;
|
|
126
|
+
console.log(message);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function version() {
|
|
130
|
+
console.log(require("../package.json").version);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function set(mac, devices) {
|
|
134
|
+
if (!mac) {
|
|
135
|
+
throw new Error("MAC address is required. Usage: spoofy set <mac> <device>");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (!devices || devices.length === 0) {
|
|
139
|
+
throw new Error("Device name is required. Usage: spoofy set <mac> <device>");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
devices.forEach((device) => {
|
|
143
|
+
const it = spoof.findInterface(device);
|
|
144
|
+
|
|
145
|
+
if (!it) {
|
|
146
|
+
throw new Error(
|
|
147
|
+
`Could not find device "${device}". ` +
|
|
148
|
+
"List available devices using: spoofy list"
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
setMACAddress(it.device, mac, it.port);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function normalize(mac) {
|
|
157
|
+
if (!mac) {
|
|
158
|
+
throw new Error("MAC address is required. Usage: spoofy normalize <mac>");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
const normalized = spoof.normalize(mac);
|
|
163
|
+
if (!normalized) {
|
|
164
|
+
throw new Error(`"${mac}" is not a valid MAC address`);
|
|
165
|
+
}
|
|
166
|
+
console.log(normalized);
|
|
167
|
+
} catch (err) {
|
|
168
|
+
throw new Error(
|
|
169
|
+
`Could not normalize MAC address "${mac}": ${err.message}`
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function randomize(devices) {
|
|
175
|
+
if (!devices || devices.length === 0) {
|
|
176
|
+
throw new Error("Device name is required. Usage: spoofy randomize <device>");
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
devices.forEach((device) => {
|
|
180
|
+
const it = spoof.findInterface(device);
|
|
181
|
+
|
|
182
|
+
if (!it) {
|
|
183
|
+
throw new Error(
|
|
184
|
+
`Could not find device "${device}". ` +
|
|
185
|
+
"List available devices using: spoofy list"
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const mac = spoof.randomize(argv.local);
|
|
190
|
+
console.log(chalk.blue("ℹ"), `Generated random MAC address: ${chalk.bold.cyan(mac)}`);
|
|
191
|
+
setMACAddress(it.device, mac, it.port);
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function reset(devices) {
|
|
196
|
+
if (!devices || devices.length === 0) {
|
|
197
|
+
throw new Error("Device name is required. Usage: spoofy reset <device>");
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
devices.forEach((device) => {
|
|
201
|
+
const it = spoof.findInterface(device);
|
|
202
|
+
|
|
203
|
+
if (!it) {
|
|
204
|
+
throw new Error(
|
|
205
|
+
`Could not find device "${device}". ` +
|
|
206
|
+
"List available devices using: spoofy list"
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (!it.address) {
|
|
211
|
+
throw new Error(
|
|
212
|
+
`Could not read hardware MAC address for "${device}". ` +
|
|
213
|
+
"The device may not have a MAC address or may be a virtual interface."
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
console.log(chalk.blue("ℹ"), `Resetting to hardware MAC address: ${chalk.bold.cyan(it.address)}`);
|
|
218
|
+
setMACAddress(it.device, it.address, it.port);
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function list() {
|
|
223
|
+
const targets = [];
|
|
224
|
+
if (argv.wifi) {
|
|
225
|
+
if (process.platform === "win32") {
|
|
226
|
+
targets.push("wi-fi", "wireless", "wlan");
|
|
227
|
+
} else {
|
|
228
|
+
targets.push("wi-fi");
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const interfaces = spoof.findInterfaces(targets);
|
|
233
|
+
|
|
234
|
+
if (interfaces.length === 0) {
|
|
235
|
+
console.log(chalk.yellow("No network interfaces found."));
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
interfaces.forEach((it) => {
|
|
240
|
+
const line = [];
|
|
241
|
+
line.push(
|
|
242
|
+
"-",
|
|
243
|
+
chalk.bold.green(it.port || it.device),
|
|
244
|
+
"on device",
|
|
245
|
+
chalk.bold.green(it.device)
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
if (it.status && process.platform === "win32") {
|
|
249
|
+
line.push(chalk.gray(`(${it.status})`));
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (it.address) {
|
|
253
|
+
line.push("with MAC address", chalk.bold.cyan(it.address));
|
|
254
|
+
}
|
|
255
|
+
if (it.currentAddress && it.currentAddress !== it.address) {
|
|
256
|
+
line.push("currently set to", chalk.bold.red(it.currentAddress));
|
|
257
|
+
}
|
|
258
|
+
console.log(line.join(" "));
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function setMACAddress(device, mac, port) {
|
|
263
|
+
// Check for admin/root privileges
|
|
264
|
+
if (process.platform === "win32") {
|
|
265
|
+
// On Windows, check if running as administrator
|
|
266
|
+
try {
|
|
267
|
+
const output = cp
|
|
268
|
+
.execSync(
|
|
269
|
+
'powershell -Command "[Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent() | Select-Object -ExpandProperty IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)"',
|
|
270
|
+
{ stdio: "pipe", shell: true }
|
|
271
|
+
)
|
|
272
|
+
.toString()
|
|
273
|
+
.trim()
|
|
274
|
+
.toLowerCase();
|
|
275
|
+
|
|
276
|
+
if (output !== "true") {
|
|
277
|
+
throw new Error(
|
|
278
|
+
"Must run as Administrator to change network settings. " +
|
|
279
|
+
"Right-click Command Prompt or PowerShell and select 'Run as Administrator'"
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
} catch (err) {
|
|
283
|
+
if (err.message.includes("Must run as Administrator")) {
|
|
284
|
+
throw err;
|
|
285
|
+
}
|
|
286
|
+
// If check fails, warn but continue (might work anyway)
|
|
287
|
+
console.warn(chalk.yellow("Warning: Could not verify administrator privileges. Operation may fail."));
|
|
288
|
+
}
|
|
289
|
+
} else if (process.platform !== "win32") {
|
|
290
|
+
// Unix-like systems (macOS, Linux)
|
|
291
|
+
if (process.getuid && process.getuid() !== 0) {
|
|
292
|
+
throw new Error(
|
|
293
|
+
"Must run as root (or using sudo) to change network settings"
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
try {
|
|
299
|
+
spoof.setInterfaceMAC(device, mac, port);
|
|
300
|
+
console.log(
|
|
301
|
+
chalk.green("✓") +
|
|
302
|
+
" Successfully set MAC address to " +
|
|
303
|
+
chalk.bold.cyan(mac) +
|
|
304
|
+
" on " +
|
|
305
|
+
chalk.bold.green(device)
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
// Note: Verification is already done in setInterfaceMAC, so we don't need to do it again here
|
|
309
|
+
} catch (err) {
|
|
310
|
+
// Error is already formatted by handleError in the catch block above
|
|
311
|
+
throw err;
|
|
312
|
+
}
|
|
313
|
+
}
|