Dumping the contents of ntds.dit files using PowerShell

October 20, 2015 | Michael Grafnetter

Although there exist several tools for dumping password hashes from the Active Directory database files, including the open-source NTDSXtract from Csaba Bárta whose great research started it all, they have these limitations:

  • They do not support the built-in indices, so searching for a single object is slow when dealing with large databases.
  • Most of the tools are either Linux-only or running them on Windows is not simple enough.
  • Almost none of these tools can modify the database. And if they do, they do not support transaction logs and are quite cumbersome.

Therefore, I have decided to create my own set of PowerShell cmdlets that wouldn’t have these shortcomings. In the process, I have unintentionally created my own framework that is built on top of Microsoft’s ManagedEsent library and hides the complexity of the underlying database. I am planning to release it at GitHub later this year.

One of the cmdlets I have created is Get-ADDBAccount, which can be used to extract password hashes, Kerberos keys and even reversibly encrypted passwords from ntds.dit files. Here is an example of its usage:

The output is identical to what the Get-ADReplAccount cmdlet would return:

I have also created several Views that generate output for the most popular password crackers, including Hashcat, John the Ripper and Ophcrack:

But with the Golden Ticket or Pass-the-Hash functionality of mimikatz, an attacker could seize control of the entire Active Directory forest even without cracking those password hashes.

As a countermeasure, it is crucial for companies to secure physical access to domain controllers, their backups and their VHD/VHDX/VMDK images in case of virtualized DCs. Turning on BitLocker is not a bad idea either. I really look forward to the new security features planned for Windows Server 2016, including Shielded VMs and Virtual TPMs.


Tags: , ,

65 comments on “Dumping the contents of ntds.dit files using PowerShell

  1. thierry says:

    Hello
    Congratulations for this great work I am currently testing the safety of my Active Directory with your powershell module and meets the following error message:

    PS C:\Users\admin> Get-BootKey -SystemHivePath ‘D:\tmp\ifm\registry\SYSTEM’
    040b02c9bd79ae68a95ccde275e12868
    PS C:\Users\admin> $key = Get-BootKey -SystemHivePath ‘D:\tmp\ifm\registry\SYSTEM’
    PS C:\Users\admin> Get-ADDBAccount -all -DBPath ‘D:\tmp\ifm\ActiveDirectory\ntds.dit’ -BootKey $key
    Get-ADDBAccount : Cannot marshal: Encountered unmappable character.
    Au caractère Ligne:1 : 1
    + Get-ADDBAccount -all -DBPath ‘D:\tmp\ifm\ActiveDirectory\ntds.dit’ -BootKey $key
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : OpenError: (:) [Get-ADDBAccount], ArgumentException
    + FullyQualifiedErrorId : DBContextError,DSInternals.PowerShell.Commands.GetADDBAccountCommand I fail to see where does the problem, thank you for your help

    • Michael Grafnetter says:

      This problem only occurs on Windows 7/2008. I know about it and it is caused by a library I am using (C Microsoft). I have reported the bug and I am awaiting a new release. Unfortunately, I currently cannot do much more about it.

  2. lee says:

    hi. thanks for working on this. i was testing in my lab (windows 2012 active directory) and am getting errors. how did you create the files: ‘C:\IFM\registry\SYSTEM’ and ‘C:\IFM\Active Directory\ntds.dit’? i used vssadmin create shadow /for=c:, and then copied SYSTEM and ntds.dit to a temp directory, but when i try to create the $key variable from your example i get: Get-BootKey : The configuration registry database is corrupt.

    • Michael Grafnetter says:

      Hi lee, I used ntdsutil IFM. It is the simplest way and generates a correct SYSTEM hive. Or use reg save I am using Windows-built-in mechanism of mounting the hive rather than my own, so it cannot be in a dirty state.

  3. Nick says:

    Get a weird error.

    ntds.dit and SYSTEM is exported from a win2008R2 server using ntdsutil. Running the powershell module from a win2012R2.

    Unblocked the module zip file before before installing.

    PS C:\> $key = Get-BootKey -SystemHivePath “C:\SYSTEM”
    PS C:\>
    PS C:\> $key
    2bc5ae2c28662f04b23a33008c743be8
    PS C:\>
    PS C:\> Get-ADDBAccount -All -DBPath “C:\ntds.dit” -BootKey $key
    Get-ADDBAccount : Parameter is not a hexadecimal string.
    At line:1 char:1
    + Get-ADDBAccount -All -DBPath “C:\ntds.dit” -BootKey $key
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : OpenError: (:) [Get-ADDBAccount], ArgumentException
    + FullyQualifiedErrorId : DBContextError,DSInternals.PowerShell.Commands.GetADDBAccountCommand

    • Michael Grafnetter says:

      OK, that is weird, I will look into it. Could you please send me stack trace of that exception?

  4. Is there a way to access AD password hashes over the network?
    This appears to read the hashes using Esent, which means you have to be on the same machine as a domain controller.

    • Michael Grafnetter says:

      See my previous answer. And the Esent library is present on all Windows systems. So it is possible to copy a ntds.dit file from Windows Server 2012 R2 and open it on Windows 8.1. If a different Windows kernel shall be used, the database must be defragmented first using esentutil.

  5. Another question. I am doing this on my domain controller.

    $bk = Get-BootKey -Online
    Get-ADDBAccount -samAccountName kevin -DBPath ‘C:\windows\ntds\ntds.dit’ -BootKey $bk and I am getting an error that the file is locked, which is because the ad service is running and using it. Do you have to stop my ad service in order to use this powershell command? Is there a way to access the db while it is in use?

  6. KevD says:

    This is awesome stuff!
    One note I wanted to make on the PowerShell example listed to dump to a hash file for use with John the Ripper… By default, out-file in PowerShell will create the text file in Unicode format, which will not be recognized by JtR. You will need to append ‘-encoding ascii’ to export to a file that will work.
    Other than that, this works fabulously!
    Thanks!

    • Michael Grafnetter says:

      Thank you, KevD, for your remark. I have updated the example in the article accordingly.

  7. Martin Handl says:

    Very sweet tool! A fast way to get to the samaccountnames:

    (Get-ADDBAccount -All -DBPath .\ntds.dit -key (Get-Content -path .\syskey.txt)).samaccountname | Out-File .\users.txt

  8. Drew R says:

    Getting trapped with the error below. I can run the first two lines of the script and see the output fly across the screen, but it always ends with this error. When I add the output function, it just fails with this same error. Any ideas?
    PS C:\WINDOWS\system32> Get-ADDBAccount -All -DBPath ‘C:\ntds.dit’ -BootKey $nkey |
    Format-Custom -View Ophcrack |
    Out-File ‘c:\hashes.txt’
    Get-ADDBAccount : Value cannot be null.
    Parameter name: value
    At line:1 char:1
    + Get-ADDBAccount -All -DBPath ‘C:\ntds.dit’ -BootKey $nkey |
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Get-ADDBAccount], ArgumentNullException
    + FullyQualifiedErrorId : System.ArgumentNullException,DSInternals.PowerShell.Commands.GetADDBAccountCommand

    • Michael Grafnetter says:

      Hi Drew, could you please send me the stack trace of this exception? $Error[0].Exception.StackTrace

  9. John says:

    Hi there. This seams to be working great however it is showing no password. ClearText field is empty. Am I doing something wrong?

    Thank you

    • Michael Grafnetter says:

      Hi John, the ClearText field only contains a value if the option “Store password using reversible encryption” is enabled on the specific account or globally.

  10. Martin Handl says:

    As it seems is the encryption used for the AD database somewhat different to 2012R2 DCs. When I try to get – for example – the krgtgt account the following result occurs:

    #retrieving the bootkey
    $bootkey = (Get-ChildItem -Path C:\temp -Include *pfx -Recurse).Basename.split(“_”)[-1].Replace(“-“,””)

    #retrieving the krbtgt account from ntds.dit
    Get-ADDBAccount -SamAccountName krbtgt -DBPath C:\NTDS\ntds.dit -BootKey $bootkey

    Get-ADDBAccount : Invalid PEK signature.
    At line:1 char:1
    + Get-ADDBAccount -SamAccountName krbtgt -DBPath C:\NTDS\ntds.dit -BootKey $bootke …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Get-ADDBAccount], Exception
    + FullyQualifiedErrorId : System.Exception,DSInternals.PowerShell.Commands.GetADDBAccountCommand I am just at the moment trying the same thing at the same domain with a 2012R2 DC. I will keep you informed

  11. Martin Handl says:

    Disregard everything! I mistook the Backupkey with the syskey

  12. Nikola says:

    Hello,Michael!

    Dump from w2008 r2 SYSTEM + ntds.dit

    Open win7 x64 install power shell v5 and run You script

    $key = Get-BootKey -SystemHivePath ‘c:\system’;
    $key ok

    Get-ADDBAccount -All -DBPath ‘c:\ntds.dit’ -BootKey $key

    result
    ====================================================
    Get-ADDBAccount : The database is not in a clean state. Try to recover it first by running the ‘esentutl /r edb /d’ com
    mand.
    At line:1 char:1
    + Get-ADDBAccount -All -DBPath ‘c:\ntds.dit’ -BootKey $key |Format
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo: OpenError: (:) [Get-ADDBAccount], InvalidDatabaseStateException
    + FullyQualifiedErrorId : BContextError,DSInternals.PowerShell.Commands.GetADDBAccountCommand
    ====================================================== After run
    esentutl /r c:\ntds.dit /d

    Operation terminated with error -1003 (JET_errInvalidParameter, Invalid API parameter) after 0.0 seconds.

    • Michael Grafnetter says:

      Nikola, there might be a problem with access rights. Please, try putting the ntds.dit file into a folder.

  13. Ubermedina says:

    Getting the error below when following the above tutorial.

    Get-ADDBAccount : Unicode normalization failed
    At line:1 char:1

    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : OpenError: (:) [Get-ADDBAccount], EsentUnicodeTranslationFailException
    + FullyQualifiedErrorId : DBContextError,DSInternals.PowerShell.Commands.GetADDBAccountCommand

    • Michael Grafnetter says:

      Hi Ubermedina, never seen this exception. Could you please send me the OS version of the DC and of the computer on which you are using the DSInternals module? What regional settings are you using on both of these systems?

  14. Ryan says:

    Hello Michael, I have exactly the same error as Nikola up there. I exported ntds.dit and SYSTEM from a shadow copy on a W2008R2 and tried to use your tools on a W7x64 machine with a fresh Powershellv5. I made sure to work within a folder where I have full control.
    Any further hint very much appreciated!
    Thanks++
    Ryan

    PS C:\Users\Ryan\Documents\AD\NTDS> $key = Get-BootKey -SystemHivePath .\SYSTEM

    PS C:\Users\Ryan\Documents\AD\NTDS> Get-ADDBAccount -All -DBPath .\ntds.dit -BootKey $key
    Get-ADDBAccount : The database is not in a clean state. Try to recover it first by running the ‘esentutl /r edb /d’ command.
    At line:1 char:1
    + Get-ADDBAccount -All -DBPath .\ntds.dit -BootKey $key
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : OpenError: (:) [Get-ADDBAccount], InvalidDatabaseStateException
    + FullyQualifiedErrorId : DBContextError,DSInternals.PowerShell.Commands.GetADDBAccountCommand

    PS C:\Users\Ryan\Documents\AD\NTDS> esentutl /r ntds.dit /d

    Extensible Storage Engine Utilities for Microsoft(R) Windows(R)
    Version 6.1
    Copyright (C) Microsoft Corporation. All Rights Reserved.

    Initiating RECOVERY mode…
    Logfile base name: ntds.dit
    Log files:
    System files:
    Database Directory:

    Operation terminated with error -1003 (JET_errInvalidParameter, Invalid API parameter) after 0.0 seconds.

    • Michael Grafnetter says:

      Hi Ryan, you are apparently running “esentutl /r ntds.dit /d” instead of “esentutl /r edb /d”…

  15. Don C says:

    Hey Michael,

    Great info! Thanks for doing this. I keep running into the following error after this step:
    Get-ADDBAccount -all -DBPath ‘C:\temp\ntds.dit’ -BootKey $key

    Get-ADDBAccount : Cannot bind parameter ‘BootKey’. Cannot convert value “55f59f858ee5a3a6f5a941d95401d272” to type “System.Byte”. Error: “Input string was not in a correct format.”
    At line:1 char:64
    + Get-ADDBAccount -all -DBPath ‘C:\temp\ntds.dit’ -BootKey $key
    + ~~~~
    + CategoryInfo : InvalidArgument: (:) [Get-ADDBAccount], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,DSInternals.PowerShell.Commands.GetADDBAccountCo
    mmand

    Have you seen this before? I am running it on Win8.1, powershell ver 4, ntds.dit and system is from 2012R2.

    • Michael Grafnetter says:

      Don, the bug will be resolved in the next release. Please use GutHub for bug reports, that platform is much more suitable for this purpose.

  16. Simon says:

    Hi Michael. I have a problem I hope you can help with. I can successfully get my boot key with Get-Bootkey and I can see it is correct. However, when I run:

    Get-ADDBAccount -All -DBPath ‘C:\temp\ntds.dit’ -BootKey $key I get the following error:

    Get-ADDBAccount : Cannot bind parameter ‘BootKey’. Cannot convert value “f15d29209a8b3c2de0e8eb9ba02c9aeb” to type
    “System.Byte”. Error: “Input string was not in a correct format.”
    At line:1 char:62
    + Get-ADDBAccount -All -DBPath ‘C:\temp\ntds.dit’ -BootKey $key
    + ~~~~
    + CategoryInfo : InvalidArgument: (:) [Get-ADDBAccount], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,DSInternals.PowerShell.Commands.GetADDBAccountCommand

    This is on Win 10 using .Net 4.6.2 and DSInternals 2.21. Is this an error you have come across before?

    Thanks in advance for any help you can offer.

    Simon

  17. kurien says:

    Hi Michael. I have a problem I hope you can help with.
    My directory schema not contain samaccounttype or samaccountname so i try using -ObjectGuid and surprise :

    Get-ADDBAccount -ObjectGuid xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxx -DBPath ‘C:\prj\adamntds.dit’ -BootKey $key
    Get-ADDBAccount : Directory schema does not contain attribute ‘sAMAccountType’.
    Au caractère Ligne:1 : 1
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Get-ADDBAccount], SchemaAttributeNotFoundException
    + FullyQualifiedErrorId : DSInternals.Common.Exceptions.SchemaAttributeNotFoundException,DSInternals.PowerShell.Co
    mmands.GetADDBAccountCommand

    Best regards

  18. Keith Fraser says:

    Hi Michael

    Our company would like to analyze our users passwords to make a case for better policies.

    We would like to not use their current passwords but use the data from the NTHashHistory.

    Could you help create an output of the NTHashHistory in NTLM Hash format? A table with the SamAccountName, DistinguishedName and NTHashHistory converted would be amazing.

    Thanks,

    Keith

    • Anonymous says:

      You can use get-ADreplaccount or get-addbaccount and take the whole output and then parse with a simple powershell script to get the history.

    • Skwerl23 says:

      Easy. Just get the whole data base from get-addbaccount, and then parse the output yourself.

      • Michael Grafnetter says:

        No need to actually “parse” the output, because you are already getting objects from the Get-AD*Account cmdlets. You only need to format the output according to your requirements.

  19. Vadim says:

    Hello Michael, I get NullReferenceException when trying to execute Get-ADDBAccount. Windows 7 64-bit, PS 5.1. Exception stack trace is below:

    at DSInternals.DataStore.DatastoreObject.ReadAttribute(String name, Byte[]& value)
    at DSInternals.DataStore.DirectoryAgent.GetSecretDecryptor(Byte[] bootKey)
    at DSInternals.DataStore.DirectoryAgent.GetAccount(DatastoreObject foundObject, Object objectIdentifier, Byte[] bootKey)
    at DSInternals.PowerShell.Commands.GetADDBAccountCommand.ReturnSingleAccount(Byte[] bootKey)
    at System.Management.Automation.CommandProcessor.ProcessRecord()

  20. John says:

    Hi, I got the same unicode error as Ubermedina using Didier’s .dit file at https://blog.didierstevens.com/2016/07/12/practice-ntds-dit-file-part-1/ using Windows Server 2003 Standard Edition with SP1 (English)
    Can you help? thanks

  21. Matt says:

    Is there any way to filter the account?
    It would be useful to have wildcards in the DistinguishedName.

    • Michael Grafnetter says:

      The filtering parameters (-ObjectSid, -DistinguishedName, -ObjectGuid and -SamAccountName) accept pipeline input by property name. And you can use Where-Object for wildcards.

      • Joseph says:

        Hi Michael, do you have an example how to do this? I can’t seem to figure it out.

        • Michael Grafnetter says:

          Filtering by DN:
          Get-ADDBAccount ... | where DistinguishedName -like '*,OU=Admins,DC=contoso,DC=com'

          Selecting multiple accounts (presuming that you have a CSV file with a column called SamAccountName):
          Import-CSV ... | select SamAccountName | Get-ADDBAccount -DBPath ... -BootKey ...

          Both examples are basic PowerShell stuff and bot specific to DSInternals.

  22. DC says:

    Hey Michael,

    Great work man! I did run across an error when I tried to re-use it recently. After running Get-ADDBAccount -all -DBPath ‘C:\temp\ntds\ntds.dit’ -BootKey $key

    Get-ADDBAccount : An item with the same key has already been added.
    At line:1 char:1
    + Get-ADDBAccount -all -DBPath ‘C:\temp\ntds\ntds.dit’ -BootKey $key | …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : OpenError: (:) [Get-ADDBAccount], ArgumentException
    + FullyQualifiedErrorId : DBContextError,DSInternals.PowerShell.Commands.GetADDBAccountCommand

    • Michael Grafnetter says:

      Thanks for reporting this. Could you please file a bug at GitHub and provide a full exception stack trace?

  23. Chris says:

    Hi,

    Great work! Is it possible to filter the output on more than just -DistinguishedName? For example, Enabled: True?

    Chris

  24. Duette says:

    This is extremely quick compared to NTDExtract and DSUsers which I normally use on kali. However there is one concern I want to share and get some recommendation as well. When extracting the hashes it not only gives you the NT/LM hashes for all domain users but it also outputs the hashes of what seems to be computer/Kerberos accounts as well. Is there anyway to limit this output to just Domain users.

    Reason being is that when exporting to JTR for example, having the kerberos accounts as well as user accounts will make the list twice as big and when working with large Domains this can increase the time it takes to start cracking significantly. I also noticed that it doesn’t like “Select-String” args when piping. Example, I tried “Get-ADDB……. | select-strings “stringname”, it does not return the string even when I know its there but it also does’t return an error either. I know ‘select’ works cause I dumped the output ADDB……to a ‘txt’ file and then was able to parse and select strings from that ‘txt’ file but no luck when going string from the ADDB….output to pipe.

    • Michael Grafnetter says:

      As the cmdlets return objects, the filtering should rather be be done using Where-Object than Select-String.

  25. ravi says:

    My DIT file is huge, can I just extract the hashes for a few users, that i have on a separate text file?

    • Michael Grafnetter says:

      The filtering parameters (-ObjectSid, -DistinguishedName, -ObjectGuid and -SamAccountName) accept pipeline input by property name.

  26. Peter says:

    PS C:\Tools\DSInternals_v2.22\DSInternals> Get-ADDBAccount -All -DBPath C:\Tools\ntds.dit\ntds.dit -BootKey $key
    Get-ADDBAccount : The database is not in a clean state. Try to recover it first by running the ‘esentutl /r edb /d’
    command. In Zeile:1 Zeichen:1
    + Get-ADDBAccount -All -DBPath C:\Tools\ntds.dit\ntds.dit -BootKey $key
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : OpenError: (:) [Get-ADDBAccount], InvalidDatabaseStateException
    + FullyQualifiedErrorId : DBContextError,DSInternals.PowerShell.Commands.GetADDBAccountCommand

    PS C:\Tools\DSInternals_v2.22\DSInternals> esentutl /r edb /d

    Extensible Storage Engine Utilities for Microsoft(R) Windows(R)
    Version 10.0
    Copyright (C) Microsoft Corporation. All Rights Reserved.

    Initiating RECOVERY mode…
    Logfile base name: edb
    Log files:
    System files:
    Database Directory:

    Performing soft recovery…

    Recovery has indicated that there might be a lossy recovery option. Run recovery with the /a argument.

    Operation terminated with error -528 (JET_errMissingLogFile, Current log file missing) after 0.78 seconds.

    Same error here, Ntds.dit from WS2k12. Recovery with a Option is not working as well.

  27. Peter says:

    PS C:\Tools\DSInternals_v2.22\DSInternals> Get-ADDBAccount -All -DBPath C:\Tools\ntds.dit\ntds.dit -BootKey $key
    Get-ADDBAccount : The database is not in a clean state. Try to recover it first by running the ‘esentutl /r edb /d’
    command. In Zeile:1 Zeichen:1
    + Get-ADDBAccount -All -DBPath C:\Tools\ntds.dit\ntds.dit -BootKey $key
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : OpenError: (:) [Get-ADDBAccount], InvalidDatabaseStateException
    + FullyQualifiedErrorId : DBContextError,DSInternals.PowerShell.Commands.GetADDBAccountCommand

    PS C:\Tools\DSInternals_v2.22\DSInternals> esentutl /r edb /d

    Extensible Storage Engine Utilities for Microsoft(R) Windows(R)
    Version 10.0
    Copyright (C) Microsoft Corporation. All Rights Reserved.

    Initiating RECOVERY mode…
    Logfile base name: edb
    Log files:
    System files:
    Database Directory:

    Performing soft recovery…

    Recovery has indicated that there might be a lossy recovery option. Run recovery with the /a argument.

    Operation terminated with error -528 (JET_errMissingLogFile, Current log file missing) after 0.78 seconds.

    Same error Here, repair with a Option is not working as well.

    • Michael Grafnetter says:

      Thanks, Peter, for reporting this. Have you tried the /a argument? Are copying the ntds.dit between different OS versions?

  28. x0dx0a says:

    I am receiving the same issue with loading the SYSTEM registry key

    Get-BootKey : The configuration registry database is corrupt

    Windows Server 2012r2 I used the method of extracting the SYSTEM key using vssadmin and then copying into a folder of which i have full access rights to. I also have full admin rights on said windows server.

    • Michael Grafnetter says:

      Thanks for reporting this. Are you at least able to mount the registry hive using regedit?

  29. Jim says:

    When I attempt to run this, I receive the following error:

    PS C:\users\xxxxxxxx\desktop\DSInternals> $hashes = Get-ADDBAccount -All -DBPath ‘c:\adaudit\active directory\ntds.di
    t’ -BootKey $key
    Get-ADDBAccount : An item with the same key has already been added.
    At line:1 char:11
    + $hashes = Get-ADDBAccount -All -DBPath ‘c:\adaudit\active directory\ntds.dit’ -B …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : OpenError: (:) [Get-ADDBAccount], ArgumentException
    + FullyQualifiedErrorId : DBContextError,DSInternals.PowerShell.Commands.GetADDBAccountCommand

    Any idea why this would be?

    • Michael Grafnetter says:

      Could you please file a bug at GitHub and provide the stack trace of this exception? Thanks.

  30. Bruce Thomson says:

    This works great. I copied ntds.dit and SYSTEM by using the recovery console at boot. I had to put ntds.dit in a folder because putting it at the filesystem root doesn’t work.

  31. CAshtones says:

    Hello Michael, great module and blog thanks for posting. I have a couple of questions please I have read several blogs which say the users password hash is not salted and during tests if I have two users with the same password, when looking at the dump using your utility I can see their NTHASH are indeed the same, so no salt I thought a users password hash was stored in AD database using the MD4 algorithm but I do not see MD4 in the output. Are the password stored as an MD4 hash and if so what can I not see them please?

    Also
    under the Credential section of the output then user the Kerberos and KerberosNew subsections I see mention of a Salt. Can you please tell me does this ‘salt’ refer to the Kerberos Key and Cypher e.g. Kerberos:
    Credentials:
    DES_CBC_MD5
    Key: cddf7308d6cd5d2a
    OldCredentials:
    DES_CBC_MD5
    Key: cddf7308d6cd5d2a
    Salt: ADATUM.COMkrbtgt
    Flags: 0 if so what is the above used for? is it to encrypt the TGT (but the key would be the hash of KRBTGT) or is it the ‘session’ key exchanged with the client when he/she/it obtains a TGT or TST

    Any clarification on the above would be most welcome

    Thank yoy

    • Michael Grafnetter says:

      NT Hash == NTLM Hash == NT One way function == MD4 hash
      Salts are only used for Kerberos DES/AES key derivation functions.

  32. Adam L says:

    Am also getting the “database is not in a clean state.” error message when attempting to read the ntds.dit file using Get-ADDBAccount with the bootkey.

    This seems to be a common occurrence in this thread. Does anyone have a solution so far?

    Running esentutl didn’t seem to achieve much.

    • Michael Grafnetter says:

      Hi Adam, do you also have the corresponding transaction logs (basically everything from the NTDS folder except *.jrs)? They are required by esentutl to repair the DB (esentutl /r edb /d). As an alternative, you might try to defragment the DB (esentutl /d ntds.dit), which has a slightly higher success rate at the cost of potentially loosing some data.

  33. michael says:

    Maybe I am missing something basic… I have captured the live key and copied off the ntds.dit to a local folder. After setting the key manually, and running Get-ADDBAccount, the command finishes without error, but I have no output.

    PS C:\Users\michaell\desktop> $key
    b05ac38ac303ab3f6f91d74d06448da8

    PS C:\Users\michaell\desktop> Get-ADDBAccount -All -DBPath ‘.\ntds.dit’ -BootKey $key
    PS C:\Users\michaell\desktop>

  34. Ganesh says:

    Hello Michael, this is an awesome tool & i truly appreciate all the efforts put in to get this details. Its really helped to find how many account we have Lm hash value. I have one question . is there any was we can clean the LMhash value for for identified users those who have it? can you you help me how we can do that. There are many disabled user have this value & we don’t delete the disabled users.

  35. John Bryant says:

    I receive this error when trying to repair the offline NTDS database. “Operation terminated with error -2102 (JET_errCallbackNotResolved, A callback function could not be found)” after 9.78 seconds. Error triggers after the “Checking the database” section. Tried running on W2k12 r2 domain controller and W2k12 member server. Export was from W2k server. All fixes I’ve seen online seem to relate to Exchange db repairs.

    • Michael Grafnetter says:

      Hi John, the DB is referencing a callback function (sort of a stored procedure/trigger in more conventional DBs) that is implemented in a DLL specific to the OS from which that DB file originates (typically ntdsa.dll, part of AD DS/LDS optional components). When DSInternals 3.0 opens such databases, it tells the DB engine to ignore any such callbacks. Unfortunately, built-in Windows tools do not have this feature. This is a known issue with WS2016 AD DBs. But W2K??? Really??? As you cannot run PS on W2K, the only viable solution to this issue would probably be to implement defragmentation/repair directly in DSInternals. And I am not there yet, sorry.

Leave a Reply

Your email address will not be published.