Generated from Manticore v1.1.6 • 388 packages. View on pkg.go.dev

ntds

import "github.com/TheManticoreProject/Manticore/windows/database/ntds"

Package ntds implements the secret-decryption primitives for offline NTDS.dit (Active Directory database) analysis: decrypting the Password Encryption Key (PEK) list with a SYSTEM boot key, and decrypting the per-account hash blobs stored in NTDS attributes (unicodePwd, dBCSPwd, ntPwdHistory, lmPwdHistory, …).

The decryption matches the reference behaviour of impacket’s secretsdump (NTDSHashes): a PEK-keyed outer layer (RC4 or AES depending on the format version) followed by the RID-keyed DES layer of [MS-SAMR] 2.2.11.1. It is independent of how the encrypted bytes are obtained — an offline ESE reader or a remote DRSUAPI reply can both feed these functions.

References:

  • [MS-SAMR] 2.2.11.1 Encrypting/Decrypting an NT or LM Hash Value
  • impacket secretsdump.py NTDSHashes (__removeRC4Layer / __removeDESLayer, PEKLIST_*)

Index

Constants

NTDS datatable column names. In NTDS.dit each attribute is an ESE column named “ATT<type><id>”; these are the columns needed to recover account secrets.

const (
    AttSAMAccountName          = "ATTm590045"
    AttSAMAccountType          = "ATTj590126"
    AttObjectSid               = "ATTr589970"
    AttUserAccountControl      = "ATTj589832"
    AttUnicodePwd              = "ATTk589914" // NT hash
    AttDBCSPwd                 = "ATTk589879" // LM hash
    AttNTPwdHistory            = "ATTk589918"
    AttLMPwdHistory            = "ATTk589984"
    AttPEKList                 = "ATTk590689"
    AttUserPrincipalName       = "ATTm590480"
    AttSupplementalCredentials = "ATTk589949"
)

func DecryptHash

func DecryptHash(peks []PEK, rid uint32, encrypted []byte) ([]byte, error)

DecryptHash decrypts a single-hash attribute blob (e.g. unicodePwd / dBCSPwd) using the PEK list and the account’s RID, returning the raw 16-byte NT or LM hash. The PEK index is taken from the blob header.

func DecryptHashHistory

func DecryptHashHistory(peks []PEK, rid uint32, encrypted []byte) ([][]byte, error)

DecryptHashHistory decrypts a hash-history attribute blob (ntPwdHistory / lmPwdHistory) using the PEK list and the account’s RID, returning the sequence of raw 16-byte hashes (most recent first, as stored).

func Dump

func Dump(db *ese.Database, bootKey []byte, fn func(Account) error) error

Dump iterates the datatable of an opened NTDS database, decrypts each user account’s secrets with the PEK list (recovered from bootKey), and invokes fn for every account that has a sAMAccountName and objectSid. bootKey is the 16-byte SYSTEM boot key (the caller derives it).

type Account

Account is one decrypted NTDS account.

type Account struct {
    SAMAccountName     string
    RID                uint32
    LMHash             []byte // 16 bytes
    NTHash             []byte // 16 bytes
    LMHistory          [][]byte
    NTHistory          [][]byte
    UserAccountControl uint32
    HasUAC             bool
}

func (*Account) Disabled

func (a *Account) Disabled() bool

Disabled reports whether the account’s userAccountControl marks it disabled.

func (*Account) HistoryLines

func (a *Account) HistoryLines() []string

HistoryLines formats the account’s password-history entries as secretsdump “user_historyN:rid:lm:nt:::” lines, skipping the current password (index 0).

func (*Account) SecretsdumpLine

func (a *Account) SecretsdumpLine() string

SecretsdumpLine formats the account as the secretsdump line “user:rid:lm:nt:::”.

type PEK

PEK is a 16-byte Password Encryption Key recovered from the pekList attribute.

type PEK []byte

func DecryptPEKList

func DecryptPEKList(bootKey, pekList []byte) ([]PEK, error)

DecryptPEKList decrypts the pekList attribute with the SYSTEM boot key and returns the contained PEKs (usually one). Both on-disk formats are supported, selected by the first header byte:

  • 0x02 (up to Windows Server 2012 R2): RC4 keyed by MD5(bootKey + keyMaterial*1000).
  • 0x03 (Windows Server 2016+): AES-CBC keyed by bootKey, IV = keyMaterial.

bootKey is the 16-byte boot key derived from the SYSTEM hive (the caller supplies it; boot-key derivation is out of scope here).

func FindPEKList

func FindPEKList(table *ese.Table, bootKey []byte) ([]PEK, error)

FindPEKList scans the datatable for the pekList attribute and decrypts it with bootKey.