Skip to content

Commit

Permalink
Add flag to allow referring to users by RDN
Browse files Browse the repository at this point in the history
  • Loading branch information
ph1ll committed Jan 10, 2024
1 parent dbb47ac commit 5e41ea6
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 11 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@ Options:
--wordlist The path to a wordlist of weak passwords for basic hash cracking. Warning, using this option is slow, the use of a dedicated password cracker, such as 'john', is recommended instead.
--ou-filter-file <file> The path to file containing a line separated list of OUs to which to limit user and computer results.
--base-date <yyyyMMdd> Specifies a custom date to be used as the base date in statistics. The last modified date of the NTDS file is used by default.
--useRdn Refer to users via name attribute (RDN) rather than samAccountName attribute in outputs.
--debug Show debug output.
WARNING: Use of the --pwdump option will result in decryption of password hashes using the System Key.
Sensitive information will be stored in memory and on disk. Ensure the pwdump file is handled appropriately
Sensitive information will be stored in memory and on disk. Ensure the pwdump file is handled appropriately.
```

For example, the following command will display statistics, output a file `pwdump.txt` containing password hashes, and output a file `users.csv` containing details for each user account.
Expand Down
17 changes: 9 additions & 8 deletions src/NtdsAudit/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ private static void Main(string[] args)
var wordlistPath = commandLineApplication.Option("--wordlist", "The path to a wordlist of weak passwords for basic hash cracking. Warning, using this option is slow, the use of a dedicated password cracker, such as 'john', is recommended instead.", CommandOptionType.SingleValue);
var ouFilterFilePath = commandLineApplication.Option("--ou-filter-file <file>", "The path to file containing a line separated list of OUs to which to limit user and computer results.", CommandOptionType.SingleValue);
var baseDate = commandLineApplication.Option("--base-date <yyyyMMdd>", "Specifies a custom date to be used as the base date in statistics. The last modified date of the NTDS file is used by default.", CommandOptionType.SingleValue);
var useRdn = commandLineApplication.Option("--useRdn", "Refer to users via name attribute (RDN) rather than samAccountName attribute in outputs.", CommandOptionType.NoValue);
var debug = commandLineApplication.Option("--debug", "Show debug output.", CommandOptionType.NoValue);

commandLineApplication.OnExecute(() =>
Expand Down Expand Up @@ -138,12 +139,12 @@ private static void Main(string[] args)

if (pwdumpPath.HasValue())
{
WritePwDumpFile(pwdumpPath.Value(), ntdsAudit, baseDateTime, includeHistoryHashes.HasValue(), wordlistPath.HasValue(), dumpReversiblePath.Value());
WritePwDumpFile(pwdumpPath.Value(), ntdsAudit, baseDateTime, includeHistoryHashes.HasValue(), wordlistPath.HasValue(), dumpReversiblePath.Value(), useRdn.HasValue());
}

if (usersCsvPath.HasValue())
{
WriteUsersCsvFile(usersCsvPath.Value(), ntdsAudit, baseDateTime);
WriteUsersCsvFile(usersCsvPath.Value(), ntdsAudit, baseDateTime, useRdn.HasValue());
}

if (computersCsvPath.HasValue())
Expand Down Expand Up @@ -235,7 +236,7 @@ private static void WriteComputersCsvFile(string computersCsvPath, NtdsAudit ntd
}
}

private static void WritePwDumpFile(string pwdumpPath, NtdsAudit ntdsAudit, DateTime baseDateTime, bool includeHistoryHashes, bool wordlistInUse, string dumpReversiblePath)
private static void WritePwDumpFile(string pwdumpPath, NtdsAudit ntdsAudit, DateTime baseDateTime, bool includeHistoryHashes, bool wordlistInUse, string dumpReversiblePath, bool useRdn)
{
DomainInfo domain = null;

Expand Down Expand Up @@ -297,7 +298,7 @@ private static void WritePwDumpFile(string pwdumpPath, NtdsAudit ntdsAudit, Date
$"IsDomainAdmin={users[i].RecursiveGroupSids.Contains(domain.DomainAdminsSid)}," +
$"IsEnterpriseAdmin={users[i].RecursiveGroupSids.Intersect(ntdsAudit.Domains.Select(x => x.EnterpriseAdminsSid)).Any()}";
var homeDir = string.Empty;
file.Write($"{domain.Fqdn}\\{users[i].SamAccountName}:{users[i].Rid}:{users[i].LmHash}:{users[i].NtHash}:{comments}:{homeDir}:");
file.Write($"{domain.Fqdn}\\{(useRdn ? users[i].Name : users[i].SamAccountName)}:{users[i].Rid}:{users[i].LmHash}:{users[i].NtHash}:{comments}:{homeDir}:");

if (includeHistoryHashes && users[i].NtHistory != null && users[i].NtHistory.Length > 0)
{
Expand All @@ -313,7 +314,7 @@ private static void WritePwDumpFile(string pwdumpPath, NtdsAudit ntdsAudit, Date
for (var j = 0; j < users[i].NtHistory.Length; j++)
{
var lmHash = (users[i].LmHistory?.Length > j) ? users[i].LmHistory[j] : NtdsAudit.EMPTY_LM_HASH;
file.Write($"{domain.Fqdn}\\{users[i].SamAccountName}__history_{j}:{users[i].Rid}:{lmHash}:{users[i].NtHistory[j]}:::");
file.Write($"{domain.Fqdn}\\{(useRdn ? users[i].Name : users[i].SamAccountName)}__history_{j}:{users[i].Rid}:{lmHash}:{users[i].NtHistory[j]}:::");

if (j < users[i].NtHistory.Length || i < users.Length - 1)
{
Expand All @@ -332,7 +333,7 @@ private static void WritePwDumpFile(string pwdumpPath, NtdsAudit ntdsAudit, Date
{
if (!string.IsNullOrEmpty(users[i].ClearTextPassword))
{
file.Write($"{domain.Fqdn}\\{users[i].SamAccountName}:{users[i].ClearTextPassword}");
file.Write($"{domain.Fqdn}\\{(useRdn ? users[i].Name : users[i].SamAccountName)}:{users[i].ClearTextPassword}");

if (i < users.Length - 1)
{
Expand All @@ -352,15 +353,15 @@ private static void WriteStatistic(string statistic, int actual, int maximum)
Console.Write(Environment.NewLine);
}

private static void WriteUsersCsvFile(string usersCsvPath, NtdsAudit ntdsAudit, DateTime baseDateTime)
private static void WriteUsersCsvFile(string usersCsvPath, NtdsAudit ntdsAudit, DateTime baseDateTime, bool useRdn)
{
using (var file = new StreamWriter(usersCsvPath, false))
{
file.WriteLine("Domain,Username,Administrator,Domain Admin,Enterprise Admin,Disabled,Expired,Password Never Expires,Password Not Required,Password Last Changed,Last Logon,DN");
foreach (var user in ntdsAudit.Users)
{
var domain = ntdsAudit.Domains.Single(x => x.Sid == user.DomainSid);
file.WriteLine($"{domain.Fqdn},{user.SamAccountName},{user.RecursiveGroupSids.Contains(domain.AdministratorsSid)},{user.RecursiveGroupSids.Contains(domain.DomainAdminsSid)},{user.RecursiveGroupSids.Intersect(ntdsAudit.Domains.Select(x => x.EnterpriseAdminsSid)).Any()},{user.Disabled},{!user.Disabled && user.Expires.HasValue && user.Expires.Value < baseDateTime},{user.PasswordNeverExpires},{user.PasswordNotRequired},{user.PasswordLastChanged},{user.LastLogon},\"{user.Dn}\"");
file.WriteLine($"{domain.Fqdn},{(useRdn ? user.Name : user.SamAccountName)},{user.RecursiveGroupSids.Contains(domain.AdministratorsSid)},{user.RecursiveGroupSids.Contains(domain.DomainAdminsSid)},{user.RecursiveGroupSids.Intersect(ntdsAudit.Domains.Select(x => x.EnterpriseAdminsSid)).Any()},{user.Disabled},{!user.Disabled && user.Expires.HasValue && user.Expires.Value < baseDateTime},{user.PasswordNeverExpires},{user.PasswordNotRequired},{user.PasswordLastChanged},{user.LastLogon},\"{user.Dn}\"");
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/NtdsAudit/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.0.8.0")]
[assembly: AssemblyFileVersion("2.0.8.0")]
[assembly: AssemblyVersion("2.0.9.0")]
[assembly: AssemblyFileVersion("2.0.9.0")]
[assembly: CLSCompliant(true)]

0 comments on commit 5e41ea6

Please sign in to comment.