csababarta / ntdsxtract

Active Directory forensic framework
http://www.ntdsxtract.com
GNU General Public License v3.0
320 stars 108 forks source link

Windows Server 2016 password hashes length exception #30

Open sfapleshakov opened 5 years ago

sfapleshakov commented 5 years ago

Hi, thank you many years of wonderful usage!! I was trying to extract hashes from a Windows Server 2016 NTDS.dit using the latest libesedb (earlier versions complained about "fixed-size data type 12") and it looks like Windows Server 2016 introduced a 4 byte value somewhere within ATTk590689, which results in dsencryption.py/dsDecryptPEK function returning a value that is 80 bytes long, instead of 76 (as mentioned here https://www.exploit-db.com/docs/english/18244-active-domain-offline-hash-dump-&-forensic-analysis.pdf). This in turn, causes the LM and NT hash decryption to fail with the following error trace, where the d2 enc_hash slice has 4 extra bytes in it. Pwdformat has no effect on this. Can anyone else confirm similar behavior?

Command: python dscomputers.py '/home/user/libesedb/esedbtools/ntds.dit.export/datatable.4' output --syshive '/home/user/Desktop/SYSTEM' --passwordhashes --lmoutfile lmout --ntoutfile ntout --pwdformat ocl

Error trace:

<snip>
Password hashes:Error in sys.excepthook:
Traceback (most recent call last):
  File "/home/user/ntdsxtract/ntds/__init__.py", line 31, in simple_exception
    sys.stderr.write("[!] Error!", value, "\n")
TypeError: function takes exactly 1 argument (3 given)

Original exception was:
Traceback (most recent call last):
  File "dscomputers.py", line 296, in <module>
    processComputer(computer)
  File "dscomputers.py", line 92, in processComputer
    (lm, nt) = computer.getPasswordHashes()
  File "/home/user/ntdsxtract/ntds/dsobjects.py", line 221, in getPasswordHashes
    nthash = hexlify(dsDecryptSingleHash(self.SID.RID, nthash))
  File "/home/user/ntdsxtract/ntds/dsencryption.py", line 67, in dsDecryptSingleHash
    hash = d1.decrypt(enc_hash[:8]) + d2.decrypt(enc_hash[8:])
  File "/usr/lib/python2.7/dist-packages/Crypto/Cipher/blockalgo.py", line 295, in decrypt
    return self._cipher.decrypt(ciphertext)
ValueError: Input strings must be a multiple of 8 in length
wgroenewold commented 5 years ago

Why didn't you supply a link_table?

sfapleshakov commented 5 years ago

Why didn't you supply a link_table?

You mean for debugging here or passing it to dscomputers.py? The script doesn't seem to take a link table as an argument and the link table file is a production copy I'd like to keep private.

wgroenewold commented 5 years ago

I was confusing dscomputers.py with dsusers.py, which takes that as a second argument.

ThugSiem commented 4 years ago

I am getting the same error on dsusers.py.

c0d3z3r0 commented 4 years ago

Quick&Dirty-Fix:

diff --git a/ntds/dsencryption.py b/ntds/dsencryption.py
index 5a5aaeb..55bb470 100755
--- a/ntds/dsencryption.py
+++ b/ntds/dsencryption.py
@@ -64,5 +64,5 @@ def dsDecryptSingleHash(rid, enc_hash):
     (des_k1,des_k2) = sid_to_key(rid)
     d1 = DES.new(des_k1, DES.MODE_ECB)
     d2 = DES.new(des_k2, DES.MODE_ECB)
-    hash = d1.decrypt(enc_hash[:8]) + d2.decrypt(enc_hash[8:])
-    return hash
\ No newline at end of file
+    hash = d1.decrypt(enc_hash[:8]) + d2.decrypt(enc_hash[8:16])
+    return hash[:16]
0pa9ue commented 4 years ago

Quick&Dirty-Fix:

diff --git a/ntds/dsencryption.py b/ntds/dsencryption.py
index 5a5aaeb..55bb470 100755
--- a/ntds/dsencryption.py
+++ b/ntds/dsencryption.py
@@ -64,5 +64,5 @@ def dsDecryptSingleHash(rid, enc_hash):
     (des_k1,des_k2) = sid_to_key(rid)
     d1 = DES.new(des_k1, DES.MODE_ECB)
     d2 = DES.new(des_k2, DES.MODE_ECB)
-    hash = d1.decrypt(enc_hash[:8]) + d2.decrypt(enc_hash[8:])
-    return hash
\ No newline at end of file
+    hash = d1.decrypt(enc_hash[:8]) + d2.decrypt(enc_hash[8:16])
+    return hash[:16]

This works perfect!!!Thanks