csababarta / ntdsxtract

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

Problem parsing supplementary credentials #5

Closed PAFsec closed 9 years ago

PAFsec commented 9 years ago

Hi, First of all, thank you for your code!

It looks like there is a little problem while retrieving the Supplementary Credentials. in the ntdsxtract/ntds/dsobjects.py file

def ParseUserProperty(self, text, offset):
        [...]
        elif Name == u"Primary:CLEARTEXT":
            self.Password = unhexlify(text[offset:offset+ValueLength]).decode('utf-16')
        else:
            print Name
        return offset + ValueLength

I get an encoding error because the value seems to already be an ascii String

Supplemental credentials:
  Kerberos newer keys
    salt: I[...]t
    Credentials
      18 fa[...]53
      17 cb[...]a2
      3 20[...]70
  Kerberos keys
    salt: I[...]t
    Credentials
      3 20[...]70
    OldCredentials
      3 c1[...]10
      1 c1[...]10
  WDigest hashes
    903e44489957c3a3ca489b86be83d12f
    [...]
    85f363474700b4dfa0ace59bdbc6ad98
  Packages
    Kerberos-Newer-Keys
    Kerberos
    WDigest
    CLEARTEXT
 [!] Error! 'ascii' codec can't encode characters in position 0-15: ordinal not in range(128)

which turns to be coming from there :

  File "/opt/ntdsxtract/dsusers.py", line 446, in <module>
    processUser(user)
  File "/opt/ntdsxtract/dsusers.py", line 178, in processUser
    creds.Print("  ")
  File "/opt/ntdsxtract/ntds/dsobjects.py", line 506, in Print
    print "{0}Password: {1}".format(indent, self.Password)

I personnaly resolved that bug by applying this modification in ntdsxtract/ntds/dsobjects.py:

def ParseUserProperty(self, text, offset):
        [...]
        elif Name == u"Primary:CLEARTEXT":
            self.Password = text[offset:offset+ValueLength])
        else:
            print Name
        return offset + ValueLength

As I just jumped into your code, I might not have a clean step back on what's really happening, so I let you consider if it is a viable fix.

Take care ;)

csababarta commented 9 years ago

Hi PAFsec,

i decided to implement a different solution to your problem. Could you please check if it works? Let me know if you still have the decoding problem.

Thanks for your bug report.

PAFsec commented 9 years ago

Hello,

I just checked your modifications. If I only give the --supplcred argument, it looks like it work well.

Although, giving all the needed inputs to retrieve passwords hashes got me the same kind of decoding error than previously mentionned:

  File "dsusers.py", line 486, in <module>
    processUser(user)
  File "dsusers.py", line 181, in processUser
    creds = user.getSupplementalCredentials()
  File "/opt/ntdsxtract/ntds/dsobjects.py", line 255, in getSupplementalCredentials
    return dsSupplCredentials(tmpdec)
  File "/opt/ntdsxtract/ntds/dsobjects.py", line 507, in __init__
    self.ParseUserProperties(text)
  File "/opt/ntdsxtract/ntds/dsobjects.py", line 575, in ParseUserProperties
    offset = self.ParseUserProperty(text, offset)
  File "/opt/ntdsxtract/ntds/dsobjects.py", line 618, in ParseUserProperty
    self.Password = unicode(unhexlify(text[offset:offset+ValueLength]).decode('utf-16')).encode('utf8')
  File "/usr/lib64/python2.7/encodings/utf_16.py", line 16, in decode
    return codecs.utf_16_decode(input, errors, True)
UnicodeDecodeError: 'utf16' codec can't decode bytes in position 100-101: illegal encoding

Thank you for your work.

csababarta commented 9 years ago

Hi PAFsec,

here is another version. Unfortunately as I cannot really reproduce the error, I cannot do real testing. Could you please test this version. In case of any exception it should dump the data in hex which should work fine.