Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sqlmapproject
GitHub Repository: sqlmapproject/sqlmap
Path: blob/master/lib/utils/hash.py
3554 views
1
#!/usr/bin/env python
2
3
"""
4
Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org)
5
See the file 'LICENSE' for copying permission
6
"""
7
8
from __future__ import print_function
9
10
try:
11
from crypt import crypt
12
except: # removed ImportError because of https://github.com/sqlmapproject/sqlmap/issues/3171
13
from thirdparty.fcrypt.fcrypt import crypt
14
15
try:
16
from Crypto.Cipher.DES import MODE_CBC as CBC
17
from Crypto.Cipher.DES import new as des
18
except:
19
from thirdparty.pydes.pyDes import CBC
20
from thirdparty.pydes.pyDes import des
21
22
_multiprocessing = None
23
24
import base64
25
import binascii
26
import gc
27
import math
28
import os
29
import re
30
import tempfile
31
import time
32
import zipfile
33
34
from hashlib import md5
35
from hashlib import sha1
36
from hashlib import sha224
37
from hashlib import sha256
38
from hashlib import sha384
39
from hashlib import sha512
40
41
from lib.core.common import Backend
42
from lib.core.common import checkFile
43
from lib.core.common import clearConsoleLine
44
from lib.core.common import dataToStdout
45
from lib.core.common import getFileItems
46
from lib.core.common import getPublicTypeMembers
47
from lib.core.common import getSafeExString
48
from lib.core.common import hashDBRetrieve
49
from lib.core.common import hashDBWrite
50
from lib.core.common import isZipFile
51
from lib.core.common import normalizeUnicode
52
from lib.core.common import openFile
53
from lib.core.common import paths
54
from lib.core.common import readInput
55
from lib.core.common import singleTimeLogMessage
56
from lib.core.common import singleTimeWarnMessage
57
from lib.core.compat import xrange
58
from lib.core.convert import decodeBase64
59
from lib.core.convert import decodeHex
60
from lib.core.convert import encodeHex
61
from lib.core.convert import getBytes
62
from lib.core.convert import getText
63
from lib.core.convert import getUnicode
64
from lib.core.data import conf
65
from lib.core.data import kb
66
from lib.core.data import logger
67
from lib.core.datatype import OrderedSet
68
from lib.core.decorators import cachedmethod
69
from lib.core.enums import DBMS
70
from lib.core.enums import HASH
71
from lib.core.enums import MKSTEMP_PREFIX
72
from lib.core.exception import SqlmapDataException
73
from lib.core.exception import SqlmapUserQuitException
74
from lib.core.settings import COMMON_PASSWORD_SUFFIXES
75
from lib.core.settings import COMMON_USER_COLUMNS
76
from lib.core.settings import DEV_EMAIL_ADDRESS
77
from lib.core.settings import DUMMY_USER_PREFIX
78
from lib.core.settings import HASH_BINARY_COLUMNS_REGEX
79
from lib.core.settings import HASH_EMPTY_PASSWORD_MARKER
80
from lib.core.settings import HASH_MOD_ITEM_DISPLAY
81
from lib.core.settings import HASH_RECOGNITION_QUIT_THRESHOLD
82
from lib.core.settings import INVALID_UNICODE_CHAR_FORMAT
83
from lib.core.settings import IS_WIN
84
from lib.core.settings import ITOA64
85
from lib.core.settings import NULL
86
from lib.core.settings import ROTATING_CHARS
87
from lib.core.settings import UNICODE_ENCODING
88
from lib.core.wordlist import Wordlist
89
from thirdparty import six
90
from thirdparty.colorama.initialise import init as coloramainit
91
from thirdparty.six.moves import queue as _queue
92
93
def mysql_passwd(password, uppercase=True):
94
"""
95
Reference(s):
96
https://web.archive.org/web/20120215205312/http://csl.sublevel3.org/mysql-password-function/
97
98
>>> mysql_passwd(password='testpass', uppercase=True)
99
'*00E247AC5F9AF26AE0194B41E1E769DEE1429A29'
100
"""
101
102
password = getBytes(password)
103
104
retVal = "*%s" % sha1(sha1(password).digest()).hexdigest()
105
106
return retVal.upper() if uppercase else retVal.lower()
107
108
def mysql_old_passwd(password, uppercase=True): # prior to version '4.1'
109
"""
110
Reference(s):
111
https://web.archive.org/web/20091205000600/http://www.sfr-fresh.com/unix/privat/tpop3d-1.5.5.tar.gz:a/tpop3d-1.5.5/password.c
112
https://github.com/pwnieexpress/pwn_plug_sources/blob/master/src/darkmysqli/DarkMySQLi.py
113
114
>>> mysql_old_passwd(password='testpass', uppercase=True)
115
'7DCDA0D57290B453'
116
"""
117
118
a, b, c = 1345345333, 7, 0x12345671
119
120
for d in password:
121
if d == ' ' or d == '\t':
122
continue
123
124
e = ord(d)
125
a ^= (((a & 63) + b) * e) + (a << 8)
126
c += (c << 8) ^ a
127
b += e
128
129
retVal = "%08lx%08lx" % (a & ((1 << 31) - 1), c & ((1 << 31) - 1))
130
131
return retVal.upper() if uppercase else retVal.lower()
132
133
def postgres_passwd(password, username, uppercase=False):
134
"""
135
Reference(s):
136
http://pentestmonkey.net/blog/cracking-postgres-hashes/
137
138
>>> postgres_passwd(password='testpass', username='testuser', uppercase=False)
139
'md599e5ea7a6f7c3269995cba3927fd0093'
140
"""
141
142
username = getBytes(username)
143
password = getBytes(password)
144
145
retVal = "md5%s" % md5(password + username).hexdigest()
146
147
return retVal.upper() if uppercase else retVal.lower()
148
149
def mssql_new_passwd(password, salt, uppercase=False): # since version '2012'
150
"""
151
Reference(s):
152
http://hashcat.net/forum/thread-1474.html
153
https://sqlity.net/en/2460/sql-password-hash/
154
155
>>> mssql_new_passwd(password='testpass', salt='4086ceb6', uppercase=False)
156
'0x02004086ceb6eb051cdbc5bdae68ffc66c918d4977e592f6bdfc2b444a7214f71fa31c35902c5b7ae773ed5f4c50676d329120ace32ee6bc81c24f70711eb0fc6400e85ebf25'
157
"""
158
159
binsalt = decodeHex(salt)
160
unistr = b"".join((_.encode(UNICODE_ENCODING) + b"\0") if ord(_) < 256 else _.encode(UNICODE_ENCODING) for _ in password)
161
162
retVal = "0200%s%s" % (salt, sha512(unistr + binsalt).hexdigest())
163
164
return "0x%s" % (retVal.upper() if uppercase else retVal.lower())
165
166
def mssql_passwd(password, salt, uppercase=False): # versions '2005' and '2008'
167
"""
168
Reference(s):
169
http://www.leidecker.info/projects/phrasendrescher/mssql.c
170
https://www.evilfingers.com/tools/GSAuditor.php
171
172
>>> mssql_passwd(password='testpass', salt='4086ceb6', uppercase=False)
173
'0x01004086ceb60c90646a8ab9889fe3ed8e5c150b5460ece8425a'
174
"""
175
176
binsalt = decodeHex(salt)
177
unistr = b"".join((_.encode(UNICODE_ENCODING) + b"\0") if ord(_) < 256 else _.encode(UNICODE_ENCODING) for _ in password)
178
179
retVal = "0100%s%s" % (salt, sha1(unistr + binsalt).hexdigest())
180
181
return "0x%s" % (retVal.upper() if uppercase else retVal.lower())
182
183
def mssql_old_passwd(password, salt, uppercase=True): # version '2000' and before
184
"""
185
Reference(s):
186
www.exploit-db.com/download_pdf/15537/
187
http://www.leidecker.info/projects/phrasendrescher/mssql.c
188
https://www.evilfingers.com/tools/GSAuditor.php
189
190
>>> mssql_old_passwd(password='testpass', salt='4086ceb6', uppercase=True)
191
'0x01004086CEB60C90646A8AB9889FE3ED8E5C150B5460ECE8425AC7BB7255C0C81D79AA5D0E93D4BB077FB9A51DA0'
192
"""
193
194
binsalt = decodeHex(salt)
195
unistr = b"".join((_.encode(UNICODE_ENCODING) + b"\0") if ord(_) < 256 else _.encode(UNICODE_ENCODING) for _ in password)
196
197
retVal = "0100%s%s%s" % (salt, sha1(unistr + binsalt).hexdigest(), sha1(unistr.upper() + binsalt).hexdigest())
198
199
return "0x%s" % (retVal.upper() if uppercase else retVal.lower())
200
201
def oracle_passwd(password, salt, uppercase=True):
202
"""
203
Reference(s):
204
https://www.evilfingers.com/tools/GSAuditor.php
205
http://www.notesbit.com/index.php/scripts-oracle/oracle-11g-new-password-algorithm-is-revealed-by-seclistsorg/
206
http://seclists.org/bugtraq/2007/Sep/304
207
208
>>> oracle_passwd(password='SHAlala', salt='1B7B5F82B7235E9E182C', uppercase=True)
209
'S:2BFCFDF5895014EE9BB2B9BA067B01E0389BB5711B7B5F82B7235E9E182C'
210
"""
211
212
binsalt = decodeHex(salt)
213
password = getBytes(password)
214
215
retVal = "s:%s%s" % (sha1(password + binsalt).hexdigest(), salt)
216
217
return retVal.upper() if uppercase else retVal.lower()
218
219
def oracle_old_passwd(password, username, uppercase=True): # prior to version '11g'
220
"""
221
Reference(s):
222
http://www.notesbit.com/index.php/scripts-oracle/oracle-11g-new-password-algorithm-is-revealed-by-seclistsorg/
223
224
>>> oracle_old_passwd(password='tiger', username='scott', uppercase=True)
225
'F894844C34402B67'
226
"""
227
228
IV, pad = b"\0" * 8, b"\0"
229
230
unistr = b"".join((b"\0" + _.encode(UNICODE_ENCODING)) if ord(_) < 256 else _.encode(UNICODE_ENCODING) for _ in (username + password).upper())
231
232
if des.__module__ == "Crypto.Cipher.DES":
233
unistr += b"\0" * ((8 - len(unistr) % 8) & 7)
234
cipher = des(decodeHex("0123456789ABCDEF"), CBC, iv=IV)
235
encrypted = cipher.encrypt(unistr)
236
cipher = des(encrypted[-8:], CBC, iv=IV)
237
encrypted = cipher.encrypt(unistr)
238
else:
239
cipher = des(decodeHex("0123456789ABCDEF"), CBC, IV, pad)
240
encrypted = cipher.encrypt(unistr)
241
cipher = des(encrypted[-8:], CBC, IV, pad)
242
encrypted = cipher.encrypt(unistr)
243
244
retVal = encodeHex(encrypted[-8:], binary=False)
245
246
return retVal.upper() if uppercase else retVal.lower()
247
248
def md5_generic_passwd(password, uppercase=False):
249
"""
250
>>> md5_generic_passwd(password='testpass', uppercase=False)
251
'179ad45c6ce2cb97cf1029e212046e81'
252
"""
253
254
password = getBytes(password)
255
256
retVal = md5(password).hexdigest()
257
258
return retVal.upper() if uppercase else retVal.lower()
259
260
def sha1_generic_passwd(password, uppercase=False):
261
"""
262
>>> sha1_generic_passwd(password='testpass', uppercase=False)
263
'206c80413b9a96c1312cc346b7d2517b84463edd'
264
"""
265
266
password = getBytes(password)
267
268
retVal = sha1(password).hexdigest()
269
270
return retVal.upper() if uppercase else retVal.lower()
271
272
def apache_sha1_passwd(password, **kwargs):
273
"""
274
>>> apache_sha1_passwd(password='testpass')
275
'{SHA}IGyAQTualsExLMNGt9JRe4RGPt0='
276
"""
277
278
password = getBytes(password)
279
280
return "{SHA}%s" % getText(base64.b64encode(sha1(password).digest()))
281
282
def ssha_passwd(password, salt, **kwargs):
283
"""
284
>>> ssha_passwd(password='testpass', salt='salt')
285
'{SSHA}mU1HPTvnmoXOhE4ROHP6sWfbfoRzYWx0'
286
"""
287
288
password = getBytes(password)
289
salt = getBytes(salt)
290
291
return "{SSHA}%s" % getText(base64.b64encode(sha1(password + salt).digest() + salt))
292
293
def ssha256_passwd(password, salt, **kwargs):
294
"""
295
>>> ssha256_passwd(password='testpass', salt='salt')
296
'{SSHA256}hhubsLrO/Aje9F/kJrgv5ZLE40UmTrVWvI7Dt6InP99zYWx0'
297
"""
298
299
password = getBytes(password)
300
salt = getBytes(salt)
301
302
return "{SSHA256}%s" % getText(base64.b64encode(sha256(password + salt).digest() + salt))
303
304
def ssha512_passwd(password, salt, **kwargs):
305
"""
306
>>> ssha512_passwd(password='testpass', salt='salt')
307
'{SSHA512}mCUSLfPMhXCQOJl9WHW/QMn9v9sjq7Ht/Wk7iVau8vLOfh+PeynkGMikqIE8sStFd0khdfcCD8xZmC6UyjTxsHNhbHQ='
308
"""
309
310
password = getBytes(password)
311
salt = getBytes(salt)
312
313
return "{SSHA512}%s" % getText(base64.b64encode(sha512(password + salt).digest() + salt))
314
315
def sha224_generic_passwd(password, uppercase=False):
316
"""
317
>>> sha224_generic_passwd(password='testpass', uppercase=False)
318
'648db6019764b598f75ab6b7616d2e82563a00eb1531680e19ac4c6f'
319
"""
320
321
retVal = sha224(getBytes(password)).hexdigest()
322
323
return retVal.upper() if uppercase else retVal.lower()
324
325
def sha256_generic_passwd(password, uppercase=False):
326
"""
327
>>> sha256_generic_passwd(password='testpass', uppercase=False)
328
'13d249f2cb4127b40cfa757866850278793f814ded3c587fe5889e889a7a9f6c'
329
"""
330
331
retVal = sha256(getBytes(password)).hexdigest()
332
333
return retVal.upper() if uppercase else retVal.lower()
334
335
def sha384_generic_passwd(password, uppercase=False):
336
"""
337
>>> sha384_generic_passwd(password='testpass', uppercase=False)
338
'6823546e56adf46849343be991d4b1be9b432e42ed1b4bb90635a0e4b930e49b9ca007bc3e04bf0a4e0df6f1f82769bf'
339
"""
340
341
retVal = sha384(getBytes(password)).hexdigest()
342
343
return retVal.upper() if uppercase else retVal.lower()
344
345
def sha512_generic_passwd(password, uppercase=False):
346
"""
347
>>> sha512_generic_passwd(password='testpass', uppercase=False)
348
'78ddc8555bb1677ff5af75ba5fc02cb30bb592b0610277ae15055e189b77fe3fda496e5027a3d99ec85d54941adee1cc174b50438fdc21d82d0a79f85b58cf44'
349
"""
350
351
retVal = sha512(getBytes(password)).hexdigest()
352
353
return retVal.upper() if uppercase else retVal.lower()
354
355
def crypt_generic_passwd(password, salt, **kwargs):
356
"""
357
Reference(s):
358
http://docs.python.org/library/crypt.html
359
http://helpful.knobs-dials.com/index.php/Hashing_notes
360
http://php.net/manual/en/function.crypt.php
361
http://carey.geek.nz/code/python-fcrypt/
362
363
>>> crypt_generic_passwd(password='rasmuslerdorf', salt='rl', uppercase=False)
364
'rl.3StKT.4T8M'
365
"""
366
367
return getText(crypt(password, salt))
368
369
def unix_md5_passwd(password, salt, magic="$1$", **kwargs):
370
"""
371
Reference(s):
372
http://www.sabren.net/code/python/crypt/md5crypt.py
373
374
>>> unix_md5_passwd(password='testpass', salt='aD9ZLmkp')
375
'$1$aD9ZLmkp$DRM5a7rRZGyuuOPOjTEk61'
376
"""
377
378
def _encode64(value, count):
379
output = ""
380
381
while (count - 1 >= 0):
382
count = count - 1
383
output += ITOA64[value & 0x3f]
384
value = value >> 6
385
386
return output
387
388
password = getBytes(password)
389
magic = getBytes(magic)
390
salt = getBytes(salt)
391
392
salt = salt[:8]
393
ctx = password + magic + salt
394
final = md5(password + salt + password).digest()
395
396
for pl in xrange(len(password), 0, -16):
397
if pl > 16:
398
ctx = ctx + final[:16]
399
else:
400
ctx = ctx + final[:pl]
401
402
i = len(password)
403
while i:
404
if i & 1:
405
ctx = ctx + b'\x00' # if ($i & 1) { $ctx->add(pack("C", 0)); }
406
else:
407
ctx = ctx + password[0:1]
408
i = i >> 1
409
410
final = md5(ctx).digest()
411
412
for i in xrange(1000):
413
ctx1 = b""
414
415
if i & 1:
416
ctx1 = ctx1 + password
417
else:
418
ctx1 = ctx1 + final[:16]
419
420
if i % 3:
421
ctx1 = ctx1 + salt
422
423
if i % 7:
424
ctx1 = ctx1 + password
425
426
if i & 1:
427
ctx1 = ctx1 + final[:16]
428
else:
429
ctx1 = ctx1 + password
430
431
final = md5(ctx1).digest()
432
433
hash_ = _encode64((int(ord(final[0:1])) << 16) | (int(ord(final[6:7])) << 8) | (int(ord(final[12:13]))), 4)
434
hash_ = hash_ + _encode64((int(ord(final[1:2])) << 16) | (int(ord(final[7:8])) << 8) | (int(ord(final[13:14]))), 4)
435
hash_ = hash_ + _encode64((int(ord(final[2:3])) << 16) | (int(ord(final[8:9])) << 8) | (int(ord(final[14:15]))), 4)
436
hash_ = hash_ + _encode64((int(ord(final[3:4])) << 16) | (int(ord(final[9:10])) << 8) | (int(ord(final[15:16]))), 4)
437
hash_ = hash_ + _encode64((int(ord(final[4:5])) << 16) | (int(ord(final[10:11])) << 8) | (int(ord(final[5:6]))), 4)
438
hash_ = hash_ + _encode64((int(ord(final[11:12]))), 2)
439
440
return getText(magic + salt + b'$' + getBytes(hash_))
441
442
def joomla_passwd(password, salt, **kwargs):
443
"""
444
Reference: https://stackoverflow.com/a/10428239
445
446
>>> joomla_passwd(password='testpass', salt='6GGlnaquVXI80b3HRmSyE3K1wEFFaBIf')
447
'e3d5794da74e917637332e0d21b76328:6GGlnaquVXI80b3HRmSyE3K1wEFFaBIf'
448
"""
449
450
return "%s:%s" % (md5(getBytes(password) + getBytes(salt)).hexdigest(), salt)
451
452
def django_md5_passwd(password, salt, **kwargs):
453
"""
454
Reference: https://github.com/jay0lee/GAM/blob/master/src/passlib/handlers/django.py
455
456
>>> django_md5_passwd(password='testpass', salt='salt')
457
'md5$salt$972141bcbcb6a0acc96e92309175b3c5'
458
"""
459
460
return "md5$%s$%s" % (salt, md5(getBytes(salt) + getBytes(password)).hexdigest())
461
462
def django_sha1_passwd(password, salt, **kwargs):
463
"""
464
Reference: https://github.com/jay0lee/GAM/blob/master/src/passlib/handlers/django.py
465
466
>>> django_sha1_passwd(password='testpass', salt='salt')
467
'sha1$salt$6ce0e522aba69d8baa873f01420fccd0250fc5b2'
468
"""
469
470
return "sha1$%s$%s" % (salt, sha1(getBytes(salt) + getBytes(password)).hexdigest())
471
472
def vbulletin_passwd(password, salt, **kwargs):
473
"""
474
Reference: https://stackoverflow.com/a/2202810
475
476
>>> vbulletin_passwd(password='testpass', salt='salt')
477
'85c4d8ea77ebef2236fb7e9d24ba9482:salt'
478
"""
479
480
return "%s:%s" % (md5(binascii.hexlify(md5(getBytes(password)).digest()) + getBytes(salt)).hexdigest(), salt)
481
482
def oscommerce_old_passwd(password, salt, **kwargs):
483
"""
484
Reference: http://ryanuber.com/09-24-2010/os-commerce-password-hashing.html
485
486
>>> oscommerce_old_passwd(password='testpass', salt='6b')
487
'16d39816e4545b3179f86f2d2d549af4:6b'
488
"""
489
490
return "%s:%s" % (md5(getBytes(salt) + getBytes(password)).hexdigest(), salt)
491
492
def phpass_passwd(password, salt, count, prefix, **kwargs):
493
"""
494
Reference(s):
495
https://web.archive.org/web/20120219120128/packetstormsecurity.org/files/74448/phpassbrute.py.txt
496
http://scriptserver.mainframe8.com/wordpress_password_hasher.php
497
https://www.openwall.com/phpass/
498
https://github.com/jedie/django-phpBB3/blob/master/django_phpBB3/hashers.py
499
500
>>> phpass_passwd(password='testpass', salt='aD9ZLmkp', count=2048, prefix='$P$')
501
'$P$9aD9ZLmkpsN4A83G8MefaaP888gVKX0'
502
>>> phpass_passwd(password='testpass', salt='Pb1j9gSb', count=2048, prefix='$H$')
503
'$H$9Pb1j9gSb/u3EVQ.4JDZ3LqtN44oIx/'
504
>>> phpass_passwd(password='testpass', salt='iwtD/g.K', count=128, prefix='$S$')
505
'$S$5iwtD/g.KZT2rwC9DASy/mGYAThkSd3lBFdkONi1Ig1IEpBpqG8W'
506
"""
507
508
def _encode64(input_, count):
509
output = ''
510
i = 0
511
512
while i < count:
513
value = (input_[i] if isinstance(input_[i], int) else ord(input_[i]))
514
i += 1
515
output = output + ITOA64[value & 0x3f]
516
517
if i < count:
518
value = value | ((input_[i] if isinstance(input_[i], int) else ord(input_[i])) << 8)
519
520
output = output + ITOA64[(value >> 6) & 0x3f]
521
522
i += 1
523
if i >= count:
524
break
525
526
if i < count:
527
value = value | ((input_[i] if isinstance(input_[i], int) else ord(input_[i])) << 16)
528
529
output = output + ITOA64[(value >> 12) & 0x3f]
530
531
i += 1
532
if i >= count:
533
break
534
535
output = output + ITOA64[(value >> 18) & 0x3f]
536
537
return output
538
539
password = getBytes(password)
540
f = {"$P$": md5, "$H$": md5, "$Q$": sha1, "$S$": sha512}[prefix]
541
542
cipher = f(getBytes(salt))
543
cipher.update(password)
544
hash_ = cipher.digest()
545
546
for i in xrange(count):
547
_ = f(hash_)
548
_.update(password)
549
hash_ = _.digest()
550
551
retVal = "%s%s%s%s" % (prefix, ITOA64[int(math.log(count, 2))], salt, _encode64(hash_, len(hash_)))
552
553
if prefix == "$S$":
554
# Reference: https://api.drupal.org/api/drupal/includes%21password.inc/constant/DRUPAL_HASH_LENGTH/7.x
555
retVal = retVal[:55]
556
557
return retVal
558
559
__functions__ = {
560
HASH.MYSQL: mysql_passwd,
561
HASH.MYSQL_OLD: mysql_old_passwd,
562
HASH.POSTGRES: postgres_passwd,
563
HASH.MSSQL: mssql_passwd,
564
HASH.MSSQL_OLD: mssql_old_passwd,
565
HASH.MSSQL_NEW: mssql_new_passwd,
566
HASH.ORACLE: oracle_passwd,
567
HASH.ORACLE_OLD: oracle_old_passwd,
568
HASH.MD5_GENERIC: md5_generic_passwd,
569
HASH.SHA1_GENERIC: sha1_generic_passwd,
570
HASH.SHA224_GENERIC: sha224_generic_passwd,
571
HASH.SHA256_GENERIC: sha256_generic_passwd,
572
HASH.SHA384_GENERIC: sha384_generic_passwd,
573
HASH.SHA512_GENERIC: sha512_generic_passwd,
574
HASH.CRYPT_GENERIC: crypt_generic_passwd,
575
HASH.JOOMLA: joomla_passwd,
576
HASH.DJANGO_MD5: django_md5_passwd,
577
HASH.DJANGO_SHA1: django_sha1_passwd,
578
HASH.PHPASS: phpass_passwd,
579
HASH.APACHE_MD5_CRYPT: unix_md5_passwd,
580
HASH.UNIX_MD5_CRYPT: unix_md5_passwd,
581
HASH.APACHE_SHA1: apache_sha1_passwd,
582
HASH.VBULLETIN: vbulletin_passwd,
583
HASH.VBULLETIN_OLD: vbulletin_passwd,
584
HASH.OSCOMMERCE_OLD: oscommerce_old_passwd,
585
HASH.SSHA: ssha_passwd,
586
HASH.SSHA256: ssha256_passwd,
587
HASH.SSHA512: ssha512_passwd,
588
HASH.MD5_BASE64: md5_generic_passwd,
589
HASH.SHA1_BASE64: sha1_generic_passwd,
590
HASH.SHA256_BASE64: sha256_generic_passwd,
591
HASH.SHA512_BASE64: sha512_generic_passwd,
592
}
593
594
def _finalize(retVal, results, processes, attack_info=None):
595
if _multiprocessing:
596
gc.enable()
597
598
# NOTE: https://github.com/sqlmapproject/sqlmap/issues/4367
599
# NOTE: https://dzone.com/articles/python-101-creating-multiple-processes
600
for process in processes:
601
try:
602
process.terminate()
603
process.join()
604
except (OSError, AttributeError):
605
pass
606
607
if retVal:
608
removals = set()
609
610
if conf.hashDB:
611
conf.hashDB.beginTransaction()
612
613
while not retVal.empty():
614
user, hash_, word = item = retVal.get(block=False)
615
results.append(item)
616
removals.add((user, hash_))
617
hashDBWrite(hash_, word)
618
619
for item in attack_info or []:
620
if (item[0][0], item[0][1]) in removals:
621
attack_info.remove(item)
622
623
if conf.hashDB:
624
conf.hashDB.endTransaction()
625
626
if hasattr(retVal, "close"):
627
retVal.close()
628
629
def storeHashesToFile(attack_dict):
630
if not attack_dict:
631
return
632
633
items = OrderedSet()
634
635
for user, hashes in attack_dict.items():
636
for hash_ in hashes:
637
hash_ = hash_.split()[0] if hash_ and hash_.strip() else hash_
638
if hash_ and hash_ != NULL and hashRecognition(hash_):
639
item = None
640
if user and not user.startswith(DUMMY_USER_PREFIX):
641
item = "%s:%s\n" % (user, hash_)
642
else:
643
item = "%s\n" % hash_
644
645
if item and item not in items:
646
items.add(item)
647
648
if kb.choices.storeHashes is None:
649
message = "do you want to store hashes to a temporary file "
650
message += "for eventual further processing with other tools [y/N] "
651
652
kb.choices.storeHashes = readInput(message, default='N', boolean=True)
653
654
if items and kb.choices.storeHashes:
655
handle, filename = tempfile.mkstemp(prefix=MKSTEMP_PREFIX.HASHES, suffix=".txt")
656
os.close(handle)
657
658
infoMsg = "writing hashes to a temporary file '%s' " % filename
659
logger.info(infoMsg)
660
661
with openFile(filename, "w+") as f:
662
for item in items:
663
try:
664
f.write(item)
665
except (UnicodeError, TypeError):
666
pass
667
668
def attackCachedUsersPasswords():
669
if kb.data.cachedUsersPasswords:
670
results = dictionaryAttack(kb.data.cachedUsersPasswords)
671
672
lut = {}
673
for (_, hash_, password) in results:
674
lut[hash_.lower()] = password
675
676
for user in kb.data.cachedUsersPasswords:
677
for i in xrange(len(kb.data.cachedUsersPasswords[user])):
678
if (kb.data.cachedUsersPasswords[user][i] or "").strip():
679
value = kb.data.cachedUsersPasswords[user][i].lower().split()[0]
680
if value in lut:
681
kb.data.cachedUsersPasswords[user][i] += "%s clear-text password: %s" % ('\n' if kb.data.cachedUsersPasswords[user][i][-1] != '\n' else '', lut[value])
682
683
def attackDumpedTable():
684
if kb.data.dumpedTable:
685
table = kb.data.dumpedTable
686
columns = list(table.keys())
687
count = table["__infos__"]["count"]
688
689
if not count:
690
return
691
692
debugMsg = "analyzing table dump for possible password hashes"
693
logger.debug(debugMsg)
694
695
found = False
696
col_user = ''
697
col_passwords = set()
698
attack_dict = {}
699
binary_fields = OrderedSet()
700
replacements = {}
701
702
for column in sorted(columns, key=len, reverse=True):
703
if column and column.lower() in COMMON_USER_COLUMNS:
704
col_user = column
705
break
706
707
for column in columns:
708
if column != "__infos__" and table[column]["values"]:
709
if all(INVALID_UNICODE_CHAR_FORMAT.split('%')[0] in (value or "") for value in table[column]["values"]):
710
binary_fields.add(column)
711
712
if binary_fields:
713
_ = ','.join(binary_fields)
714
warnMsg = "potential binary fields detected ('%s'). In case of any problems you are " % _
715
warnMsg += "advised to rerun table dump with '--fresh-queries --binary-fields=\"%s\"'" % _
716
logger.warning(warnMsg)
717
718
for i in xrange(count):
719
if not found and i > HASH_RECOGNITION_QUIT_THRESHOLD:
720
break
721
722
for column in columns:
723
if column == col_user or column == "__infos__":
724
continue
725
726
if len(table[column]["values"]) <= i:
727
continue
728
729
if conf.binaryFields and column in conf.binaryFields:
730
continue
731
732
value = table[column]["values"][i]
733
734
if column in binary_fields and re.search(HASH_BINARY_COLUMNS_REGEX, column) is not None:
735
previous = value
736
value = encodeHex(getBytes(value), binary=False)
737
replacements[value] = previous
738
739
if hashRecognition(value):
740
found = True
741
742
if col_user and i < len(table[col_user]["values"]):
743
if table[col_user]["values"][i] not in attack_dict:
744
attack_dict[table[col_user]["values"][i]] = []
745
746
attack_dict[table[col_user]["values"][i]].append(value)
747
else:
748
attack_dict["%s%d" % (DUMMY_USER_PREFIX, i)] = [value]
749
750
col_passwords.add(column)
751
752
if attack_dict:
753
infoMsg = "recognized possible password hashes in column%s " % ("s" if len(col_passwords) > 1 else "")
754
infoMsg += "'%s'" % ", ".join(col for col in col_passwords)
755
logger.info(infoMsg)
756
757
storeHashesToFile(attack_dict)
758
759
message = "do you want to crack them via a dictionary-based attack? %s" % ("[y/N/q]" if conf.multipleTargets else "[Y/n/q]")
760
choice = readInput(message, default='N' if conf.multipleTargets else 'Y').upper()
761
762
if choice == 'N':
763
return
764
elif choice == 'Q':
765
raise SqlmapUserQuitException
766
767
results = dictionaryAttack(attack_dict)
768
lut = dict()
769
770
for (_, hash_, password) in results:
771
if hash_:
772
key = hash_ if hash_ not in replacements else replacements[hash_]
773
lut[key.lower()] = password
774
lut["0x%s" % key.lower()] = password
775
776
debugMsg = "post-processing table dump"
777
logger.debug(debugMsg)
778
779
for i in xrange(count):
780
for column in columns:
781
if not (column == col_user or column == '__infos__' or len(table[column]['values']) <= i):
782
value = table[column]['values'][i]
783
784
if value and value.lower() in lut:
785
table[column]['values'][i] = "%s (%s)" % (getUnicode(table[column]['values'][i]), getUnicode(lut[value.lower()] or HASH_EMPTY_PASSWORD_MARKER))
786
table[column]['length'] = max(table[column]['length'], len(table[column]['values'][i]))
787
788
@cachedmethod
789
def hashRecognition(value):
790
"""
791
>>> hashRecognition("179ad45c6ce2cb97cf1029e212046e81") == HASH.MD5_GENERIC
792
True
793
>>> hashRecognition("S:2BFCFDF5895014EE9BB2B9BA067B01E0389BB5711B7B5F82B7235E9E182C") == HASH.ORACLE
794
True
795
>>> hashRecognition("foobar") == None
796
True
797
"""
798
799
retVal = None
800
801
if value and len(value) >= 8 and ' ' not in value: # Note: pre-filter condition (for optimization purposes)
802
isOracle, isMySQL = Backend.isDbms(DBMS.ORACLE), Backend.isDbms(DBMS.MYSQL)
803
804
if kb.cache.hashRegex is None:
805
parts = []
806
807
for name, regex in getPublicTypeMembers(HASH):
808
# Hashes for Oracle and old MySQL look the same hence these checks
809
if isOracle and regex == HASH.MYSQL_OLD or isMySQL and regex == HASH.ORACLE_OLD:
810
continue
811
elif regex == HASH.CRYPT_GENERIC:
812
if any((value.lower() == value, value.upper() == value)):
813
continue
814
else:
815
parts.append("(?P<%s>%s)" % (name, regex))
816
817
kb.cache.hashRegex = ('|'.join(parts)).replace("(?i)", "")
818
819
if isinstance(value, six.string_types):
820
match = re.search(kb.cache.hashRegex, value, re.I)
821
if match:
822
algorithm, _ = [_ for _ in match.groupdict().items() if _[1] is not None][0]
823
retVal = getattr(HASH, algorithm)
824
825
return retVal
826
827
def _bruteProcessVariantA(attack_info, hash_regex, suffix, retVal, proc_id, proc_count, wordlists, custom_wordlist, api):
828
if IS_WIN:
829
coloramainit()
830
831
count = 0
832
rotator = 0
833
hashes = set(item[0][1] for item in attack_info)
834
835
wordlist = Wordlist(wordlists, proc_id, getattr(proc_count, "value", 0), custom_wordlist)
836
837
try:
838
for word in wordlist:
839
if not attack_info:
840
break
841
842
count += 1
843
844
if isinstance(word, six.binary_type):
845
word = getUnicode(word)
846
elif not isinstance(word, six.string_types):
847
continue
848
849
if suffix:
850
word = word + suffix
851
852
try:
853
current = __functions__[hash_regex](password=word, uppercase=False)
854
855
if current in hashes:
856
for item in attack_info[:]:
857
((user, hash_), _) = item
858
859
if hash_ == current:
860
retVal.put((user, hash_, word))
861
862
clearConsoleLine()
863
864
infoMsg = "\r[%s] [INFO] cracked password '%s'" % (time.strftime("%X"), word)
865
866
if user and not user.startswith(DUMMY_USER_PREFIX):
867
infoMsg += " for user '%s'\n" % user
868
else:
869
infoMsg += " for hash '%s'\n" % hash_
870
871
dataToStdout(infoMsg, True)
872
873
attack_info.remove(item)
874
875
elif (proc_id == 0 or getattr(proc_count, "value", 0) == 1) and count % HASH_MOD_ITEM_DISPLAY == 0 or hash_regex == HASH.ORACLE_OLD or hash_regex == HASH.CRYPT_GENERIC and IS_WIN:
876
rotator += 1
877
878
if rotator >= len(ROTATING_CHARS):
879
rotator = 0
880
881
status = "current status: %s... %s" % (word.ljust(5)[:5], ROTATING_CHARS[rotator])
882
883
if not api:
884
dataToStdout("\r[%s] [INFO] %s" % (time.strftime("%X"), status))
885
886
except KeyboardInterrupt:
887
raise
888
889
except (UnicodeEncodeError, UnicodeDecodeError):
890
pass # ignore possible encoding problems caused by some words in custom dictionaries
891
892
except Exception as ex:
893
warnMsg = "there was a problem while hashing entry: %s ('%s'). " % (repr(word), getSafeExString(ex))
894
warnMsg += "Please report by e-mail to '%s'" % DEV_EMAIL_ADDRESS
895
logger.critical(warnMsg)
896
897
except KeyboardInterrupt:
898
pass
899
900
finally:
901
if hasattr(proc_count, "value"):
902
with proc_count.get_lock():
903
proc_count.value -= 1
904
905
def _bruteProcessVariantB(user, hash_, kwargs, hash_regex, suffix, retVal, found, proc_id, proc_count, wordlists, custom_wordlist, api):
906
if IS_WIN:
907
coloramainit()
908
909
count = 0
910
rotator = 0
911
912
wordlist = Wordlist(wordlists, proc_id, getattr(proc_count, "value", 0), custom_wordlist)
913
914
try:
915
for word in wordlist:
916
if found.value:
917
break
918
919
count += 1
920
921
if isinstance(word, six.binary_type):
922
word = getUnicode(word)
923
elif not isinstance(word, six.string_types):
924
continue
925
926
if suffix:
927
word = word + suffix
928
929
try:
930
current = __functions__[hash_regex](password=word, uppercase=False, **kwargs)
931
932
if hash_ == current:
933
if hash_regex == HASH.ORACLE_OLD: # only for cosmetic purposes
934
word = word.upper()
935
936
retVal.put((user, hash_, word))
937
938
clearConsoleLine()
939
940
infoMsg = "\r[%s] [INFO] cracked password '%s'" % (time.strftime("%X"), word)
941
942
if user and not user.startswith(DUMMY_USER_PREFIX):
943
infoMsg += " for user '%s'\n" % user
944
else:
945
infoMsg += " for hash '%s'\n" % hash_
946
947
dataToStdout(infoMsg, True)
948
949
found.value = True
950
951
elif (proc_id == 0 or getattr(proc_count, "value", 0) == 1) and count % HASH_MOD_ITEM_DISPLAY == 0:
952
rotator += 1
953
954
if rotator >= len(ROTATING_CHARS):
955
rotator = 0
956
957
status = "current status: %s... %s" % (word.ljust(5)[:5], ROTATING_CHARS[rotator])
958
959
if user and not user.startswith(DUMMY_USER_PREFIX):
960
status += " (user: %s)" % user
961
962
if not api:
963
dataToStdout("\r[%s] [INFO] %s" % (time.strftime("%X"), status))
964
965
except KeyboardInterrupt:
966
raise
967
968
except (UnicodeEncodeError, UnicodeDecodeError):
969
pass # ignore possible encoding problems caused by some words in custom dictionaries
970
971
except Exception as ex:
972
warnMsg = "there was a problem while hashing entry: %s ('%s'). " % (repr(word), getSafeExString(ex))
973
warnMsg += "Please report by e-mail to '%s'" % DEV_EMAIL_ADDRESS
974
logger.critical(warnMsg)
975
976
except KeyboardInterrupt:
977
pass
978
979
finally:
980
if hasattr(proc_count, "value"):
981
with proc_count.get_lock():
982
proc_count.value -= 1
983
984
def dictionaryAttack(attack_dict):
985
global _multiprocessing
986
987
suffix_list = [""]
988
custom_wordlist = [""]
989
hash_regexes = []
990
results = []
991
resumes = []
992
user_hash = []
993
processException = False
994
foundHash = False
995
996
if conf.disableMulti:
997
_multiprocessing = None
998
else:
999
# Note: https://github.com/sqlmapproject/sqlmap/issues/4367
1000
try:
1001
import multiprocessing
1002
1003
# problems on FreeBSD (Reference: https://web.archive.org/web/20110710041353/http://www.eggheadcafe.com/microsoft/Python/35880259/multiprocessing-on-freebsd.aspx)
1004
_ = multiprocessing.Queue()
1005
1006
# problems with ctypes (Reference: https://github.com/sqlmapproject/sqlmap/issues/2952)
1007
_ = multiprocessing.Value('i')
1008
except (ImportError, OSError, AttributeError):
1009
pass
1010
else:
1011
try:
1012
if multiprocessing.cpu_count() > 1:
1013
_multiprocessing = multiprocessing
1014
except NotImplementedError:
1015
pass
1016
1017
for (_, hashes) in attack_dict.items():
1018
for hash_ in hashes:
1019
if not hash_:
1020
continue
1021
1022
hash_ = hash_.split()[0] if hash_ and hash_.strip() else hash_
1023
regex = hashRecognition(hash_)
1024
1025
if regex and regex not in hash_regexes:
1026
hash_regexes.append(regex)
1027
infoMsg = "using hash method '%s'" % __functions__[regex].__name__
1028
logger.info(infoMsg)
1029
1030
for hash_regex in hash_regexes:
1031
keys = set()
1032
attack_info = []
1033
1034
for (user, hashes) in attack_dict.items():
1035
for hash_ in hashes:
1036
if not hash_:
1037
continue
1038
1039
foundHash = True
1040
hash_ = hash_.split()[0] if hash_ and hash_.strip() else hash_
1041
1042
if re.match(hash_regex, hash_):
1043
try:
1044
item = None
1045
1046
if hash_regex not in (HASH.CRYPT_GENERIC, HASH.JOOMLA, HASH.PHPASS, HASH.UNIX_MD5_CRYPT, HASH.APACHE_MD5_CRYPT, HASH.APACHE_SHA1, HASH.VBULLETIN, HASH.VBULLETIN_OLD, HASH.SSHA, HASH.SSHA256, HASH.SSHA512, HASH.DJANGO_MD5, HASH.DJANGO_SHA1, HASH.MD5_BASE64, HASH.SHA1_BASE64, HASH.SHA256_BASE64, HASH.SHA512_BASE64):
1047
hash_ = hash_.lower()
1048
1049
if hash_regex in (HASH.MD5_BASE64, HASH.SHA1_BASE64, HASH.SHA256_BASE64, HASH.SHA512_BASE64):
1050
item = [(user, encodeHex(decodeBase64(hash_, binary=True))), {}]
1051
elif hash_regex in (HASH.MYSQL, HASH.MYSQL_OLD, HASH.MD5_GENERIC, HASH.SHA1_GENERIC, HASH.SHA224_GENERIC, HASH.SHA256_GENERIC, HASH.SHA384_GENERIC, HASH.SHA512_GENERIC, HASH.APACHE_SHA1):
1052
if hash_.startswith("0x"): # Reference: https://docs.microsoft.com/en-us/sql/t-sql/functions/hashbytes-transact-sql?view=sql-server-2017
1053
hash_ = hash_[2:]
1054
item = [(user, hash_), {}]
1055
elif hash_regex in (HASH.SSHA,):
1056
item = [(user, hash_), {"salt": decodeBase64(hash_, binary=True)[20:]}]
1057
elif hash_regex in (HASH.SSHA256,):
1058
item = [(user, hash_), {"salt": decodeBase64(hash_, binary=True)[32:]}]
1059
elif hash_regex in (HASH.SSHA512,):
1060
item = [(user, hash_), {"salt": decodeBase64(hash_, binary=True)[64:]}]
1061
elif hash_regex in (HASH.ORACLE_OLD, HASH.POSTGRES):
1062
item = [(user, hash_), {'username': user}]
1063
elif hash_regex in (HASH.ORACLE,):
1064
item = [(user, hash_), {"salt": hash_[-20:]}]
1065
elif hash_regex in (HASH.MSSQL, HASH.MSSQL_OLD, HASH.MSSQL_NEW):
1066
item = [(user, hash_), {"salt": hash_[6:14]}]
1067
elif hash_regex in (HASH.CRYPT_GENERIC,):
1068
item = [(user, hash_), {"salt": hash_[0:2]}]
1069
elif hash_regex in (HASH.UNIX_MD5_CRYPT, HASH.APACHE_MD5_CRYPT):
1070
item = [(user, hash_), {"salt": hash_.split('$')[2], "magic": "$%s$" % hash_.split('$')[1]}]
1071
elif hash_regex in (HASH.JOOMLA, HASH.VBULLETIN, HASH.VBULLETIN_OLD, HASH.OSCOMMERCE_OLD):
1072
item = [(user, hash_), {"salt": hash_.split(':')[-1]}]
1073
elif hash_regex in (HASH.DJANGO_MD5, HASH.DJANGO_SHA1):
1074
item = [(user, hash_), {"salt": hash_.split('$')[1]}]
1075
elif hash_regex in (HASH.PHPASS,):
1076
if ITOA64.index(hash_[3]) < 32:
1077
item = [(user, hash_), {"salt": hash_[4:12], "count": 1 << ITOA64.index(hash_[3]), "prefix": hash_[:3]}]
1078
else:
1079
warnMsg = "invalid hash '%s'" % hash_
1080
logger.warning(warnMsg)
1081
1082
if item and hash_ not in keys:
1083
resumed = hashDBRetrieve(hash_)
1084
if not resumed:
1085
attack_info.append(item)
1086
user_hash.append(item[0])
1087
else:
1088
infoMsg = "resuming password '%s' for hash '%s'" % (resumed, hash_)
1089
if user and not user.startswith(DUMMY_USER_PREFIX):
1090
infoMsg += " for user '%s'" % user
1091
logger.info(infoMsg)
1092
resumes.append((user, hash_, resumed))
1093
keys.add(hash_)
1094
1095
except (binascii.Error, TypeError, IndexError):
1096
pass
1097
1098
if not attack_info:
1099
continue
1100
1101
if not kb.wordlists:
1102
while not kb.wordlists:
1103
1104
# the slowest of all methods hence smaller default dict
1105
if hash_regex in (HASH.ORACLE_OLD, HASH.PHPASS):
1106
dictPaths = [paths.SMALL_DICT]
1107
else:
1108
dictPaths = [paths.WORDLIST]
1109
1110
message = "what dictionary do you want to use?\n"
1111
message += "[1] default dictionary file '%s' (press Enter)\n" % dictPaths[0]
1112
message += "[2] custom dictionary file\n"
1113
message += "[3] file with list of dictionary files"
1114
choice = readInput(message, default='1')
1115
1116
try:
1117
if choice == '2':
1118
message = "what's the custom dictionary's location?\n"
1119
dictPath = readInput(message)
1120
if dictPath:
1121
dictPaths = [dictPath]
1122
logger.info("using custom dictionary")
1123
elif choice == '3':
1124
message = "what's the list file location?\n"
1125
listPath = readInput(message)
1126
checkFile(listPath)
1127
dictPaths = getFileItems(listPath)
1128
logger.info("using custom list of dictionaries")
1129
else:
1130
logger.info("using default dictionary")
1131
1132
dictPaths = [_ for _ in dictPaths if _]
1133
1134
for dictPath in dictPaths:
1135
checkFile(dictPath)
1136
1137
if isZipFile(dictPath):
1138
_ = zipfile.ZipFile(dictPath, 'r')
1139
if len(_.namelist()) == 0:
1140
errMsg = "no file(s) inside '%s'" % dictPath
1141
raise SqlmapDataException(errMsg)
1142
else:
1143
_.open(_.namelist()[0])
1144
1145
kb.wordlists = dictPaths
1146
1147
except Exception as ex:
1148
warnMsg = "there was a problem while loading dictionaries"
1149
warnMsg += " ('%s')" % getSafeExString(ex)
1150
logger.critical(warnMsg)
1151
1152
message = "do you want to use common password suffixes? (slow!) [y/N] "
1153
1154
if readInput(message, default='N', boolean=True):
1155
suffix_list += COMMON_PASSWORD_SUFFIXES
1156
1157
infoMsg = "starting dictionary-based cracking (%s)" % __functions__[hash_regex].__name__
1158
logger.info(infoMsg)
1159
1160
for item in attack_info:
1161
((user, _), _) = item
1162
if user and not user.startswith(DUMMY_USER_PREFIX):
1163
custom_wordlist.append(normalizeUnicode(user))
1164
1165
# Algorithms without extra arguments (e.g. salt and/or username)
1166
if hash_regex in (HASH.MYSQL, HASH.MYSQL_OLD, HASH.MD5_GENERIC, HASH.SHA1_GENERIC, HASH.SHA224_GENERIC, HASH.SHA256_GENERIC, HASH.SHA384_GENERIC, HASH.SHA512_GENERIC, HASH.APACHE_SHA1):
1167
for suffix in suffix_list:
1168
if not attack_info or processException:
1169
break
1170
1171
if suffix:
1172
clearConsoleLine()
1173
infoMsg = "using suffix '%s'" % suffix
1174
logger.info(infoMsg)
1175
1176
retVal = None
1177
processes = []
1178
1179
try:
1180
if _multiprocessing:
1181
if _multiprocessing.cpu_count() > 1:
1182
infoMsg = "starting %d processes " % _multiprocessing.cpu_count()
1183
singleTimeLogMessage(infoMsg)
1184
1185
gc.disable()
1186
1187
retVal = _multiprocessing.Queue()
1188
count = _multiprocessing.Value('i', _multiprocessing.cpu_count())
1189
1190
for i in xrange(_multiprocessing.cpu_count()):
1191
process = _multiprocessing.Process(target=_bruteProcessVariantA, args=(attack_info, hash_regex, suffix, retVal, i, count, kb.wordlists, custom_wordlist, conf.api))
1192
processes.append(process)
1193
1194
for process in processes:
1195
process.daemon = True
1196
process.start()
1197
1198
while count.value > 0:
1199
time.sleep(0.5)
1200
1201
else:
1202
warnMsg = "multiprocessing hash cracking is currently "
1203
warnMsg += "%s on this platform" % ("not supported" if not conf.disableMulti else "disabled")
1204
singleTimeWarnMessage(warnMsg)
1205
1206
retVal = _queue.Queue()
1207
_bruteProcessVariantA(attack_info, hash_regex, suffix, retVal, 0, 1, kb.wordlists, custom_wordlist, conf.api)
1208
1209
except KeyboardInterrupt:
1210
print()
1211
processException = True
1212
warnMsg = "user aborted during dictionary-based attack phase (Ctrl+C was pressed)"
1213
logger.warning(warnMsg)
1214
1215
finally:
1216
_finalize(retVal, results, processes, attack_info)
1217
1218
clearConsoleLine()
1219
1220
else:
1221
for ((user, hash_), kwargs) in attack_info:
1222
if processException:
1223
break
1224
1225
if any(_[0] == user and _[1] == hash_ for _ in results):
1226
continue
1227
1228
count = 0
1229
found = False
1230
1231
for suffix in suffix_list:
1232
if found or processException:
1233
break
1234
1235
if suffix:
1236
clearConsoleLine()
1237
infoMsg = "using suffix '%s'" % suffix
1238
logger.info(infoMsg)
1239
1240
retVal = None
1241
processes = []
1242
1243
try:
1244
if _multiprocessing:
1245
if _multiprocessing.cpu_count() > 1:
1246
infoMsg = "starting %d processes " % _multiprocessing.cpu_count()
1247
singleTimeLogMessage(infoMsg)
1248
1249
gc.disable()
1250
1251
retVal = _multiprocessing.Queue()
1252
found_ = _multiprocessing.Value('i', False)
1253
count = _multiprocessing.Value('i', _multiprocessing.cpu_count())
1254
1255
for i in xrange(_multiprocessing.cpu_count()):
1256
process = _multiprocessing.Process(target=_bruteProcessVariantB, args=(user, hash_, kwargs, hash_regex, suffix, retVal, found_, i, count, kb.wordlists, custom_wordlist, conf.api))
1257
processes.append(process)
1258
1259
for process in processes:
1260
process.daemon = True
1261
process.start()
1262
1263
while count.value > 0:
1264
time.sleep(0.5)
1265
1266
found = found_.value != 0
1267
1268
else:
1269
warnMsg = "multiprocessing hash cracking is currently "
1270
warnMsg += "%s on this platform" % ("not supported" if not conf.disableMulti else "disabled")
1271
singleTimeWarnMessage(warnMsg)
1272
1273
class Value(object):
1274
pass
1275
1276
retVal = _queue.Queue()
1277
found_ = Value()
1278
found_.value = False
1279
1280
_bruteProcessVariantB(user, hash_, kwargs, hash_regex, suffix, retVal, found_, 0, 1, kb.wordlists, custom_wordlist, conf.api)
1281
1282
found = found_.value
1283
1284
except KeyboardInterrupt:
1285
print()
1286
processException = True
1287
warnMsg = "user aborted during dictionary-based attack phase (Ctrl+C was pressed)"
1288
logger.warning(warnMsg)
1289
1290
for process in processes:
1291
try:
1292
process.terminate()
1293
process.join()
1294
except (OSError, AttributeError):
1295
pass
1296
1297
finally:
1298
_finalize(retVal, results, processes, attack_info)
1299
1300
clearConsoleLine()
1301
1302
results.extend(resumes)
1303
1304
if foundHash and len(hash_regexes) == 0:
1305
warnMsg = "unknown hash format"
1306
logger.warning(warnMsg)
1307
1308
if len(results) == 0:
1309
warnMsg = "no clear password(s) found"
1310
logger.warning(warnMsg)
1311
1312
return results
1313
1314
def crackHashFile(hashFile):
1315
i = 0
1316
attack_dict = {}
1317
1318
check = None
1319
for line in getFileItems(conf.hashFile):
1320
if check is None and not attack_dict and ':' in line:
1321
check = any(re.search(_, line) for _ in getPublicTypeMembers(HASH, True))
1322
1323
if ':' in line and check is False:
1324
user, hash_ = line.split(':', 1)
1325
attack_dict[user] = [hash_]
1326
else:
1327
attack_dict["%s%d" % (DUMMY_USER_PREFIX, i)] = [line]
1328
i += 1
1329
1330
dictionaryAttack(attack_dict)
1331
1332