-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHashCat.py
375 lines (313 loc) · 12.5 KB
/
HashCat.py
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
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
#!/usr/bin/env python
# Copyright (c) 2005, Corey Goldberg
#
# HashCat.py is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
"""
@author: Corey Goldberg
@copyright: (C) 2005 Corey Goldberg
@license: GNU General Public License (GPL)
"""
import time
from socket import timeout
from threading import Thread
from Config import Config
class HashCat(Thread):
"""Connect to remote host with SSH and execute and control hashcat.
This is a facade/wrapper that uses paramiko to spawn and control an SSH client.
You must have OpenSSH installed.
@ivar host_name: Host name or IP address
@ivar user_name: User name
@ivar password: Password
@ivar prompt: Command prompt (or partial string matching the end of the prompt)
@ivar ssh: Instance of a paramiko.SSHClient object
"""
config = Config().getConfig()
def __init__(self, hostInfo,command):
"""
@param host_name: Host name or IP address
@param user_name: User name
@param password: Password
@param command: The hashcat command that have to be executed
@param results: A list that will contain the results once this thread is completed.
"""
Thread.__init__(self)
self.log = Config().getLogger('distributor.'+hostInfo.getHostName(), hostInfo.getHostName())
self.log.debug("Logging has been configured!!!")
self.results=results()
self.results.set_host(hostInfo)
self.results.set_command(command)
self.__chan = None
self.__ssh = None
self.interval = int(HashCat.config["heartbeat_timeout"])
self.be_alive = False
self.aborted = False
def get_command_xcode(self):
return self.results.get_command_xcode()
def __str__(self) :
#return str(self.__dict__)
return str({"host_name":self.results.get_host().getHostName(), "user_name":self.results.get_host().getUserName()})
def __eq__(self, other) :
return self.__dict__ == other.__dict__
def abort(self,value):
self.aborted = value
def isAborted(self):
return self.aborted
def set_command(self,value):
self.results.set_command(value)
def run(self):
if self.run_command(self.results.get_command()):
self.ping()
if self.aborted:
self.stop_proc()
self.results.set_command_xcode(-500)
self.quit()
def run_command(self, command):
"""Run a command on the remote host.
@param command: Unix command
@return: Command output
@rtype: String
"""
self.__ssh=self.results.get_host().getChannel()
if self.__ssh == None:
return False
self.__chan=self.__ssh.invoke_shell()
self.__chan.settimeout(15.0)
self.__chan.setblocking(1)
self.log.debug("sending command: '%s' to host" % command.getCommand())
try:
self.__chan.send(command.getCommand()+'\n')
except:
self.log.exception("Unable to send Command!!! - %s" % command.getCommand())
return False
time.sleep(int(HashCat.config["init_timeout"]))
self.be_alive = True
self.read_proc()
return True
def ping(self):
self.log.debug("Heartbeat is: %s and override is: %s" % (self.be_alive, self.aborted))
while self.be_alive and not self.aborted:
self.write_proc("s")
self.read_proc()
self.log.debug("Sleeping for %d seconds" % self.interval)
time.sleep(self.interval)
def parse(self, lines):
line_arr=lines.splitlines()
self.log.debug("Lines array: %s" % line_arr)
for line in line_arr:
if line.startswith("Status."):
self.results.set_status(line.split(":")[1].strip())
for case in switch(self.results.get_status()):
if case('Running'):
self.be_alive=True
break
if case('Finished'):
self.be_alive=False
break
if case('Cracked'):
self.getCrackCode()
self.be_alive=False
break
if case('Aborted'):
self.be_alive=False
break
if case('Exhausted'):
self.be_alive=False
break
if case('Initializing'):
self.be_alive=True
break
if case():
self.log.warning("Unexpected value: %s" % self.results.get_status())
continue
if line.startswith("Progress."):
try:
prg=float(line[line.find("(")+1:line.find(")")-1])
if prg==float(self.results.get_command().getID())+1.0:
prg=0.99
self.results.set_progress(prg)
except:
self.results.set_progress(-1.0)
continue
if line.startswith("Time.Running."):
self.results.set_elapsed_time(self.parseTime(line.split(":")[1].strip()))
continue
if line.startswith("Time.Left."):
self.results.set_estimated_time(self.parseTime(line.split(":")[1].strip()))
continue
if [True for i in ["$ ","$ s","# ","# s","ss"] if line.endswith(i)]:
self.results.set_last_output(line_arr)
self.be_alive=False
self.evaluate_xcode()
if not self.results.get_command_xcode() in [0,1]:
self.results.set_status("Error")
continue
#self.log.debug("Line cannot be recognized: %s" % line)
def parseTime(self,timeString):
days=0
hours=0
minutes=0
seconds=0
time_arr=timeString.split(",")
for timeLine in time_arr:
if timeLine.strip().split(" ")[1].strip() in ["day","days"]:
days=int(timeLine.strip().split(" ")[0].strip())
if timeLine.strip().split(" ")[1].strip() in ["hour","hours"]:
hours=int(timeLine.strip().split(" ")[0].strip())
if timeLine.strip().split(" ")[1].strip() in ["min","mins"]:
minutes=int(timeLine.strip().split(" ")[0].strip())
if timeLine.strip().split(" ")[1].strip() in ["sec","secs"]:
seconds=int(timeLine.strip().split(" ")[0].strip())
return "%i:%i:%i" %(24*days+hours,minutes,seconds)
def evaluate_xcode(self):
lines=''
command="echo $?"
self.write_proc("\b"*10)
self.log.debug("sending command: '%s' to host" % command)
try:
self.__chan.send(command+'\n')
except:
self.log.error("Unable to send command!!! - %s" % command)
while not [True for i in ["=> ","$ ","$ s","# ","# s","ss"] if lines.endswith(i)]:
try:
for x in range(1,16):
time.sleep(1)
if self.__chan.recv_ready():
line=self.__chan.recv(9999)
lines=lines+''.join(line)
break
if x==15: raise Exception()
except:
self.log.error("Cannot obtain exit code line!!!")
self.log.debug("Exit Code Line: %s" % lines)
line_arr=lines.splitlines()
try:
self.results.set_command_xcode(int(line_arr[1]))
except:
self.log.exception("Line: %s - does not contain an integer value!!!" % line_arr[1])
self.log.debug("Exit Code is: %d" % self.results.get_command_xcode())
def stop_proc(self):
self.log.info("Sending stop command to process...")
self.be_alive = False
self.write_proc("q")
self.read_proc()
def read_proc(self):
lines=''
while not [True for i in ["=> ","$ ","$ s","# ","# s","ss"] if lines.endswith(i)]:
try:
self.log.debug("Channel receive status: %s" % self.__chan.recv_ready())
for x in range(1,16):
time.sleep(1)
if self.__chan.recv_ready():
line=self.__chan.recv(9999)
lines=lines+''.join(line)
break
if x==15: raise Exception()
except:
self.log.exception("Stream not ready!!!")
self.be_alive=False
return
self.parse(lines)
def write_proc(self, message):
try:
self.log.debug("Sending message: %s through the channel..." % message)
self.__chan.send(message)
return True
except:
self.log.exception("Sending message %s failed!!!" % message)
return False
def quit(self):
self.log.debug("Quitting thread on host %s ..."% self.results.get_host().getHostName())
if self.__ssh!= None:
self.results.get_host().closeChannel(self.__ssh)
def getCrackCode(self):
#read code from file
cmdline=self.results.get_command().getCommand().split(" ")
for cmd in cmdline:
if cmd.startswith('--outfile'):
filename=cmd.split("=")[1]
if filename != None:
tmp=self.results.get_host().getFile(filename)
crackCode=tmp[0][:-1].split(':')[2]
if crackCode != None:
self.results.set_crackCode(crackCode)
def get_result(self):
return self.results
class switch(object):
def __init__(self, value):
self.value = value
self.fall = False
def __iter__(self):
"""Return the match method once, then stop"""
yield self.match
raise StopIteration
def match(self, *args):
"""Indicate whether or not to enter a case suite"""
if self.fall or not args:
return True
elif self.value in args: # changed for v1.5, see below
self.fall = True
return True
else:
return False
class results(object):
def get_host(self):
return self.host
def get_command_xcode(self):
return self.command_xcode
def get_command(self):
return self.command
def get_status(self):
return self.__status
def get_progress(self):
return self.progress
def get_elapsed_time(self):
return self.elapsed_time
def get_estimated_time(self):
return self.estimated_time
def get_be_alive(self):
return self.be_alive
def get_aborted(self):
return self.aborted
def get_last_output(self):
return self.last_output
def set_host(self, value):
self.host = value
def set_command_xcode(self, value):
self.command_xcode = value
def set_command(self, value):
self.command = value
def set_status(self, value):
self.__status = value
def set_progress(self, value):
self.progress = value
def set_elapsed_time(self, value):
self.elapsed_time = value
def set_estimated_time(self, value):
self.estimated_time = value
def set_be_alive(self, value):
self.be_alive = value
def set_aborted(self, value):
self.aborted = value
def set_last_output(self, value):
self.last_output = value
def get_crackCode(self):
return self.crackCode
def set_crackCode(self,value):
self.crackCode = value
def __init__(self):
self.host = None
self.command_xcode=-100
self.command = ''
self.__status = ''
self.progress = 0.0
self.elapsed_time = ''
self.estimated_time = ''
self.be_alive = None
self.aborted = None
self.last_output = ''
self.crackCode=None
if __name__ == '__main__':
pass