Monday, March 11, 2013

Extracting LM/NTLM password hashes from a 2003 Domain controller using ntbackup

Extracting LM/NTLM password hashes from a 2003 Domain controller using ntbackup

Take System state backup and restore ntds.dit and system reg key

Log onto Domain controller using a domain admin account and follow this method published by quarkspwdump ( )

1. Launch NTBACKUP gui
2. Use backup wizard (advanced)
3. Choose to save system state only and choose output filename
4. Wait some minutes
5. Use restore wizard (advanced)
6. Choose your backup, click next and use advanced button
7. Choose to restore file on another location (c:\tmp\ for example)
8. Choose to overwrite everything and next uncheck all restoration parameters
9. Validate and wait some minutes
10. Open a command shell to "c:\tmp\Active Directory"
11. We need to repair the database with this command " esentutl /p ntds.dit "
12. Validate warning and wait some minutes
Now copy the restored ntds.dit and system from "c:\tmp\Active Directory" folder into a 
new folder on a Backtrack machine.

How to extract password hashes from ntds.dit file and system reg key.

The next part you need to copy the ntds.dit and system reg key from the ntbackup restore into a folder on a backtrack machine. I haven choosen to create an ntds folder in the home directory and have copied the system reg key into (see text is green) and have also created a sub folder in this directory called "Active Directory" that has the ntds.dit file. (see below)



Next follow the guide published on "" to extract the ntlm hashes using ntdsxtract.

1. Stay in the ntds directory and download and install libesedb

tar xvzf libesedb-alpha-20120102.tar.gz
cd libesedb-20120102 
chmod +x configure
./configure && make

2. Create directory in ntds called ntdsxtract and download and extract ntdsxtract

mkdir ntdsxtract
cd ntdsxtract_v1_0
chmod +x *.py

3. Use esedbexport to extract the relevant tables from ntds.dit, esedbtools is a subdirectory in the libesedb folder

cd esedbtools
./esedbexport ../../Active\ Directory/ntds.dit

4. Use to extract the hashes from the datatable. To put the hashes in a pentester friendly format download from or copy from below

cd ../../NTDSXtract/
chmod +x *.py
python ./ ../datatable ../link_table --passwordhashes ../system > domainhashes.txt

To make it more difficult for password cracking tools to crack ntlm password hashes then stop windows from using LMhash passwords. Follow this article script

# This file was derived from, which is is part of ntdsxtract.
# ntdsxtract is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# ntdsxtract is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with ntdsxtract.  If not, see .

@editor:        LaNMaSteR53
@author:        Csaba Barta
@license:       GNU General Public License 2.0 or later

from ntds.dsdatabase import *
from ntds.dsrecord import *
from ntds.dslink import *
from ntds.dstime import *
from ntds.dsobjects import *

def usage():
    print "DSHashes"
    print "Extracts user hashes in a user-friendly format\n"
    print "usage: %s   [option]" % sys.argv[0]
    print "  options:"
    print "    --rid "
    print "          List user identified by RID"
    print "    --name "
    print "          List user identified by Name"
    print "    --passwordhashes "
    print "          Extract password hashes"
    print "    --passwordhistory "
    print "          Extract password history"
    print "    --exclude-disabled"
    print "          Exclude disabled accounts from output"

if len(sys.argv) < 3:

rid = -1
name = ""
syshive = ""
pwdump = False
pwhdump = False
optid = 0
excl_dsbl = False
print "Running with options:"
for opt in sys.argv:
    if opt == "--rid":
        if len(sys.argv) < 5:
        rid = int(sys.argv[optid + 1])
        print "\tUser RID: %d" % rid
    if opt == "--name":
        if len(sys.argv) < 5:
        name = sys.argv[optid + 1]
        print "\tUser name: %s" % name
    if opt == "--passwordhashes":
        if len(sys.argv) < 5:
        syshive = sys.argv[optid + 1]
        pwdump = True
        print "\tExtracting password hashes"
    if opt == "--passwordhistory":
        if len(sys.argv) < 5:
        syshive = sys.argv[optid + 1]
        pwhdump = True
        print "\tExtracting password history"
    if '--exclude-disabled' in sys.argv:
        excl_dsbl = True
    optid += 1 

db = dsInitDatabase(sys.argv[1])
dl = dsInitLinks(sys.argv[2])

if pwdump or pwhdump:

utype = -1
utype = dsGetTypeIdByTypeName(db, "Person")
if utype == -1:
    print "Unable to get type id for Person"

print "\nList of hashes:"
print "=============="
for recordid in dsMapLineIdByRecordId:
    if int(dsGetRecordType(db, recordid)) == utype:
        user = dsUser(db, recordid)
        if rid != -1 and user.SID.RID != rid:
        if name != "" and user.Name != name:
        if excl_dsbl:
            user_disabled = False
            for uac in user.getUserAccountControl():
                if uac == 'Disabled': user_disabled = True
            if user_disabled: continue

        if pwdump == True:
            nthash = ''
            lmhash = 'aad3b435b51404eeaad3b435b51404ee'
            (lm, nt) = user.getPasswordHashes()
            if nt != '':
                nthash = nt
                if lm != '':
                    lmhash = lm
            hash = "%s:%s:%s:%s:::" % (user.SAMAccountName, user.SID.RID, lmhash, nthash)
            if nt != '':
                print hash

        if pwhdump == True:
            lmhistory = None
            nthistory = None
            (lmhistory, nthistory) = user.getPasswordHistory()
            if nthistory != None:
                hashid = 0
                for nthash in nthistory:
                    print "%s_nthistory%d:%s:E52CAC67419A9A224A3B108F3FA6CB6D:%s:::" % (user.SAMAccountName, hashid, user.SID.RID, nthash)
                    hashid += 1
                if lmhistory != None:
                    hashid = 0
                    for lmhash in lmhistory:
                        print "%s_lmhistory%d:%s:%s:8846F7EAEE8FB117AD06BDD830B7586C:::" % (user.SAMAccountName, hashid, user.SID.RID, lmhash)
                        hashid += 1

if pwhdump == True:
  print "\n[*] NOTE: NT and LM hashes are shown on individual lines with the respective hash of 'password' in the opposing position."
  print "This is done in order to make sure the output plays nice with various hash cracking tools. Account for this when cracking historical hashes.\n"

1 comment:

  1. IMO you need to give some credit to the author of NTDSXtract, Csaba Barta. Your post is informative but it is Mr. Barta who has done the heavy lifting...