33
33
class Respotter :
34
34
def __init__ (self ,
35
35
delay = 30 ,
36
+ discord_webhook = "" ,
36
37
excluded_protocols = [],
37
38
hostname = "Loremipsumdolorsitamet" ,
39
+ slack_webhook = "" ,
40
+ state_file = "state/state.json" ,
38
41
subnet = "" ,
42
+ syslog_address = "" ,
43
+ teams_webhook = "" ,
44
+ test_webhooks = False ,
39
45
timeout = 1 ,
40
46
verbosity = 2 ,
41
- discord_webhook = "" ,
42
- slack_webhook = "" ,
43
- teams_webhook = "" ,
44
- syslog_address = "" ,
45
- test_webhooks = False
46
47
):
47
48
# initialize logger
48
49
self .log = logging .getLogger ('respotter' )
@@ -64,9 +65,10 @@ def __init__(self,
64
65
self .timeout = timeout
65
66
self .verbosity = verbosity
66
67
# state persistence
68
+ self .state_file = state_file
67
69
self .state_lock = Lock ()
68
70
try :
69
- with open ("state/state.json" , "r+" ) as state_file :
71
+ with open (self . state_file , "r+" ) as state_file :
70
72
try :
71
73
previous_state = json .load (state_file )
72
74
self .responder_alerts = previous_state ["responder_alerts" ]
@@ -82,7 +84,7 @@ def __init__(self,
82
84
self .responder_alerts = {}
83
85
self .vulnerable_alerts = {}
84
86
Path ("state" ).mkdir (parents = True , exist_ok = True )
85
- with open ("state/state.json" , "w" ) as state_file :
87
+ with open (self . state_file , "w" ) as state_file :
86
88
json .dump ({"responder_alerts" : {}, "vulnerable_alerts" : {}}, state_file )
87
89
# get broadcast IP for Netbios
88
90
if subnet :
@@ -131,7 +133,7 @@ def webhook_responder_alert(self, responder_ip):
131
133
except WebhookException as e :
132
134
self .log .error (f"[!] { service .capitalize ()} webhook failed: { e } " )
133
135
self .responder_alerts [responder_ip ] = datetime .now ()
134
- with open ("state/state.json" , "r+" ) as state_file :
136
+ with open (self . state_file , "r+" ) as state_file :
135
137
state = json .load (state_file )
136
138
new_state = deepcopy (self .responder_alerts )
137
139
for ip in new_state :
@@ -159,7 +161,7 @@ def webhook_sniffer_alert(self, protocol, requester_ip, requested_hostname):
159
161
self .vulnerable_alerts [requester_ip ][protocol ] = datetime .now ()
160
162
else :
161
163
self .vulnerable_alerts [requester_ip ] = {protocol : datetime .now ()}
162
- with open ("state/state.json" , "r+" ) as state_file :
164
+ with open (self . state_file , "r+" ) as state_file :
163
165
state = json .load (state_file )
164
166
new_state = deepcopy (self .vulnerable_alerts )
165
167
for ip in new_state :
@@ -327,6 +329,7 @@ def parse_options():
327
329
"exclude" : "" ,
328
330
"hostname" : "Loremipsumdolorsitamet" ,
329
331
"slack_webhook" : "" ,
332
+ "state_file" : "state/state.json" ,
330
333
"subnet" : "" ,
331
334
"syslog_address" : "" ,
332
335
"teams_webhook" : "" ,
@@ -352,6 +355,7 @@ def parse_options():
352
355
parser .add_argument ("-x" , "--exclude" , help = "Protocols to exclude from scanning (e.g. 'llmnr,nbns')" )
353
356
parser .add_argument ("-l" , "--syslog-address" , help = "Syslog server address" )
354
357
parser .add_argument ("--test-webhooks" , action = "store_true" , help = "Test configured webhooks" )
358
+ parser .add_argument ("--state-file" , help = "Path to state file" )
355
359
args = parser .parse_args (remaining_argv )
356
360
if int (args .verbosity ) > 4 :
357
361
print (f"Final config: { args } \n " )
@@ -372,16 +376,17 @@ def parse_options():
372
376
exit (1 )
373
377
374
378
respotter = Respotter (delay = int (options .delay ),
379
+ discord_webhook = options .discord_webhook ,
375
380
excluded_protocols = excluded_protocols ,
376
381
hostname = options .hostname ,
377
- subnet = options .subnet ,
378
- timeout = int (options .timeout ),
379
- verbosity = int (options .verbosity ),
380
- discord_webhook = options .discord_webhook ,
381
382
slack_webhook = options .slack_webhook ,
382
- teams_webhook = options .teams_webhook ,
383
+ state_file = options .state_file ,
384
+ subnet = options .subnet ,
383
385
syslog_address = options .syslog_address ,
384
- test_webhooks = options .test_webhooks
386
+ teams_webhook = options .teams_webhook ,
387
+ test_webhooks = options .test_webhooks ,
388
+ timeout = int (options .timeout ),
389
+ verbosity = int (options .verbosity )
385
390
)
386
391
387
392
respotter .daemon ()
0 commit comments