Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <#
- .SYNOPSIS
- ADRecon is a tool which gathers information about the Active Directory and generates a report which can provide a holistic picture of the current state of the target AD environment.
- .DESCRIPTION
- ADRecon is a tool which extracts and combines various artefacts (as highlighted below) out of an AD environment. The information can be presented in a specially formatted Microsoft Excel report that includes summary views with metrics to facilitate analysis and provide a holistic picture of the current state of the target AD environment.
- The tool is useful to various classes of security professionals like auditors, DFIR, students, administrators, etc. It can also be an invaluable post-exploitation tool for a penetration tester.
- It can be run from any workstation that is connected to the environment, even hosts that are not domain members. Furthermore, the tool can be executed in the context of a non-privileged (i.e. standard domain user) account.
- Fine Grained Password Policy, LAPS and BitLocker may require Privileged user accounts.
- The tool will use Microsoft Remote Server Administration Tools (RSAT) if available, otherwise it will communicate with the Domain Controller using LDAP.
- The following information is gathered by the tool:
- - Forest;
- - Domain;
- - Trusts;
- - Sites;
- - Subnets;
- - Default and Fine Grained Password Policy (if implemented);
- - Domain Controllers, SMB versions, whether SMB Signing is supported and FSMO roles;
- - Users and their attributes;
- - Service Principal Names (SPNs);
- - Groups and memberships;
- - Organizational Units (OUs);
- - Group Policy Object and gPLink details;
- - DNS Zones and Records;
- - Printers;
- - Computers and their attributes;
- - PasswordAttributes (Experimental);
- - LAPS passwords (if implemented);
- - BitLocker Recovery Keys (if implemented);
- - ACLs (DACLs and SACLs) for the Domain, OUs, Root Containers, GPO, Users, Computers and Groups objects;
- - GPOReport (requires RSAT);
- - Kerberoast (not included in the default collection method); and
- - Domain accounts used for service accounts (requires privileged account and not included in the default collection method).
- Author : Prashant Mahajan
- Company : https://www.senseofsecurity.com.au
- .NOTES
- The following commands can be used to turn off ExecutionPolicy: (Requires Admin Privs)
- PS > $ExecPolicy = Get-ExecutionPolicy
- PS > Set-ExecutionPolicy bypass
- PS > .\ADRecon.ps1
- PS > Set-ExecutionPolicy $ExecPolicy
- OR
- Start the PowerShell as follows:
- powershell.exe -ep bypass
- OR
- Already have a PowerShell open ?
- PS > $Env:PSExecutionPolicyPreference = 'Bypass'
- OR
- powershell.exe -nologo -executionpolicy bypass -noprofile -file ADRecon.ps1
- .PARAMETER Protocol
- Which protocol to use; ADWS (default) or LDAP
- .PARAMETER DomainController
- Domain Controller IP Address or Domain FQDN.
- .PARAMETER Credential
- Domain Credentials.
- .PARAMETER GenExcel
- Path for ADRecon output folder containing the CSV files to generate the ADRecon-Report.xlsx. Use it to generate the ADRecon-Report.xlsx when Microsoft Excel is not installed on the host used to run ADRecon.
- .PARAMETER OutputDir
- Path for ADRecon output folder to save the files and the ADRecon-Report.xlsx. (The folder specified will be created if it doesn't exist)
- .PARAMETER Collect
- Which modules to run; Comma separated; e.g Forest,Domain (Default all except Kerberoast, DomainAccountsusedforServiceLogon)
- Valid values include: Forest, Domain, Trusts, Sites, Subnets, PasswordPolicy, FineGrainedPasswordPolicy, DomainControllers, Users, UserSPNs, PasswordAttributes, Groups, GroupMembers, OUs, GPOs, gPLinks, DNSZones, Printers, Computers, ComputerSPNs, LAPS, BitLocker, ACLs, GPOReport, Kerberoast, DomainAccountsusedforServiceLogon.
- .PARAMETER OutputType
- Output Type; Comma seperated; e.g STDOUT,CSV,XML,JSON,HTML,Excel (Default STDOUT with -Collect parameter, else CSV and Excel).
- Valid values include: STDOUT, CSV, XML, JSON, HTML, Excel, All (excludes STDOUT).
- .PARAMETER DormantTimeSpan
- Timespan for Dormant accounts. (Default 90 days)
- .PARAMETER PassMaxAge
- Maximum machine account password age. (Default 30 days)
- .PARAMETER PageSize
- The PageSize to set for the LDAP searcher object.
- .PARAMETER Threads
- The number of threads to use during processing objects. (Default 10)
- .PARAMETER Log
- Create ADRecon Log using Start-Transcript
- .EXAMPLE
- .\ADRecon.ps1 -GenExcel C:\ADRecon-Report-<timestamp>
- [*] ADRecon <version> by Prashant Mahajan (@prashant3535) from Sense of Security.
- [*] Generating ADRecon-Report.xlsx
- [+] Excelsheet Saved to: C:\ADRecon-Report-<timestamp>\<domain>-ADRecon-Report.xlsx
- .EXAMPLE
- .\ADRecon.ps1 -DomainController <IP or FQDN> -Credential <domain\username>
- [*] ADRecon <version> by Prashant Mahajan (@prashant3535) from Sense of Security.
- [*] Running on <domain>\<hostname> - Member Workstation
- <snip>
- Example output from Domain Member with Alternate Credentials.
- .EXAMPLE
- .\ADRecon.ps1 -DomainController <IP or FQDN> -Credential <domain\username> -Collect DomainControllers -OutputType Excel
- [*] ADRecon <version> by Prashant Mahajan (@prashant3535) from Sense of Security.
- [*] Running on WORKGROUP\<hostname> - Standalone Workstation
- [*] Commencing - <timestamp>
- [-] Domain Controllers
- [*] Total Execution Time (mins): <minutes>
- [*] Generating ADRecon-Report.xlsx
- [+] Excelsheet Saved to: C:\ADRecon-Report-<timestamp>\<domain>-ADRecon-Report.xlsx
- [*] Completed.
- [*] Output Directory: C:\ADRecon-Report-<timestamp>
- Example output from from a Non-Member using RSAT to only enumerate Domain Controllers.
- .EXAMPLE
- .\ADRecon.ps1 -Protocol ADWS -DomainController <IP or FQDN> -Credential <domain\username>
- [*] ADRecon <version> by Prashant Mahajan (@prashant3535) from Sense of Security.
- [*] Running on WORKGROUP\<hostname> - Standalone Workstation
- [*] Commencing - <timestamp>
- [-] Domain
- [-] Forest
- [-] Trusts
- [-] Sites
- [-] Subnets
- [-] Default Password Policy
- [-] Fine Grained Password Policy - May need a Privileged Account
- [-] Domain Controllers
- [-] Users - May take some time
- [-] User SPNs
- [-] PasswordAttributes - Experimental
- [-] Groups - May take some time
- [-] Group Memberships - May take some time
- [-] OrganizationalUnits (OUs)
- [-] GPOs
- [-] gPLinks - Scope of Management (SOM)
- [-] DNS Zones and Records
- [-] Printers
- [-] Computers - May take some time
- [-] Computer SPNs
- [-] LAPS - Needs Privileged Account
- WARNING: [*] LAPS is not implemented.
- [-] BitLocker Recovery Keys - Needs Privileged Account
- [-] ACLs - May take some time
- WARNING: [*] SACLs - Currently, the module is only supported with LDAP.
- [-] GPOReport - May take some time
- WARNING: [EXCEPTION] Current security context is not associated with an Active Directory domain or forest.
- WARNING: [*] Run the tool using RUNAS.
- WARNING: [*] runas /user:<Domain FQDN>\<Username> /netonly powershell.exe
- [*] Total Execution Time (mins): <minutes>
- [*] Output Directory: C:\ADRecon-Report-<timestamp>
- [*] Generating ADRecon-Report.xlsx
- [+] Excelsheet Saved to: C:\ADRecon-Report-<timestamp>\<domain>-ADRecon-Report.xlsx
- Example output from a Non-Member using RSAT.
- .EXAMPLE
- .\ADRecon.ps1 -Protocol LDAP -DomainController <IP or FQDN> -Credential <domain\username>
- [*] ADRecon <version> by Prashant Mahajan (@prashant3535) from Sense of Security.
- [*] Running on WORKGROUP\<hostname> - Standalone Workstation
- [*] LDAP bind Successful
- [*] Commencing - <timestamp>
- [-] Domain
- [-] Forest
- [-] Trusts
- [-] Sites
- [-] Subnets
- [-] Default Password Policy
- [-] Fine Grained Password Policy - May need a Privileged Account
- [-] Domain Controllers
- [-] Users - May take some time
- [-] User SPNs
- [-] PasswordAttributes - Experimental
- [-] Groups - May take some time
- [-] Group Memberships - May take some time
- [-] OrganizationalUnits (OUs)
- [-] GPOs
- [-] gPLinks - Scope of Management (SOM)
- [-] DNS Zones and Records
- [-] Printers
- [-] Computers - May take some time
- [-] Computer SPNs
- [-] LAPS - Needs Privileged Account
- WARNING: [*] LAPS is not implemented.
- [-] BitLocker Recovery Keys - Needs Privileged Account
- [-] ACLs - May take some time
- [-] GPOReport - May take some time
- WARNING: [*] Currently, the module is only supported with ADWS.
- [*] Total Execution Time (mins): <minutes>
- [*] Output Directory: C:\ADRecon-Report-<timestamp>
- [*] Generating ADRecon-Report.xlsx
- [+] Excelsheet Saved to: C:\ADRecon-Report-<timestamp>\<domain>-ADRecon-Report.xlsx
- Example output from a Non-Member using LDAP.
- .LINK
- https://github.com/sense-of-security/ADRecon
- #>
- [CmdletBinding()]
- param
- (
- [Parameter(Mandatory = $false, HelpMessage = "Which protocol to use; ADWS (default) or LDAP.")]
- [ValidateSet('ADWS', 'LDAP')]
- [string] $Protocol = 'ADWS',
- [Parameter(Mandatory = $false, HelpMessage = "Domain Controller IP Address or Domain FQDN.")]
- [string] $DomainController = '',
- [Parameter(Mandatory = $false, HelpMessage = "Domain Credentials.")]
- [Management.Automation.PSCredential] $Credential = [Management.Automation.PSCredential]::Empty,
- [Parameter(Mandatory = $false, HelpMessage = "Path for ADRecon output folder containing the CSV files to generate the ADRecon-Report.xlsx. Use it to generate the ADRecon-Report.xlsx when Microsoft Excel is not installed on the host used to run ADRecon.")]
- [string] $GenExcel,
- [Parameter(Mandatory = $false, HelpMessage = "Path for ADRecon output folder to save the CSV/XML/JSON/HTML files and the ADRecon-Report.xlsx. (The folder specified will be created if it doesn't exist)")]
- [string] $OutputDir,
- [Parameter(Mandatory = $false, HelpMessage = "Which modules to run; Comma separated; e.g Forest,Domain (Default all except Kerberoast, DomainAccountsusedforServiceLogon) Valid values include: Forest, Domain, Trusts, Sites, Subnets, PasswordPolicy, FineGrainedPasswordPolicy, DomainControllers, Users, UserSPNs, PasswordAttributes, Groups, GroupMembers, OUs, GPOs, gPLinks, DNSZones, Printers, Computers, ComputerSPNs, LAPS, BitLocker, ACLs, GPOReport, Kerberoast, DomainAccountsusedforServiceLogon")]
- [ValidateSet('Forest', 'Domain', 'Trusts', 'Sites', 'Subnets', 'PasswordPolicy', 'FineGrainedPasswordPolicy', 'DomainControllers', 'Users', 'UserSPNs', 'PasswordAttributes', 'Groups', 'GroupMembers', 'OUs', 'GPOs', 'gPLinks', 'DNSZones', 'Printers', 'Computers', 'ComputerSPNs', 'LAPS', 'BitLocker', 'ACLs', 'GPOReport', 'Kerberoast', 'DomainAccountsusedforServiceLogon', 'Default')]
- [array] $Collect = 'Default',
- [Parameter(Mandatory = $false, HelpMessage = "Output type; Comma seperated; e.g STDOUT,CSV,XML,JSON,HTML,Excel (Default STDOUT with -Collect parameter, else CSV and Excel)")]
- [ValidateSet('STDOUT', 'CSV', 'XML', 'JSON', 'EXCEL', 'HTML', 'All', 'Default')]
- [array] $OutputType = 'Default',
- [Parameter(Mandatory = $false, HelpMessage = "Timespan for Dormant accounts. Default 90 days")]
- [ValidateRange(1,1000)]
- [int] $DormantTimeSpan = 90,
- [Parameter(Mandatory = $false, HelpMessage = "Maximum machine account password age. Default 30 days")]
- [ValidateRange(1,1000)]
- [int] $PassMaxAge = 30,
- [Parameter(Mandatory = $false, HelpMessage = "The PageSize to set for the LDAP searcher object. Default 200")]
- [ValidateRange(1,10000)]
- [int] $PageSize = 200,
- [Parameter(Mandatory = $false, HelpMessage = "The number of threads to use during processing of objects. Default 10")]
- [ValidateRange(1,100)]
- [int] $Threads = 10,
- [Parameter(Mandatory = $false, HelpMessage = "Create ADRecon Log using Start-Transcript")]
- [switch] $Log
- )
- $ADWSSource = @"
- // Thanks Dennis Albuquerque for the C# multithreading code
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading;
- using System.DirectoryServices;
- using System.Security.Principal;
- using System.Security.AccessControl;
- using System.Management.Automation;
- namespace ADRecon
- {
- public static class ADWSClass
- {
- private static DateTime Date1;
- private static int PassMaxAge;
- private static int DormantTimeSpan;
- private static Dictionary<String, String> AdGroupDictionary = new Dictionary<String, String>();
- private static String DomainSID;
- private static Dictionary<String, String> AdGPODictionary = new Dictionary<String, String>();
- private static Hashtable GUIDs = new Hashtable();
- private static Dictionary<String, String> AdSIDDictionary = new Dictionary<String, String>();
- private static readonly HashSet<string> Groups = new HashSet<string> ( new String[] {"268435456", "268435457", "536870912", "536870913"} );
- private static readonly HashSet<string> Users = new HashSet<string> ( new String[] { "805306368" } );
- private static readonly HashSet<string> Computers = new HashSet<string> ( new String[] { "805306369" }) ;
- private static readonly HashSet<string> TrustAccounts = new HashSet<string> ( new String[] { "805306370" } );
- [Flags]
- //Values taken from https://support.microsoft.com/en-au/kb/305144
- public enum UACFlags
- {
- SCRIPT = 1, // 0x1
- ACCOUNTDISABLE = 2, // 0x2
- HOMEDIR_REQUIRED = 8, // 0x8
- LOCKOUT = 16, // 0x10
- PASSWD_NOTREQD = 32, // 0x20
- PASSWD_CANT_CHANGE = 64, // 0x40
- ENCRYPTED_TEXT_PASSWORD_ALLOWED = 128, // 0x80
- TEMP_DUPLICATE_ACCOUNT = 256, // 0x100
- NORMAL_ACCOUNT = 512, // 0x200
- INTERDOMAIN_TRUST_ACCOUNT = 2048, // 0x800
- WORKSTATION_TRUST_ACCOUNT = 4096, // 0x1000
- SERVER_TRUST_ACCOUNT = 8192, // 0x2000
- DONT_EXPIRE_PASSWD = 65536, // 0x10000
- MNS_LOGON_ACCOUNT = 131072, // 0x20000
- SMARTCARD_REQUIRED = 262144, // 0x40000
- TRUSTED_FOR_DELEGATION = 524288, // 0x80000
- NOT_DELEGATED = 1048576, // 0x100000
- USE_DES_KEY_ONLY = 2097152, // 0x200000
- DONT_REQUIRE_PREAUTH = 4194304, // 0x400000
- PASSWORD_EXPIRED = 8388608, // 0x800000
- TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 16777216, // 0x1000000
- PARTIAL_SECRETS_ACCOUNT = 67108864 // 0x04000000
- }
- [Flags]
- //Values taken from https://blogs.msdn.microsoft.com/openspecification/2011/05/30/windows-configurations-for-kerberos-supported-encryption-type/
- public enum KerbEncFlags
- {
- ZERO = 0,
- DES_CBC_CRC = 1, // 0x1
- DES_CBC_MD5 = 2, // 0x2
- RC4_HMAC = 4, // 0x4
- AES128_CTS_HMAC_SHA1_96 = 8, // 0x18
- AES256_CTS_HMAC_SHA1_96 = 16 // 0x10
- }
- private static readonly Dictionary<String, String> Replacements = new Dictionary<String, String>()
- {
- //{System.Environment.NewLine, ""},
- //{",", ";"},
- {"\"", "'"}
- };
- public static String CleanString(Object StringtoClean)
- {
- // Remove extra spaces and new lines
- String CleanedString = String.Join(" ", ((Convert.ToString(StringtoClean)).Split((string[]) null, StringSplitOptions.RemoveEmptyEntries)));
- foreach (String Replacement in Replacements.Keys)
- {
- CleanedString = CleanedString.Replace(Replacement, Replacements[Replacement]);
- }
- return CleanedString;
- }
- public static int ObjectCount(Object[] ADRObject)
- {
- return ADRObject.Length;
- }
- public static Object[] UserParser(Object[] AdUsers, DateTime Date1, int DormantTimeSpan, int PassMaxAge, int numOfThreads)
- {
- ADWSClass.Date1 = Date1;
- ADWSClass.DormantTimeSpan = DormantTimeSpan;
- ADWSClass.PassMaxAge = PassMaxAge;
- Object[] ADRObj = runProcessor(AdUsers, numOfThreads, "Users");
- return ADRObj;
- }
- public static Object[] UserSPNParser(Object[] AdUsers, int numOfThreads)
- {
- Object[] ADRObj = runProcessor(AdUsers, numOfThreads, "UserSPNs");
- return ADRObj;
- }
- public static Object[] GroupParser(Object[] AdGroups, int numOfThreads)
- {
- Object[] ADRObj = runProcessor(AdGroups, numOfThreads, "Groups");
- return ADRObj;
- }
- public static Object[] GroupMemberParser(Object[] AdGroups, Object[] AdGroupMembers, String DomainSID, int numOfThreads)
- {
- ADWSClass.AdGroupDictionary = new Dictionary<String, String>();
- runProcessor(AdGroups, numOfThreads, "GroupsDictionary");
- ADWSClass.DomainSID = DomainSID;
- Object[] ADRObj = runProcessor(AdGroupMembers, numOfThreads, "GroupMembers");
- return ADRObj;
- }
- public static Object[] OUParser(Object[] AdOUs, int numOfThreads)
- {
- Object[] ADRObj = runProcessor(AdOUs, numOfThreads, "OUs");
- return ADRObj;
- }
- public static Object[] GPOParser(Object[] AdGPOs, int numOfThreads)
- {
- Object[] ADRObj = runProcessor(AdGPOs, numOfThreads, "GPOs");
- return ADRObj;
- }
- public static Object[] SOMParser(Object[] AdGPOs, Object[] AdSOMs, int numOfThreads)
- {
- ADWSClass.AdGPODictionary = new Dictionary<String, String>();
- runProcessor(AdGPOs, numOfThreads, "GPOsDictionary");
- Object[] ADRObj = runProcessor(AdSOMs, numOfThreads, "SOMs");
- return ADRObj;
- }
- public static Object[] PrinterParser(Object[] ADPrinters, int numOfThreads)
- {
- Object[] ADRObj = runProcessor(ADPrinters, numOfThreads, "Printers");
- return ADRObj;
- }
- public static Object[] ComputerParser(Object[] AdComputers, DateTime Date1, int DormantTimeSpan, int PassMaxAge, int numOfThreads)
- {
- ADWSClass.Date1 = Date1;
- ADWSClass.DormantTimeSpan = DormantTimeSpan;
- ADWSClass.PassMaxAge = PassMaxAge;
- Object[] ADRObj = runProcessor(AdComputers, numOfThreads, "Computers");
- return ADRObj;
- }
- public static Object[] ComputerSPNParser(Object[] AdComputers, int numOfThreads)
- {
- Object[] ADRObj = runProcessor(AdComputers, numOfThreads, "ComputerSPNs");
- return ADRObj;
- }
- public static Object[] LAPSParser(Object[] AdComputers, int numOfThreads)
- {
- Object[] ADRObj = runProcessor(AdComputers, numOfThreads, "LAPS");
- return ADRObj;
- }
- public static Object[] DACLParser(Object[] ADObjects, Object PSGUIDs, int numOfThreads)
- {
- ADWSClass.AdSIDDictionary = new Dictionary<String, String>();
- runProcessor(ADObjects, numOfThreads, "SIDDictionary");
- ADWSClass.GUIDs = (Hashtable) PSGUIDs;
- Object[] ADRObj = runProcessor(ADObjects, numOfThreads, "DACLs");
- return ADRObj;
- }
- public static Object[] SACLParser(Object[] ADObjects, Object PSGUIDs, int numOfThreads)
- {
- ADWSClass.GUIDs = (Hashtable) PSGUIDs;
- Object[] ADRObj = runProcessor(ADObjects, numOfThreads, "SACLs");
- return ADRObj;
- }
- static Object[] runProcessor(Object[] arrayToProcess, int numOfThreads, string processorType)
- {
- int totalRecords = arrayToProcess.Length;
- IRecordProcessor recordProcessor = recordProcessorFactory(processorType);
- IResultsHandler resultsHandler = new SimpleResultsHandler ();
- int numberOfRecordsPerThread = totalRecords / numOfThreads;
- int remainders = totalRecords % numOfThreads;
- Thread[] threads = new Thread[numOfThreads];
- for (int i = 0; i < numOfThreads; i++)
- {
- int numberOfRecordsToProcess = numberOfRecordsPerThread;
- if (i == (numOfThreads - 1))
- {
- //last thread, do the remaining records
- numberOfRecordsToProcess += remainders;
- }
- //split the full array into chunks to be given to different threads
- Object[] sliceToProcess = new Object[numberOfRecordsToProcess];
- Array.Copy(arrayToProcess, i * numberOfRecordsPerThread, sliceToProcess, 0, numberOfRecordsToProcess);
- ProcessorThread processorThread = new ProcessorThread(i, recordProcessor, resultsHandler, sliceToProcess);
- threads[i] = new Thread(processorThread.processThreadRecords);
- threads[i].Start();
- }
- foreach (Thread t in threads)
- {
- t.Join();
- }
- return resultsHandler.finalise();
- }
- static IRecordProcessor recordProcessorFactory(String name)
- {
- switch (name)
- {
- case "Users":
- return new UserRecordProcessor();
- case "UserSPNs":
- return new UserSPNRecordProcessor();
- case "Groups":
- return new GroupRecordProcessor();
- case "GroupsDictionary":
- return new GroupRecordDictionaryProcessor();
- case "GroupMembers":
- return new GroupMemberRecordProcessor();
- case "OUs":
- return new OURecordProcessor();
- case "GPOs":
- return new GPORecordProcessor();
- case "GPOsDictionary":
- return new GPORecordDictionaryProcessor();
- case "SOMs":
- return new SOMRecordProcessor();
- case "Printers":
- return new PrinterRecordProcessor();
- case "Computers":
- return new ComputerRecordProcessor();
- case "ComputerSPNs":
- return new ComputerSPNRecordProcessor();
- case "LAPS":
- return new LAPSRecordProcessor();
- case "SIDDictionary":
- return new SIDRecordDictionaryProcessor();
- case "DACLs":
- return new DACLRecordProcessor();
- case "SACLs":
- return new SACLRecordProcessor();
- }
- throw new ArgumentException("Invalid processor type " + name);
- }
- class ProcessorThread
- {
- readonly int id;
- readonly IRecordProcessor recordProcessor;
- readonly IResultsHandler resultsHandler;
- readonly Object[] objectsToBeProcessed;
- public ProcessorThread(int id, IRecordProcessor recordProcessor, IResultsHandler resultsHandler, Object[] objectsToBeProcessed)
- {
- this.recordProcessor = recordProcessor;
- this.id = id;
- this.resultsHandler = resultsHandler;
- this.objectsToBeProcessed = objectsToBeProcessed;
- }
- public void processThreadRecords()
- {
- for (int i = 0; i < objectsToBeProcessed.Length; i++)
- {
- Object[] result = recordProcessor.processRecord(objectsToBeProcessed[i]);
- resultsHandler.processResults(result); //this is a thread safe operation
- }
- }
- }
- //The interface and implmentation class used to process a record (this implemmentation just returns a log type string)
- interface IRecordProcessor
- {
- PSObject[] processRecord(Object record);
- }
- class UserRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- PSObject AdUser = (PSObject) record;
- bool? Enabled = null;
- bool MustChangePasswordatLogon = false;
- bool PasswordNotChangedafterMaxAge = false;
- bool NeverLoggedIn = false;
- int? DaysSinceLastLogon = null;
- int? DaysSinceLastPasswordChange = null;
- int? AccountExpirationNumofDays = null;
- bool Dormant = false;
- String SIDHistory = "";
- bool? KerberosRC4 = null;
- bool? KerberosAES128 = null;
- bool? KerberosAES256 = null;
- String DelegationType = null;
- String DelegationProtocol = null;
- String DelegationServices = null;
- DateTime? LastLogonDate = null;
- DateTime? PasswordLastSet = null;
- DateTime? AccountExpires = null;
- try
- {
- // The Enabled field can be blank which raises an exception. This may occur when the user is not allowed to query the UserAccountControl attribute.
- Enabled = (bool) AdUser.Members["Enabled"].Value;
- }
- catch //(Exception e)
- {
- //Console.WriteLine("{0} Exception caught.", e);
- }
- if (AdUser.Members["lastLogonTimeStamp"].Value != null)
- {
- //LastLogonDate = DateTime.FromFileTime((long)(AdUser.Members["lastLogonTimeStamp"].Value));
- // LastLogonDate is lastLogonTimeStamp converted to local time
- LastLogonDate = Convert.ToDateTime(AdUser.Members["LastLogonDate"].Value);
- DaysSinceLastLogon = Math.Abs((Date1 - (DateTime)LastLogonDate).Days);
- if (DaysSinceLastLogon > DormantTimeSpan)
- {
- Dormant = true;
- }
- }
- else
- {
- NeverLoggedIn = true;
- }
- if (Convert.ToString(AdUser.Members["pwdLastSet"].Value) == "0")
- {
- if ((bool) AdUser.Members["PasswordNeverExpires"].Value == false)
- {
- MustChangePasswordatLogon = true;
- }
- }
- if (AdUser.Members["PasswordLastSet"].Value != null)
- {
- //PasswordLastSet = DateTime.FromFileTime((long)(AdUser.Members["pwdLastSet"].Value));
- // PasswordLastSet is pwdLastSet converted to local time
- PasswordLastSet = Convert.ToDateTime(AdUser.Members["PasswordLastSet"].Value);
- DaysSinceLastPasswordChange = Math.Abs((Date1 - (DateTime)PasswordLastSet).Days);
- if (DaysSinceLastPasswordChange > PassMaxAge)
- {
- PasswordNotChangedafterMaxAge = true;
- }
- }
- //https://msdn.microsoft.com/en-us/library/ms675098(v=vs.85).aspx
- //if ((Int64) AdUser.Members["accountExpires"].Value != (Int64) 9223372036854775807)
- //{
- //if ((Int64) AdUser.Members["accountExpires"].Value != (Int64) 0)
- if (AdUser.Members["AccountExpirationDate"].Value != null)
- {
- try
- {
- //AccountExpires = DateTime.FromFileTime((long)(AdUser.Members["accountExpires"].Value));
- // AccountExpirationDate is accountExpires converted to local time
- AccountExpires = Convert.ToDateTime(AdUser.Members["AccountExpirationDate"].Value);
- AccountExpirationNumofDays = ((int)((DateTime)AccountExpires - Date1).Days);
- }
- catch //(Exception e)
- {
- //Console.WriteLine("{0} Exception caught.", e);
- }
- }
- //}
- Microsoft.ActiveDirectory.Management.ADPropertyValueCollection history = (Microsoft.ActiveDirectory.Management.ADPropertyValueCollection) AdUser.Members["SIDHistory"].Value;
- if (history.Value is System.Security.Principal.SecurityIdentifier[])
- {
- string sids = "";
- foreach (var value in (SecurityIdentifier[]) history.Value)
- {
- sids = sids + "," + Convert.ToString(value);
- }
- SIDHistory = sids.TrimStart(',');
- }
- else
- {
- SIDHistory = history != null ? Convert.ToString(history.Value) : "";
- }
- if (AdUser.Members["msDS-SupportedEncryptionTypes"].Value != null)
- {
- var userKerbEncFlags = (KerbEncFlags) AdUser.Members["msDS-SupportedEncryptionTypes"].Value;
- if (userKerbEncFlags != KerbEncFlags.ZERO)
- {
- KerberosRC4 = (userKerbEncFlags & KerbEncFlags.RC4_HMAC) == KerbEncFlags.RC4_HMAC;
- KerberosAES128 = (userKerbEncFlags & KerbEncFlags.AES128_CTS_HMAC_SHA1_96) == KerbEncFlags.AES128_CTS_HMAC_SHA1_96;
- KerberosAES256 = (userKerbEncFlags & KerbEncFlags.AES256_CTS_HMAC_SHA1_96) == KerbEncFlags.AES256_CTS_HMAC_SHA1_96;
- }
- }
- if ((bool) AdUser.Members["TrustedForDelegation"].Value)
- {
- DelegationType = "Unconstrained";
- DelegationServices = "Any";
- }
- if (AdUser.Members["msDS-AllowedToDelegateTo"] != null)
- {
- Microsoft.ActiveDirectory.Management.ADPropertyValueCollection delegateto = (Microsoft.ActiveDirectory.Management.ADPropertyValueCollection) AdUser.Members["msDS-AllowedToDelegateTo"].Value;
- if (delegateto.Value != null)
- {
- DelegationType = "Constrained";
- if (delegateto.Value is System.String[])
- {
- foreach (var value in (String[]) delegateto.Value)
- {
- DelegationServices = DelegationServices + "," + Convert.ToString(value);
- }
- DelegationServices = DelegationServices.TrimStart(',');
- }
- else
- {
- DelegationServices = Convert.ToString(delegateto.Value);
- }
- }
- }
- if ((bool) AdUser.Members["TrustedToAuthForDelegation"].Value == true)
- {
- DelegationProtocol = "Any";
- }
- else if (DelegationType != null)
- {
- DelegationProtocol = "Kerberos";
- }
- PSObject UserObj = new PSObject();
- UserObj.Members.Add(new PSNoteProperty("UserName", AdUser.Members["SamAccountName"].Value));
- UserObj.Members.Add(new PSNoteProperty("Name", CleanString(AdUser.Members["Name"].Value)));
- UserObj.Members.Add(new PSNoteProperty("Enabled", Enabled));
- UserObj.Members.Add(new PSNoteProperty("Must Change Password at Logon", MustChangePasswordatLogon));
- UserObj.Members.Add(new PSNoteProperty("Cannot Change Password", AdUser.Members["CannotChangePassword"].Value));
- UserObj.Members.Add(new PSNoteProperty("Password Never Expires", AdUser.Members["PasswordNeverExpires"].Value));
- UserObj.Members.Add(new PSNoteProperty("Reversible Password Encryption", AdUser.Members["AllowReversiblePasswordEncryption"].Value));
- UserObj.Members.Add(new PSNoteProperty("Smartcard Logon Required", AdUser.Members["SmartcardLogonRequired"].Value));
- UserObj.Members.Add(new PSNoteProperty("Delegation Permitted", !((bool) AdUser.Members["AccountNotDelegated"].Value)));
- UserObj.Members.Add(new PSNoteProperty("Kerberos DES Only", AdUser.Members["UseDESKeyOnly"].Value));
- UserObj.Members.Add(new PSNoteProperty("Kerberos RC4", KerberosRC4));
- UserObj.Members.Add(new PSNoteProperty("Kerberos AES-128bit", KerberosAES128));
- UserObj.Members.Add(new PSNoteProperty("Kerberos AES-256bit", KerberosAES256));
- UserObj.Members.Add(new PSNoteProperty("Does Not Require Pre Auth", AdUser.Members["DoesNotRequirePreAuth"].Value));
- UserObj.Members.Add(new PSNoteProperty("Never Logged in", NeverLoggedIn));
- UserObj.Members.Add(new PSNoteProperty("Logon Age (days)", DaysSinceLastLogon));
- UserObj.Members.Add(new PSNoteProperty("Password Age (days)", DaysSinceLastPasswordChange));
- UserObj.Members.Add(new PSNoteProperty("Dormant (> " + DormantTimeSpan + " days)", Dormant));
- UserObj.Members.Add(new PSNoteProperty("Password Age (> " + PassMaxAge + " days)", PasswordNotChangedafterMaxAge));
- UserObj.Members.Add(new PSNoteProperty("Account Locked Out", AdUser.Members["LockedOut"].Value));
- UserObj.Members.Add(new PSNoteProperty("Password Expired", AdUser.Members["PasswordExpired"].Value));
- UserObj.Members.Add(new PSNoteProperty("Password Not Required", AdUser.Members["PasswordNotRequired"].Value));
- UserObj.Members.Add(new PSNoteProperty("Delegation Type", DelegationType));
- UserObj.Members.Add(new PSNoteProperty("Delegation Protocol", DelegationProtocol));
- UserObj.Members.Add(new PSNoteProperty("Delegation Services", DelegationServices));
- UserObj.Members.Add(new PSNoteProperty("Logon Workstations", AdUser.Members["LogonWorkstations"].Value));
- UserObj.Members.Add(new PSNoteProperty("AdminCount", AdUser.Members["AdminCount"].Value));
- UserObj.Members.Add(new PSNoteProperty("Primary GroupID", AdUser.Members["primaryGroupID"].Value));
- UserObj.Members.Add(new PSNoteProperty("SID", AdUser.Members["SID"].Value));
- UserObj.Members.Add(new PSNoteProperty("SIDHistory", SIDHistory));
- UserObj.Members.Add(new PSNoteProperty("Description", CleanString(AdUser.Members["Description"].Value)));
- UserObj.Members.Add(new PSNoteProperty("Title", CleanString(AdUser.Members["Title"].Value)));
- UserObj.Members.Add(new PSNoteProperty("Department", CleanString(AdUser.Members["Department"].Value)));
- UserObj.Members.Add(new PSNoteProperty("Company", CleanString(AdUser.Members["Company"].Value)));
- UserObj.Members.Add(new PSNoteProperty("Manager", CleanString(AdUser.Members["Manager"].Value)));
- UserObj.Members.Add(new PSNoteProperty("Info", CleanString(AdUser.Members["Info"].Value)));
- UserObj.Members.Add(new PSNoteProperty("Last Logon Date", LastLogonDate));
- UserObj.Members.Add(new PSNoteProperty("Password LastSet", PasswordLastSet));
- UserObj.Members.Add(new PSNoteProperty("Account Expiration Date", AccountExpires));
- UserObj.Members.Add(new PSNoteProperty("Account Expiration (days)", AccountExpirationNumofDays));
- UserObj.Members.Add(new PSNoteProperty("Mobile", CleanString(AdUser.Members["Mobile"].Value)));
- UserObj.Members.Add(new PSNoteProperty("Email", CleanString(AdUser.Members["mail"].Value)));
- UserObj.Members.Add(new PSNoteProperty("HomeDirectory", AdUser.Members["homeDirectory"].Value));
- UserObj.Members.Add(new PSNoteProperty("ProfilePath", AdUser.Members["profilePath"].Value));
- UserObj.Members.Add(new PSNoteProperty("ScriptPath", AdUser.Members["ScriptPath"].Value));
- UserObj.Members.Add(new PSNoteProperty("UserAccountControl", AdUser.Members["UserAccountControl"].Value));
- UserObj.Members.Add(new PSNoteProperty("First Name", CleanString(AdUser.Members["givenName"].Value)));
- UserObj.Members.Add(new PSNoteProperty("Middle Name", CleanString(AdUser.Members["middleName"].Value)));
- UserObj.Members.Add(new PSNoteProperty("Last Name", CleanString(AdUser.Members["sn"].Value)));
- UserObj.Members.Add(new PSNoteProperty("Country", CleanString(AdUser.Members["c"].Value)));
- UserObj.Members.Add(new PSNoteProperty("whenCreated", AdUser.Members["whenCreated"].Value));
- UserObj.Members.Add(new PSNoteProperty("whenChanged", AdUser.Members["whenChanged"].Value));
- UserObj.Members.Add(new PSNoteProperty("DistinguishedName", CleanString(AdUser.Members["DistinguishedName"].Value)));
- UserObj.Members.Add(new PSNoteProperty("CanonicalName", AdUser.Members["CanonicalName"].Value));
- return new PSObject[] { UserObj };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class UserSPNRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- PSObject AdUser = (PSObject) record;
- List<PSObject> SPNList = new List<PSObject>();
- bool? Enabled = null;
- String Memberof = null;
- DateTime? PasswordLastSet = null;
- // When the user is not allowed to query the UserAccountControl attribute.
- if (AdUser.Members["userAccountControl"].Value != null)
- {
- var userFlags = (UACFlags) AdUser.Members["userAccountControl"].Value;
- Enabled = !((userFlags & UACFlags.ACCOUNTDISABLE) == UACFlags.ACCOUNTDISABLE);
- }
- if (Convert.ToString(AdUser.Members["pwdLastSet"].Value) != "0")
- {
- PasswordLastSet = DateTime.FromFileTime((long)AdUser.Members["pwdLastSet"].Value);
- }
- Microsoft.ActiveDirectory.Management.ADPropertyValueCollection SPNs = (Microsoft.ActiveDirectory.Management.ADPropertyValueCollection)AdUser.Members["servicePrincipalName"].Value;
- Microsoft.ActiveDirectory.Management.ADPropertyValueCollection MemberOfAttribute = (Microsoft.ActiveDirectory.Management.ADPropertyValueCollection)AdUser.Members["memberof"].Value;
- if (MemberOfAttribute.Value is System.String[])
- {
- foreach (String Member in (System.String[])MemberOfAttribute.Value)
- {
- Memberof = Memberof + "," + ((Convert.ToString(Member)).Split(',')[0]).Split('=')[1];
- }
- Memberof = Memberof.TrimStart(',');
- }
- else if (Memberof != null)
- {
- Memberof = ((Convert.ToString(MemberOfAttribute.Value)).Split(',')[0]).Split('=')[1];
- }
- String Description = CleanString(AdUser.Members["Description"].Value);
- String PrimaryGroupID = Convert.ToString(AdUser.Members["primaryGroupID"].Value);
- if (SPNs.Value is System.String[])
- {
- foreach (String SPN in (System.String[])SPNs.Value)
- {
- String[] SPNArray = SPN.Split('/');
- PSObject UserSPNObj = new PSObject();
- UserSPNObj.Members.Add(new PSNoteProperty("Name", AdUser.Members["Name"].Value));
- UserSPNObj.Members.Add(new PSNoteProperty("Username", AdUser.Members["SamAccountName"].Value));
- UserSPNObj.Members.Add(new PSNoteProperty("Enabled", Enabled));
- UserSPNObj.Members.Add(new PSNoteProperty("Service", SPNArray[0]));
- UserSPNObj.Members.Add(new PSNoteProperty("Host", SPNArray[1]));
- UserSPNObj.Members.Add(new PSNoteProperty("Password Last Set", PasswordLastSet));
- UserSPNObj.Members.Add(new PSNoteProperty("Description", Description));
- UserSPNObj.Members.Add(new PSNoteProperty("Primary GroupID", PrimaryGroupID));
- UserSPNObj.Members.Add(new PSNoteProperty("Memberof", Memberof));
- SPNList.Add( UserSPNObj );
- }
- }
- else
- {
- String[] SPNArray = Convert.ToString(SPNs.Value).Split('/');
- PSObject UserSPNObj = new PSObject();
- UserSPNObj.Members.Add(new PSNoteProperty("Name", AdUser.Members["Name"].Value));
- UserSPNObj.Members.Add(new PSNoteProperty("Username", AdUser.Members["SamAccountName"].Value));
- UserSPNObj.Members.Add(new PSNoteProperty("Enabled", Enabled));
- UserSPNObj.Members.Add(new PSNoteProperty("Service", SPNArray[0]));
- UserSPNObj.Members.Add(new PSNoteProperty("Host", SPNArray[1]));
- UserSPNObj.Members.Add(new PSNoteProperty("Password Last Set", PasswordLastSet));
- UserSPNObj.Members.Add(new PSNoteProperty("Description", Description));
- UserSPNObj.Members.Add(new PSNoteProperty("Primary GroupID", PrimaryGroupID));
- UserSPNObj.Members.Add(new PSNoteProperty("Memberof", Memberof));
- SPNList.Add( UserSPNObj );
- }
- return SPNList.ToArray();
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class GroupRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- PSObject AdGroup = (PSObject) record;
- string ManagedByValue = Convert.ToString(AdGroup.Members["managedBy"].Value);
- string ManagedBy = "";
- String SIDHistory = "";
- if (AdGroup.Members["managedBy"].Value != null)
- {
- ManagedBy = (ManagedByValue.Split(',')[0]).Split('=')[1];
- }
- Microsoft.ActiveDirectory.Management.ADPropertyValueCollection history = (Microsoft.ActiveDirectory.Management.ADPropertyValueCollection) AdGroup.Members["SIDHistory"].Value;
- if (history.Value is System.Security.Principal.SecurityIdentifier[])
- {
- string sids = "";
- foreach (var value in (SecurityIdentifier[]) history.Value)
- {
- sids = sids + "," + Convert.ToString(value);
- }
- SIDHistory = sids.TrimStart(',');
- }
- else
- {
- SIDHistory = history != null ? Convert.ToString(history.Value) : "";
- }
- PSObject GroupObj = new PSObject();
- GroupObj.Members.Add(new PSNoteProperty("Name", AdGroup.Members["SamAccountName"].Value));
- GroupObj.Members.Add(new PSNoteProperty("AdminCount", AdGroup.Members["AdminCount"].Value));
- GroupObj.Members.Add(new PSNoteProperty("GroupCategory", AdGroup.Members["GroupCategory"].Value));
- GroupObj.Members.Add(new PSNoteProperty("GroupScope", AdGroup.Members["GroupScope"].Value));
- GroupObj.Members.Add(new PSNoteProperty("ManagedBy", ManagedBy));
- GroupObj.Members.Add(new PSNoteProperty("SID", AdGroup.Members["sid"].Value));
- GroupObj.Members.Add(new PSNoteProperty("SIDHistory", SIDHistory));
- GroupObj.Members.Add(new PSNoteProperty("Description", CleanString(AdGroup.Members["Description"].Value)));
- GroupObj.Members.Add(new PSNoteProperty("whenCreated", AdGroup.Members["whenCreated"].Value));
- GroupObj.Members.Add(new PSNoteProperty("whenChanged", AdGroup.Members["whenChanged"].Value));
- GroupObj.Members.Add(new PSNoteProperty("DistinguishedName", CleanString(AdGroup.Members["DistinguishedName"].Value)));
- GroupObj.Members.Add(new PSNoteProperty("CanonicalName", AdGroup.Members["CanonicalName"].Value));
- return new PSObject[] { GroupObj };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class GroupRecordDictionaryProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- PSObject AdGroup = (PSObject) record;
- ADWSClass.AdGroupDictionary.Add((Convert.ToString(AdGroup.Properties["SID"].Value)), (Convert.ToString(AdGroup.Members["SamAccountName"].Value)));
- return new PSObject[] { };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class GroupMemberRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- // based on https://github.com/BloodHoundAD/BloodHound/blob/master/PowerShell/BloodHound.ps1
- PSObject AdGroup = (PSObject) record;
- List<PSObject> GroupsList = new List<PSObject>();
- string SamAccountType = Convert.ToString(AdGroup.Members["samaccounttype"].Value);
- string AccountType = "";
- string GroupName = "";
- string MemberUserName = "-";
- string MemberName = "";
- if (Groups.Contains(SamAccountType))
- {
- AccountType = "group";
- MemberName = ((Convert.ToString(AdGroup.Members["DistinguishedName"].Value)).Split(',')[0]).Split('=')[1];
- Microsoft.ActiveDirectory.Management.ADPropertyValueCollection MemberGroups = (Microsoft.ActiveDirectory.Management.ADPropertyValueCollection)AdGroup.Members["memberof"].Value;
- if (MemberGroups.Value != null)
- {
- if (MemberGroups.Value is System.String[])
- {
- foreach (String GroupMember in (System.String[])MemberGroups.Value)
- {
- GroupName = ((Convert.ToString(GroupMember)).Split(',')[0]).Split('=')[1];
- PSObject GroupMemberObj = new PSObject();
- GroupMemberObj.Members.Add(new PSNoteProperty("Group Name", GroupName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member UserName", MemberUserName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member Name", MemberName));
- GroupMemberObj.Members.Add(new PSNoteProperty("AccountType", AccountType));
- GroupsList.Add( GroupMemberObj );
- }
- }
- else
- {
- GroupName = (Convert.ToString(MemberGroups.Value).Split(',')[0]).Split('=')[1];
- PSObject GroupMemberObj = new PSObject();
- GroupMemberObj.Members.Add(new PSNoteProperty("Group Name", GroupName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member UserName", MemberUserName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member Name", MemberName));
- GroupMemberObj.Members.Add(new PSNoteProperty("AccountType", AccountType));
- GroupsList.Add( GroupMemberObj );
- }
- }
- }
- if (Users.Contains(SamAccountType))
- {
- AccountType = "user";
- MemberName = ((Convert.ToString(AdGroup.Members["DistinguishedName"].Value)).Split(',')[0]).Split('=')[1];
- MemberUserName = Convert.ToString(AdGroup.Members["sAMAccountName"].Value);
- String PrimaryGroupID = Convert.ToString(AdGroup.Members["primaryGroupID"].Value);
- try
- {
- GroupName = ADWSClass.AdGroupDictionary[ADWSClass.DomainSID + "-" + PrimaryGroupID];
- }
- catch //(Exception e)
- {
- //Console.WriteLine("{0} Exception caught.", e);
- GroupName = PrimaryGroupID;
- }
- {
- PSObject GroupMemberObj = new PSObject();
- GroupMemberObj.Members.Add(new PSNoteProperty("Group Name", GroupName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member UserName", MemberUserName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member Name", MemberName));
- GroupMemberObj.Members.Add(new PSNoteProperty("AccountType", AccountType));
- GroupsList.Add( GroupMemberObj );
- }
- Microsoft.ActiveDirectory.Management.ADPropertyValueCollection MemberGroups = (Microsoft.ActiveDirectory.Management.ADPropertyValueCollection)AdGroup.Members["memberof"].Value;
- if (MemberGroups.Value != null)
- {
- if (MemberGroups.Value is System.String[])
- {
- foreach (String GroupMember in (System.String[])MemberGroups.Value)
- {
- GroupName = ((Convert.ToString(GroupMember)).Split(',')[0]).Split('=')[1];
- PSObject GroupMemberObj = new PSObject();
- GroupMemberObj.Members.Add(new PSNoteProperty("Group Name", GroupName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member UserName", MemberUserName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member Name", MemberName));
- GroupMemberObj.Members.Add(new PSNoteProperty("AccountType", AccountType));
- GroupsList.Add( GroupMemberObj );
- }
- }
- else
- {
- GroupName = (Convert.ToString(MemberGroups.Value).Split(',')[0]).Split('=')[1];
- PSObject GroupMemberObj = new PSObject();
- GroupMemberObj.Members.Add(new PSNoteProperty("Group Name", GroupName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member UserName", MemberUserName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member Name", MemberName));
- GroupMemberObj.Members.Add(new PSNoteProperty("AccountType", AccountType));
- GroupsList.Add( GroupMemberObj );
- }
- }
- }
- if (Computers.Contains(SamAccountType))
- {
- AccountType = "computer";
- MemberName = ((Convert.ToString(AdGroup.Members["DistinguishedName"].Value)).Split(',')[0]).Split('=')[1];
- MemberUserName = Convert.ToString(AdGroup.Members["sAMAccountName"].Value);
- String PrimaryGroupID = Convert.ToString(AdGroup.Members["primaryGroupID"].Value);
- try
- {
- GroupName = ADWSClass.AdGroupDictionary[ADWSClass.DomainSID + "-" + PrimaryGroupID];
- }
- catch //(Exception e)
- {
- //Console.WriteLine("{0} Exception caught.", e);
- GroupName = PrimaryGroupID;
- }
- {
- PSObject GroupMemberObj = new PSObject();
- GroupMemberObj.Members.Add(new PSNoteProperty("Group Name", GroupName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member UserName", MemberUserName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member Name", MemberName));
- GroupMemberObj.Members.Add(new PSNoteProperty("AccountType", AccountType));
- GroupsList.Add( GroupMemberObj );
- }
- Microsoft.ActiveDirectory.Management.ADPropertyValueCollection MemberGroups = (Microsoft.ActiveDirectory.Management.ADPropertyValueCollection)AdGroup.Members["memberof"].Value;
- if (MemberGroups.Value != null)
- {
- if (MemberGroups.Value is System.String[])
- {
- foreach (String GroupMember in (System.String[])MemberGroups.Value)
- {
- GroupName = ((Convert.ToString(GroupMember)).Split(',')[0]).Split('=')[1];
- PSObject GroupMemberObj = new PSObject();
- GroupMemberObj.Members.Add(new PSNoteProperty("Group Name", GroupName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member UserName", MemberUserName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member Name", MemberName));
- GroupMemberObj.Members.Add(new PSNoteProperty("AccountType", AccountType));
- GroupsList.Add( GroupMemberObj );
- }
- }
- else
- {
- GroupName = (Convert.ToString(MemberGroups.Value).Split(',')[0]).Split('=')[1];
- PSObject GroupMemberObj = new PSObject();
- GroupMemberObj.Members.Add(new PSNoteProperty("Group Name", GroupName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member UserName", MemberUserName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member Name", MemberName));
- GroupMemberObj.Members.Add(new PSNoteProperty("AccountType", AccountType));
- GroupsList.Add( GroupMemberObj );
- }
- }
- }
- if (TrustAccounts.Contains(SamAccountType))
- {
- // TO DO
- }
- return GroupsList.ToArray();
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class OURecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- PSObject AdOU = (PSObject) record;
- PSObject OUObj = new PSObject();
- OUObj.Members.Add(new PSNoteProperty("Name", AdOU.Members["Name"].Value));
- OUObj.Members.Add(new PSNoteProperty("Depth", ((Convert.ToString(AdOU.Members["DistinguishedName"].Value).Split(new string[] { "OU=" }, StringSplitOptions.None)).Length -1)));
- OUObj.Members.Add(new PSNoteProperty("Description", AdOU.Members["Description"].Value));
- OUObj.Members.Add(new PSNoteProperty("whenCreated", AdOU.Members["whenCreated"].Value));
- OUObj.Members.Add(new PSNoteProperty("whenChanged", AdOU.Members["whenChanged"].Value));
- OUObj.Members.Add(new PSNoteProperty("DistinguishedName", AdOU.Members["DistinguishedName"].Value));
- return new PSObject[] { OUObj };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class GPORecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- PSObject AdGPO = (PSObject) record;
- PSObject GPOObj = new PSObject();
- GPOObj.Members.Add(new PSNoteProperty("DisplayName", CleanString(AdGPO.Members["DisplayName"].Value)));
- GPOObj.Members.Add(new PSNoteProperty("GUID", CleanString(AdGPO.Members["Name"].Value)));
- GPOObj.Members.Add(new PSNoteProperty("whenCreated", AdGPO.Members["whenCreated"].Value));
- GPOObj.Members.Add(new PSNoteProperty("whenChanged", AdGPO.Members["whenChanged"].Value));
- GPOObj.Members.Add(new PSNoteProperty("DistinguishedName", CleanString(AdGPO.Members["DistinguishedName"].Value)));
- GPOObj.Members.Add(new PSNoteProperty("FilePath", AdGPO.Members["gPCFileSysPath"].Value));
- return new PSObject[] { GPOObj };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class GPORecordDictionaryProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- PSObject AdGPO = (PSObject) record;
- ADWSClass.AdGPODictionary.Add((Convert.ToString(AdGPO.Members["DistinguishedName"].Value).ToUpper()), (Convert.ToString(AdGPO.Members["DisplayName"].Value)));
- return new PSObject[] { };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class SOMRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- PSObject AdSOM = (PSObject) record;
- List<PSObject> SOMsList = new List<PSObject>();
- int Depth = 0;
- bool BlockInheritance = false;
- bool? LinkEnabled = null;
- bool? Enforced = null;
- String gPLink = Convert.ToString(AdSOM.Members["gPLink"].Value);
- String GPOName = null;
- Depth = (Convert.ToString(AdSOM.Members["DistinguishedName"].Value).Split(new string[] { "OU=" }, StringSplitOptions.None)).Length -1;
- if (AdSOM.Members["gPOptions"].Value != null && (int) AdSOM.Members["gPOptions"].Value == 1)
- {
- BlockInheritance = true;
- }
- var GPLinks = gPLink.Split(']', '[').Where(x => x.StartsWith("LDAP"));
- int Order = (GPLinks.ToArray()).Length;
- if (Order == 0)
- {
- PSObject SOMObj = new PSObject();
- SOMObj.Members.Add(new PSNoteProperty("Name", AdSOM.Members["Name"].Value));
- SOMObj.Members.Add(new PSNoteProperty("Depth", Depth));
- SOMObj.Members.Add(new PSNoteProperty("DistinguishedName", AdSOM.Members["DistinguishedName"].Value));
- SOMObj.Members.Add(new PSNoteProperty("Link Order", null));
- SOMObj.Members.Add(new PSNoteProperty("GPO", GPOName));
- SOMObj.Members.Add(new PSNoteProperty("Enforced", Enforced));
- SOMObj.Members.Add(new PSNoteProperty("Link Enabled", LinkEnabled));
- SOMObj.Members.Add(new PSNoteProperty("BlockInheritance", BlockInheritance));
- SOMObj.Members.Add(new PSNoteProperty("gPLink", gPLink));
- SOMObj.Members.Add(new PSNoteProperty("gPOptions", AdSOM.Members["gPOptions"].Value));
- SOMsList.Add( SOMObj );
- }
- foreach (String link in GPLinks)
- {
- String[] linksplit = link.Split('/', ';');
- if (!Convert.ToBoolean((Convert.ToInt32(linksplit[3]) & 1)))
- {
- LinkEnabled = true;
- }
- else
- {
- LinkEnabled = false;
- }
- if (Convert.ToBoolean((Convert.ToInt32(linksplit[3]) & 2)))
- {
- Enforced = true;
- }
- else
- {
- Enforced = false;
- }
- GPOName = ADWSClass.AdGPODictionary.ContainsKey(linksplit[2].ToUpper()) ? ADWSClass.AdGPODictionary[linksplit[2].ToUpper()] : linksplit[2].Split('=',',')[1];
- PSObject SOMObj = new PSObject();
- SOMObj.Members.Add(new PSNoteProperty("Name", AdSOM.Members["Name"].Value));
- SOMObj.Members.Add(new PSNoteProperty("Depth", Depth));
- SOMObj.Members.Add(new PSNoteProperty("DistinguishedName", AdSOM.Members["DistinguishedName"].Value));
- SOMObj.Members.Add(new PSNoteProperty("Link Order", Order));
- SOMObj.Members.Add(new PSNoteProperty("GPO", GPOName));
- SOMObj.Members.Add(new PSNoteProperty("Enforced", Enforced));
- SOMObj.Members.Add(new PSNoteProperty("Link Enabled", LinkEnabled));
- SOMObj.Members.Add(new PSNoteProperty("BlockInheritance", BlockInheritance));
- SOMObj.Members.Add(new PSNoteProperty("gPLink", gPLink));
- SOMObj.Members.Add(new PSNoteProperty("gPOptions", AdSOM.Members["gPOptions"].Value));
- SOMsList.Add( SOMObj );
- Order--;
- }
- return SOMsList.ToArray();
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class PrinterRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- PSObject AdPrinter = (PSObject) record;
- PSObject PrinterObj = new PSObject();
- PrinterObj.Members.Add(new PSNoteProperty("Name", AdPrinter.Members["Name"].Value));
- PrinterObj.Members.Add(new PSNoteProperty("ServerName", AdPrinter.Members["serverName"].Value));
- PrinterObj.Members.Add(new PSNoteProperty("ShareName", ((Microsoft.ActiveDirectory.Management.ADPropertyValueCollection) (AdPrinter.Members["printShareName"].Value)).Value));
- PrinterObj.Members.Add(new PSNoteProperty("DriverName", AdPrinter.Members["driverName"].Value));
- PrinterObj.Members.Add(new PSNoteProperty("DriverVersion", AdPrinter.Members["driverVersion"].Value));
- PrinterObj.Members.Add(new PSNoteProperty("PortName", ((Microsoft.ActiveDirectory.Management.ADPropertyValueCollection) (AdPrinter.Members["portName"].Value)).Value));
- PrinterObj.Members.Add(new PSNoteProperty("URL", ((Microsoft.ActiveDirectory.Management.ADPropertyValueCollection) (AdPrinter.Members["url"].Value)).Value));
- PrinterObj.Members.Add(new PSNoteProperty("whenCreated", AdPrinter.Members["whenCreated"].Value));
- PrinterObj.Members.Add(new PSNoteProperty("whenChanged", AdPrinter.Members["whenChanged"].Value));
- return new PSObject[] { PrinterObj };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class ComputerRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- PSObject AdComputer = (PSObject) record;
- int? DaysSinceLastLogon = null;
- int? DaysSinceLastPasswordChange = null;
- bool Dormant = false;
- bool PasswordNotChangedafterMaxAge = false;
- String SIDHistory = "";
- String DelegationType = null;
- String DelegationProtocol = null;
- String DelegationServices = null;
- DateTime? LastLogonDate = null;
- DateTime? PasswordLastSet = null;
- if (AdComputer.Members["LastLogonDate"].Value != null)
- {
- //LastLogonDate = DateTime.FromFileTime((long)(AdComputer.Members["lastLogonTimeStamp"].Value));
- // LastLogonDate is lastLogonTimeStamp converted to local time
- LastLogonDate = Convert.ToDateTime(AdComputer.Members["LastLogonDate"].Value);
- DaysSinceLastLogon = Math.Abs((Date1 - (DateTime)LastLogonDate).Days);
- if (DaysSinceLastLogon > DormantTimeSpan)
- {
- Dormant = true;
- }
- }
- if (AdComputer.Members["PasswordLastSet"].Value != null)
- {
- //PasswordLastSet = DateTime.FromFileTime((long)(AdComputer.Members["pwdLastSet"].Value));
- // PasswordLastSet is pwdLastSet converted to local time
- PasswordLastSet = Convert.ToDateTime(AdComputer.Members["PasswordLastSet"].Value);
- DaysSinceLastPasswordChange = Math.Abs((Date1 - (DateTime)PasswordLastSet).Days);
- if (DaysSinceLastPasswordChange > PassMaxAge)
- {
- PasswordNotChangedafterMaxAge = true;
- }
- }
- if ( ((bool) AdComputer.Members["TrustedForDelegation"].Value) && ((int) AdComputer.Members["primaryGroupID"].Value == 515) )
- {
- DelegationType = "Unconstrained";
- DelegationServices = "Any";
- }
- if (AdComputer.Members["msDS-AllowedToDelegateTo"] != null)
- {
- Microsoft.ActiveDirectory.Management.ADPropertyValueCollection delegateto = (Microsoft.ActiveDirectory.Management.ADPropertyValueCollection) AdComputer.Members["msDS-AllowedToDelegateTo"].Value;
- if (delegateto.Value != null)
- {
- DelegationType = "Constrained";
- if (delegateto.Value is System.String[])
- {
- foreach (var value in (String[]) delegateto.Value)
- {
- DelegationServices = DelegationServices + "," + Convert.ToString(value);
- }
- DelegationServices = DelegationServices.TrimStart(',');
- }
- else
- {
- DelegationServices = Convert.ToString(delegateto.Value);
- }
- }
- }
- if ((bool) AdComputer.Members["TrustedToAuthForDelegation"].Value)
- {
- DelegationProtocol = "Any";
- }
- else if (DelegationType != null)
- {
- DelegationProtocol = "Kerberos";
- }
- Microsoft.ActiveDirectory.Management.ADPropertyValueCollection history = (Microsoft.ActiveDirectory.Management.ADPropertyValueCollection) AdComputer.Members["SIDHistory"].Value;
- if (history.Value is System.Security.Principal.SecurityIdentifier[])
- {
- string sids = "";
- foreach (var value in (SecurityIdentifier[]) history.Value)
- {
- sids = sids + "," + Convert.ToString(value);
- }
- SIDHistory = sids.TrimStart(',');
- }
- else
- {
- SIDHistory = history != null ? Convert.ToString(history.Value) : "";
- }
- String OperatingSystem = CleanString((AdComputer.Members["OperatingSystem"].Value != null ? AdComputer.Members["OperatingSystem"].Value : "-") + " " + AdComputer.Members["OperatingSystemHotfix"].Value + " " + AdComputer.Members["OperatingSystemServicePack"].Value + " " + AdComputer.Members["OperatingSystemVersion"].Value);
- PSObject ComputerObj = new PSObject();
- ComputerObj.Members.Add(new PSNoteProperty("Name", AdComputer.Members["Name"].Value));
- ComputerObj.Members.Add(new PSNoteProperty("DNSHostName", AdComputer.Members["DNSHostName"].Value));
- ComputerObj.Members.Add(new PSNoteProperty("Enabled", AdComputer.Members["Enabled"].Value));
- ComputerObj.Members.Add(new PSNoteProperty("IPv4Address", AdComputer.Members["IPv4Address"].Value));
- ComputerObj.Members.Add(new PSNoteProperty("Operating System", OperatingSystem));
- ComputerObj.Members.Add(new PSNoteProperty("Logon Age (days)", DaysSinceLastLogon));
- ComputerObj.Members.Add(new PSNoteProperty("Password Age (days)", DaysSinceLastPasswordChange));
- ComputerObj.Members.Add(new PSNoteProperty("Dormant (> " + DormantTimeSpan + " days)", Dormant));
- ComputerObj.Members.Add(new PSNoteProperty("Password Age (> " + PassMaxAge + " days)", PasswordNotChangedafterMaxAge));
- ComputerObj.Members.Add(new PSNoteProperty("Delegation Type", DelegationType));
- ComputerObj.Members.Add(new PSNoteProperty("Delegation Protocol", DelegationProtocol));
- ComputerObj.Members.Add(new PSNoteProperty("Delegation Services", DelegationServices));
- ComputerObj.Members.Add(new PSNoteProperty("UserName", AdComputer.Members["SamAccountName"].Value));
- ComputerObj.Members.Add(new PSNoteProperty("Primary Group ID", AdComputer.Members["primaryGroupID"].Value));
- ComputerObj.Members.Add(new PSNoteProperty("SID", AdComputer.Members["SID"].Value));
- ComputerObj.Members.Add(new PSNoteProperty("SIDHistory", SIDHistory));
- ComputerObj.Members.Add(new PSNoteProperty("Description", AdComputer.Members["Description"].Value));
- ComputerObj.Members.Add(new PSNoteProperty("ms-ds-CreatorSid", AdComputer.Members["ms-ds-CreatorSid"].Value));
- ComputerObj.Members.Add(new PSNoteProperty("Last Logon Date", LastLogonDate));
- ComputerObj.Members.Add(new PSNoteProperty("Password LastSet", PasswordLastSet));
- ComputerObj.Members.Add(new PSNoteProperty("UserAccountControl", AdComputer.Members["UserAccountControl"].Value));
- ComputerObj.Members.Add(new PSNoteProperty("whenCreated", AdComputer.Members["whenCreated"].Value));
- ComputerObj.Members.Add(new PSNoteProperty("whenChanged", AdComputer.Members["whenChanged"].Value));
- ComputerObj.Members.Add(new PSNoteProperty("Distinguished Name", AdComputer.Members["DistinguishedName"].Value));
- return new PSObject[] { ComputerObj };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class ComputerSPNRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- PSObject AdComputer = (PSObject) record;
- List<PSObject> SPNList = new List<PSObject>();
- Microsoft.ActiveDirectory.Management.ADPropertyValueCollection SPNs = (Microsoft.ActiveDirectory.Management.ADPropertyValueCollection)AdComputer.Members["servicePrincipalName"].Value;
- if (SPNs.Value is System.String[])
- {
- foreach (String SPN in (System.String[])SPNs.Value)
- {
- bool flag = true;
- String[] SPNArray = SPN.Split('/');
- foreach (PSObject Obj in SPNList)
- {
- if ( (String) Obj.Members["Service"].Value == SPNArray[0] )
- {
- Obj.Members["Host"].Value = String.Join(",", (Obj.Members["Host"].Value + "," + SPNArray[1]).Split(',').Distinct().ToArray());
- flag = false;
- }
- }
- if (flag)
- {
- PSObject ComputerSPNObj = new PSObject();
- ComputerSPNObj.Members.Add(new PSNoteProperty("Name", AdComputer.Members["Name"].Value));
- ComputerSPNObj.Members.Add(new PSNoteProperty("Service", SPNArray[0]));
- ComputerSPNObj.Members.Add(new PSNoteProperty("Host", SPNArray[1]));
- SPNList.Add( ComputerSPNObj );
- }
- }
- }
- else
- {
- String[] SPNArray = Convert.ToString(SPNs.Value).Split('/');
- PSObject ComputerSPNObj = new PSObject();
- ComputerSPNObj.Members.Add(new PSNoteProperty("Name", AdComputer.Members["Name"].Value));
- ComputerSPNObj.Members.Add(new PSNoteProperty("Service", SPNArray[0]));
- ComputerSPNObj.Members.Add(new PSNoteProperty("Host", SPNArray[1]));
- SPNList.Add( ComputerSPNObj );
- }
- return SPNList.ToArray();
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class LAPSRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- PSObject AdComputer = (PSObject) record;
- bool PasswordStored = false;
- DateTime? CurrentExpiration = null;
- try
- {
- CurrentExpiration = DateTime.FromFileTime((long)(AdComputer.Members["ms-Mcs-AdmPwdExpirationTime"].Value));
- PasswordStored = true;
- }
- catch //(Exception e)
- {
- //Console.WriteLine("{0} Exception caught.", e);
- }
- PSObject LAPSObj = new PSObject();
- LAPSObj.Members.Add(new PSNoteProperty("Hostname", (AdComputer.Members["DNSHostName"].Value != null ? AdComputer.Members["DNSHostName"].Value : AdComputer.Members["CN"].Value )));
- LAPSObj.Members.Add(new PSNoteProperty("Stored", PasswordStored));
- LAPSObj.Members.Add(new PSNoteProperty("Readable", (AdComputer.Members["ms-Mcs-AdmPwd"].Value != null ? true : false)));
- LAPSObj.Members.Add(new PSNoteProperty("Password", AdComputer.Members["ms-Mcs-AdmPwd"].Value));
- LAPSObj.Members.Add(new PSNoteProperty("Expiration", CurrentExpiration));
- return new PSObject[] { LAPSObj };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class SIDRecordDictionaryProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- PSObject AdObject = (PSObject) record;
- switch (Convert.ToString(AdObject.Members["ObjectClass"].Value))
- {
- case "user":
- case "computer":
- case "group":
- ADWSClass.AdSIDDictionary.Add(Convert.ToString(AdObject.Members["objectsid"].Value), Convert.ToString(AdObject.Members["Name"].Value));
- break;
- }
- return new PSObject[] { };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} {1} Exception caught.", ((PSObject) record).Members["ObjectClass"].Value, e);
- return new PSObject[] { };
- }
- }
- }
- class DACLRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- PSObject AdObject = (PSObject) record;
- String Name = null;
- String Type = null;
- List<PSObject> DACLList = new List<PSObject>();
- Name = Convert.ToString(AdObject.Members["Name"].Value);
- switch (Convert.ToString(AdObject.Members["objectClass"].Value))
- {
- case "user":
- Type = "User";
- break;
- case "computer":
- Type = "Computer";
- break;
- case "group":
- Type = "Group";
- break;
- case "container":
- Type = "Container";
- break;
- case "groupPolicyContainer":
- Type = "GPO";
- Name = Convert.ToString(AdObject.Members["DisplayName"].Value);
- break;
- case "organizationalUnit":
- Type = "OU";
- break;
- case "domainDNS":
- Type = "Domain";
- break;
- default:
- Type = Convert.ToString(AdObject.Members["objectClass"].Value);
- break;
- }
- // When the user is not allowed to query the ntsecuritydescriptor attribute.
- if (AdObject.Members["ntsecuritydescriptor"] != null)
- {
- DirectoryObjectSecurity DirObjSec = (DirectoryObjectSecurity) AdObject.Members["ntsecuritydescriptor"].Value;
- AuthorizationRuleCollection AccessRules = (AuthorizationRuleCollection) DirObjSec.GetAccessRules(true,true,typeof(System.Security.Principal.NTAccount));
- foreach (ActiveDirectoryAccessRule Rule in AccessRules)
- {
- String IdentityReference = Convert.ToString(Rule.IdentityReference);
- String Owner = Convert.ToString(DirObjSec.GetOwner(typeof(System.Security.Principal.SecurityIdentifier)));
- PSObject ObjectObj = new PSObject();
- ObjectObj.Members.Add(new PSNoteProperty("Name", CleanString(Name)));
- ObjectObj.Members.Add(new PSNoteProperty("Type", Type));
- ObjectObj.Members.Add(new PSNoteProperty("ObjectTypeName", ADWSClass.GUIDs[Convert.ToString(Rule.ObjectType)]));
- ObjectObj.Members.Add(new PSNoteProperty("InheritedObjectTypeName", ADWSClass.GUIDs[Convert.ToString(Rule.InheritedObjectType)]));
- ObjectObj.Members.Add(new PSNoteProperty("ActiveDirectoryRights", Rule.ActiveDirectoryRights));
- ObjectObj.Members.Add(new PSNoteProperty("AccessControlType", Rule.AccessControlType));
- ObjectObj.Members.Add(new PSNoteProperty("IdentityReferenceName", ADWSClass.AdSIDDictionary.ContainsKey(IdentityReference) ? ADWSClass.AdSIDDictionary[IdentityReference] : IdentityReference));
- ObjectObj.Members.Add(new PSNoteProperty("OwnerName", ADWSClass.AdSIDDictionary.ContainsKey(Owner) ? ADWSClass.AdSIDDictionary[Owner] : Owner));
- ObjectObj.Members.Add(new PSNoteProperty("Inherited", Rule.IsInherited));
- ObjectObj.Members.Add(new PSNoteProperty("ObjectFlags", Rule.ObjectFlags));
- ObjectObj.Members.Add(new PSNoteProperty("InheritanceFlags", Rule.InheritanceFlags));
- ObjectObj.Members.Add(new PSNoteProperty("InheritanceType", Rule.InheritanceType));
- ObjectObj.Members.Add(new PSNoteProperty("PropagationFlags", Rule.PropagationFlags));
- ObjectObj.Members.Add(new PSNoteProperty("ObjectType", Rule.ObjectType));
- ObjectObj.Members.Add(new PSNoteProperty("InheritedObjectType", Rule.InheritedObjectType));
- ObjectObj.Members.Add(new PSNoteProperty("IdentityReference", Rule.IdentityReference));
- ObjectObj.Members.Add(new PSNoteProperty("Owner", Owner));
- ObjectObj.Members.Add(new PSNoteProperty("DistinguishedName", AdObject.Members["DistinguishedName"].Value));
- DACLList.Add( ObjectObj );
- }
- }
- return DACLList.ToArray();
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class SACLRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- PSObject AdObject = (PSObject) record;
- String Name = null;
- String Type = null;
- List<PSObject> SACLList = new List<PSObject>();
- Name = Convert.ToString(AdObject.Members["Name"].Value);
- switch (Convert.ToString(AdObject.Members["objectClass"].Value))
- {
- case "user":
- Type = "User";
- break;
- case "computer":
- Type = "Computer";
- break;
- case "group":
- Type = "Group";
- break;
- case "container":
- Type = "Container";
- break;
- case "groupPolicyContainer":
- Type = "GPO";
- Name = Convert.ToString(AdObject.Members["DisplayName"].Value);
- break;
- case "organizationalUnit":
- Type = "OU";
- break;
- case "domainDNS":
- Type = "Domain";
- break;
- default:
- Type = Convert.ToString(AdObject.Members["objectClass"].Value);
- break;
- }
- // When the user is not allowed to query the ntsecuritydescriptor attribute.
- if (AdObject.Members["ntsecuritydescriptor"] != null)
- {
- DirectoryObjectSecurity DirObjSec = (DirectoryObjectSecurity) AdObject.Members["ntsecuritydescriptor"].Value;
- AuthorizationRuleCollection AuditRules = (AuthorizationRuleCollection) DirObjSec.GetAuditRules(true,true,typeof(System.Security.Principal.NTAccount));
- foreach (ActiveDirectoryAuditRule Rule in AuditRules)
- {
- PSObject ObjectObj = new PSObject();
- ObjectObj.Members.Add(new PSNoteProperty("Name", CleanString(Name)));
- ObjectObj.Members.Add(new PSNoteProperty("Type", Type));
- ObjectObj.Members.Add(new PSNoteProperty("ObjectTypeName", ADWSClass.GUIDs[Convert.ToString(Rule.ObjectType)]));
- ObjectObj.Members.Add(new PSNoteProperty("InheritedObjectTypeName", ADWSClass.GUIDs[Convert.ToString(Rule.InheritedObjectType)]));
- ObjectObj.Members.Add(new PSNoteProperty("ActiveDirectoryRights", Rule.ActiveDirectoryRights));
- ObjectObj.Members.Add(new PSNoteProperty("IdentityReference", Rule.IdentityReference));
- ObjectObj.Members.Add(new PSNoteProperty("AuditFlags", Rule.AuditFlags));
- ObjectObj.Members.Add(new PSNoteProperty("ObjectFlags", Rule.ObjectFlags));
- ObjectObj.Members.Add(new PSNoteProperty("InheritanceFlags", Rule.InheritanceFlags));
- ObjectObj.Members.Add(new PSNoteProperty("InheritanceType", Rule.InheritanceType));
- ObjectObj.Members.Add(new PSNoteProperty("Inherited", Rule.IsInherited));
- ObjectObj.Members.Add(new PSNoteProperty("PropagationFlags", Rule.PropagationFlags));
- ObjectObj.Members.Add(new PSNoteProperty("ObjectType", Rule.ObjectType));
- ObjectObj.Members.Add(new PSNoteProperty("InheritedObjectType", Rule.InheritedObjectType));
- SACLList.Add( ObjectObj );
- }
- }
- return SACLList.ToArray();
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- //The interface and implmentation class used to handle the results (this implementation just writes the strings to a file)
- interface IResultsHandler
- {
- void processResults(Object[] t);
- Object[] finalise();
- }
- class SimpleResultsHandler : IResultsHandler
- {
- private Object lockObj = new Object();
- private List<Object> processed = new List<Object>();
- public SimpleResultsHandler()
- {
- }
- public void processResults(Object[] results)
- {
- lock (lockObj)
- {
- if (results.Length != 0)
- {
- for (var i = 0; i < results.Length; i++)
- {
- processed.Add((PSObject)results[i]);
- }
- }
- }
- }
- public Object[] finalise()
- {
- return processed.ToArray();
- }
- }
- }
- }
- "@
- $LDAPSource = @"
- // Thanks Dennis Albuquerque for the C# multithreading code
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net;
- using System.Threading;
- using System.DirectoryServices;
- using System.Security.Principal;
- using System.Security.AccessControl;
- using System.Management.Automation;
- namespace ADRecon
- {
- public static class LDAPClass
- {
- private static DateTime Date1;
- private static int PassMaxAge;
- private static int DormantTimeSpan;
- private static Dictionary<String, String> AdGroupDictionary = new Dictionary<String, String>();
- private static String DomainSID;
- private static Dictionary<String, String> AdGPODictionary = new Dictionary<String, String>();
- private static Hashtable GUIDs = new Hashtable();
- private static Dictionary<String, String> AdSIDDictionary = new Dictionary<String, String>();
- private static readonly HashSet<string> Groups = new HashSet<string> ( new String[] {"268435456", "268435457", "536870912", "536870913"} );
- private static readonly HashSet<string> Users = new HashSet<string> ( new String[] { "805306368" } );
- private static readonly HashSet<string> Computers = new HashSet<string> ( new String[] { "805306369" }) ;
- private static readonly HashSet<string> TrustAccounts = new HashSet<string> ( new String[] { "805306370" } );
- [Flags]
- //Values taken from https://support.microsoft.com/en-au/kb/305144
- public enum UACFlags
- {
- SCRIPT = 1, // 0x1
- ACCOUNTDISABLE = 2, // 0x2
- HOMEDIR_REQUIRED = 8, // 0x8
- LOCKOUT = 16, // 0x10
- PASSWD_NOTREQD = 32, // 0x20
- PASSWD_CANT_CHANGE = 64, // 0x40
- ENCRYPTED_TEXT_PASSWORD_ALLOWED = 128, // 0x80
- TEMP_DUPLICATE_ACCOUNT = 256, // 0x100
- NORMAL_ACCOUNT = 512, // 0x200
- INTERDOMAIN_TRUST_ACCOUNT = 2048, // 0x800
- WORKSTATION_TRUST_ACCOUNT = 4096, // 0x1000
- SERVER_TRUST_ACCOUNT = 8192, // 0x2000
- DONT_EXPIRE_PASSWD = 65536, // 0x10000
- MNS_LOGON_ACCOUNT = 131072, // 0x20000
- SMARTCARD_REQUIRED = 262144, // 0x40000
- TRUSTED_FOR_DELEGATION = 524288, // 0x80000
- NOT_DELEGATED = 1048576, // 0x100000
- USE_DES_KEY_ONLY = 2097152, // 0x200000
- DONT_REQUIRE_PREAUTH = 4194304, // 0x400000
- PASSWORD_EXPIRED = 8388608, // 0x800000
- TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 16777216, // 0x1000000
- PARTIAL_SECRETS_ACCOUNT = 67108864 // 0x04000000
- }
- [Flags]
- //Values taken from https://blogs.msdn.microsoft.com/openspecification/2011/05/30/windows-configurations-for-kerberos-supported-encryption-type/
- public enum KerbEncFlags
- {
- ZERO = 0,
- DES_CBC_CRC = 1, // 0x1
- DES_CBC_MD5 = 2, // 0x2
- RC4_HMAC = 4, // 0x4
- AES128_CTS_HMAC_SHA1_96 = 8, // 0x18
- AES256_CTS_HMAC_SHA1_96 = 16 // 0x10
- }
- [Flags]
- //Values taken from https://support.microsoft.com/en-au/kb/305144
- public enum GroupTypeFlags
- {
- GLOBAL_GROUP = 2, // 0x00000002
- DOMAIN_LOCAL_GROUP = 4, // 0x00000004
- LOCAL_GROUP = 4, // 0x00000004
- UNIVERSAL_GROUP = 8, // 0x00000008
- SECURITY_ENABLED = -2147483648 // 0x80000000
- }
- private static readonly Dictionary<String, String> Replacements = new Dictionary<String, String>()
- {
- //{System.Environment.NewLine, ""},
- //{",", ";"},
- {"\"", "'"}
- };
- public static String CleanString(Object StringtoClean)
- {
- // Remove extra spaces and new lines
- String CleanedString = String.Join(" ", ((Convert.ToString(StringtoClean)).Split((string[]) null, StringSplitOptions.RemoveEmptyEntries)));
- foreach (String Replacement in Replacements.Keys)
- {
- CleanedString = CleanedString.Replace(Replacement, Replacements[Replacement]);
- }
- return CleanedString;
- }
- public static int ObjectCount(Object[] ADRObject)
- {
- return ADRObject.Length;
- }
- public static bool LAPSCheck(Object[] AdComputers)
- {
- bool LAPS = false;
- foreach (SearchResult AdComputer in AdComputers)
- {
- if (AdComputer.Properties["ms-mcs-admpwdexpirationtime"].Count == 1)
- {
- LAPS = true;
- return LAPS;
- }
- }
- return LAPS;
- }
- public static Object[] UserParser(Object[] AdUsers, DateTime Date1, int DormantTimeSpan, int PassMaxAge, int numOfThreads)
- {
- LDAPClass.Date1 = Date1;
- LDAPClass.DormantTimeSpan = DormantTimeSpan;
- LDAPClass.PassMaxAge = PassMaxAge;
- Object[] ADRObj = runProcessor(AdUsers, numOfThreads, "Users");
- return ADRObj;
- }
- public static Object[] UserSPNParser(Object[] AdUsers, int numOfThreads)
- {
- Object[] ADRObj = runProcessor(AdUsers, numOfThreads, "UserSPNs");
- return ADRObj;
- }
- public static Object[] GroupParser(Object[] AdGroups, int numOfThreads)
- {
- Object[] ADRObj = runProcessor(AdGroups, numOfThreads, "Groups");
- return ADRObj;
- }
- public static Object[] GroupMemberParser(Object[] AdGroups, Object[] AdGroupMembers, String DomainSID, int numOfThreads)
- {
- LDAPClass.AdGroupDictionary = new Dictionary<String, String>();
- runProcessor(AdGroups, numOfThreads, "GroupsDictionary");
- LDAPClass.DomainSID = DomainSID;
- Object[] ADRObj = runProcessor(AdGroupMembers, numOfThreads, "GroupMembers");
- return ADRObj;
- }
- public static Object[] OUParser(Object[] AdOUs, int numOfThreads)
- {
- Object[] ADRObj = runProcessor(AdOUs, numOfThreads, "OUs");
- return ADRObj;
- }
- public static Object[] GPOParser(Object[] AdGPOs, int numOfThreads)
- {
- Object[] ADRObj = runProcessor(AdGPOs, numOfThreads, "GPOs");
- return ADRObj;
- }
- public static Object[] SOMParser(Object[] AdGPOs, Object[] AdSOMs, int numOfThreads)
- {
- LDAPClass.AdGPODictionary = new Dictionary<String, String>();
- runProcessor(AdGPOs, numOfThreads, "GPOsDictionary");
- Object[] ADRObj = runProcessor(AdSOMs, numOfThreads, "SOMs");
- return ADRObj;
- }
- public static Object[] PrinterParser(Object[] ADPrinters, int numOfThreads)
- {
- Object[] ADRObj = runProcessor(ADPrinters, numOfThreads, "Printers");
- return ADRObj;
- }
- public static Object[] ComputerParser(Object[] AdComputers, DateTime Date1, int DormantTimeSpan, int PassMaxAge, int numOfThreads)
- {
- LDAPClass.Date1 = Date1;
- LDAPClass.DormantTimeSpan = DormantTimeSpan;
- LDAPClass.PassMaxAge = PassMaxAge;
- Object[] ADRObj = runProcessor(AdComputers, numOfThreads, "Computers");
- return ADRObj;
- }
- public static Object[] ComputerSPNParser(Object[] AdComputers, int numOfThreads)
- {
- Object[] ADRObj = runProcessor(AdComputers, numOfThreads, "ComputerSPNs");
- return ADRObj;
- }
- public static Object[] LAPSParser(Object[] AdComputers, int numOfThreads)
- {
- Object[] ADRObj = runProcessor(AdComputers, numOfThreads, "LAPS");
- return ADRObj;
- }
- public static Object[] DACLParser(Object[] ADObjects, Object PSGUIDs, int numOfThreads)
- {
- LDAPClass.AdSIDDictionary = new Dictionary<String, String>();
- runProcessor(ADObjects, numOfThreads, "SIDDictionary");
- LDAPClass.GUIDs = (Hashtable) PSGUIDs;
- Object[] ADRObj = runProcessor(ADObjects, numOfThreads, "DACLs");
- return ADRObj;
- }
- public static Object[] SACLParser(Object[] ADObjects, Object PSGUIDs, int numOfThreads)
- {
- LDAPClass.GUIDs = (Hashtable) PSGUIDs;
- Object[] ADRObj = runProcessor(ADObjects, numOfThreads, "SACLs");
- return ADRObj;
- }
- static Object[] runProcessor(Object[] arrayToProcess, int numOfThreads, string processorType)
- {
- int totalRecords = arrayToProcess.Length;
- IRecordProcessor recordProcessor = recordProcessorFactory(processorType);
- IResultsHandler resultsHandler = new SimpleResultsHandler ();
- int numberOfRecordsPerThread = totalRecords / numOfThreads;
- int remainders = totalRecords % numOfThreads;
- Thread[] threads = new Thread[numOfThreads];
- for (int i = 0; i < numOfThreads; i++)
- {
- int numberOfRecordsToProcess = numberOfRecordsPerThread;
- if (i == (numOfThreads - 1))
- {
- //last thread, do the remaining records
- numberOfRecordsToProcess += remainders;
- }
- //split the full array into chunks to be given to different threads
- Object[] sliceToProcess = new Object[numberOfRecordsToProcess];
- Array.Copy(arrayToProcess, i * numberOfRecordsPerThread, sliceToProcess, 0, numberOfRecordsToProcess);
- ProcessorThread processorThread = new ProcessorThread(i, recordProcessor, resultsHandler, sliceToProcess);
- threads[i] = new Thread(processorThread.processThreadRecords);
- threads[i].Start();
- }
- foreach (Thread t in threads)
- {
- t.Join();
- }
- return resultsHandler.finalise();
- }
- static IRecordProcessor recordProcessorFactory(String name)
- {
- switch (name)
- {
- case "Users":
- return new UserRecordProcessor();
- case "UserSPNs":
- return new UserSPNRecordProcessor();
- case "Groups":
- return new GroupRecordProcessor();
- case "GroupsDictionary":
- return new GroupRecordDictionaryProcessor();
- case "GroupMembers":
- return new GroupMemberRecordProcessor();
- case "OUs":
- return new OURecordProcessor();
- case "GPOs":
- return new GPORecordProcessor();
- case "GPOsDictionary":
- return new GPORecordDictionaryProcessor();
- case "SOMs":
- return new SOMRecordProcessor();
- case "Printers":
- return new PrinterRecordProcessor();
- case "Computers":
- return new ComputerRecordProcessor();
- case "ComputerSPNs":
- return new ComputerSPNRecordProcessor();
- case "LAPS":
- return new LAPSRecordProcessor();
- case "SIDDictionary":
- return new SIDRecordDictionaryProcessor();
- case "DACLs":
- return new DACLRecordProcessor();
- case "SACLs":
- return new SACLRecordProcessor();
- }
- throw new ArgumentException("Invalid processor type " + name);
- }
- class ProcessorThread
- {
- readonly int id;
- readonly IRecordProcessor recordProcessor;
- readonly IResultsHandler resultsHandler;
- readonly Object[] objectsToBeProcessed;
- public ProcessorThread(int id, IRecordProcessor recordProcessor, IResultsHandler resultsHandler, Object[] objectsToBeProcessed)
- {
- this.recordProcessor = recordProcessor;
- this.id = id;
- this.resultsHandler = resultsHandler;
- this.objectsToBeProcessed = objectsToBeProcessed;
- }
- public void processThreadRecords()
- {
- for (int i = 0; i < objectsToBeProcessed.Length; i++)
- {
- Object[] result = recordProcessor.processRecord(objectsToBeProcessed[i]);
- resultsHandler.processResults(result); //this is a thread safe operation
- }
- }
- }
- //The interface and implmentation class used to process a record (this implemmentation just returns a log type string)
- interface IRecordProcessor
- {
- PSObject[] processRecord(Object record);
- }
- class UserRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- SearchResult AdUser = (SearchResult) record;
- bool? Enabled = null;
- bool? CannotChangePassword = null;
- bool? PasswordNeverExpires = null;
- bool? AccountLockedOut = null;
- bool? PasswordExpired = null;
- bool? ReversiblePasswordEncryption = null;
- bool? DelegationPermitted = null;
- bool? SmartcardRequired = null;
- bool? UseDESKeyOnly = null;
- bool? PasswordNotRequired = null;
- bool? TrustedforDelegation = null;
- bool? TrustedtoAuthforDelegation = null;
- bool? DoesNotRequirePreAuth = null;
- bool? KerberosRC4 = null;
- bool? KerberosAES128 = null;
- bool? KerberosAES256 = null;
- String DelegationType = null;
- String DelegationProtocol = null;
- String DelegationServices = null;
- bool MustChangePasswordatLogon = false;
- int? DaysSinceLastLogon = null;
- int? DaysSinceLastPasswordChange = null;
- int? AccountExpirationNumofDays = null;
- bool PasswordNotChangedafterMaxAge = false;
- bool NeverLoggedIn = false;
- bool Dormant = false;
- DateTime? LastLogonDate = null;
- DateTime? PasswordLastSet = null;
- DateTime? AccountExpires = null;
- byte[] ntSecurityDescriptor = null;
- bool DenyEveryone = false;
- bool DenySelf = false;
- String SIDHistory = "";
- // When the user is not allowed to query the UserAccountControl attribute.
- if (AdUser.Properties["useraccountcontrol"].Count != 0)
- {
- var userFlags = (UACFlags) AdUser.Properties["useraccountcontrol"][0];
- Enabled = !((userFlags & UACFlags.ACCOUNTDISABLE) == UACFlags.ACCOUNTDISABLE);
- PasswordNeverExpires = (userFlags & UACFlags.DONT_EXPIRE_PASSWD) == UACFlags.DONT_EXPIRE_PASSWD;
- AccountLockedOut = (userFlags & UACFlags.LOCKOUT) == UACFlags.LOCKOUT;
- DelegationPermitted = !((userFlags & UACFlags.NOT_DELEGATED) == UACFlags.NOT_DELEGATED);
- SmartcardRequired = (userFlags & UACFlags.SMARTCARD_REQUIRED) == UACFlags.SMARTCARD_REQUIRED;
- ReversiblePasswordEncryption = (userFlags & UACFlags.ENCRYPTED_TEXT_PASSWORD_ALLOWED) == UACFlags.ENCRYPTED_TEXT_PASSWORD_ALLOWED;
- UseDESKeyOnly = (userFlags & UACFlags.USE_DES_KEY_ONLY) == UACFlags.USE_DES_KEY_ONLY;
- PasswordNotRequired = (userFlags & UACFlags.PASSWD_NOTREQD) == UACFlags.PASSWD_NOTREQD;
- PasswordExpired = (userFlags & UACFlags.PASSWORD_EXPIRED) == UACFlags.PASSWORD_EXPIRED;
- TrustedforDelegation = (userFlags & UACFlags.TRUSTED_FOR_DELEGATION) == UACFlags.TRUSTED_FOR_DELEGATION;
- TrustedtoAuthforDelegation = (userFlags & UACFlags.TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION) == UACFlags.TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION;
- DoesNotRequirePreAuth = (userFlags & UACFlags.DONT_REQUIRE_PREAUTH) == UACFlags.DONT_REQUIRE_PREAUTH;
- }
- if (AdUser.Properties["msds-supportedencryptiontypes"].Count != 0)
- {
- var userKerbEncFlags = (KerbEncFlags) AdUser.Properties["msds-supportedencryptiontypes"][0];
- if (userKerbEncFlags != KerbEncFlags.ZERO)
- {
- KerberosRC4 = (userKerbEncFlags & KerbEncFlags.RC4_HMAC) == KerbEncFlags.RC4_HMAC;
- KerberosAES128 = (userKerbEncFlags & KerbEncFlags.AES128_CTS_HMAC_SHA1_96) == KerbEncFlags.AES128_CTS_HMAC_SHA1_96;
- KerberosAES256 = (userKerbEncFlags & KerbEncFlags.AES256_CTS_HMAC_SHA1_96) == KerbEncFlags.AES256_CTS_HMAC_SHA1_96;
- }
- }
- // When the user is not allowed to query the ntsecuritydescriptor attribute.
- if (AdUser.Properties["ntsecuritydescriptor"].Count != 0)
- {
- ntSecurityDescriptor = (byte[]) AdUser.Properties["ntsecuritydescriptor"][0];
- }
- else
- {
- DirectoryEntry AdUserEntry = ((SearchResult)record).GetDirectoryEntry();
- ntSecurityDescriptor = (byte[]) AdUserEntry.ObjectSecurity.GetSecurityDescriptorBinaryForm();
- }
- if (ntSecurityDescriptor != null)
- {
- DirectoryObjectSecurity DirObjSec = new ActiveDirectorySecurity();
- DirObjSec.SetSecurityDescriptorBinaryForm(ntSecurityDescriptor);
- AuthorizationRuleCollection AccessRules = (AuthorizationRuleCollection) DirObjSec.GetAccessRules(true,false,typeof(System.Security.Principal.NTAccount));
- foreach (ActiveDirectoryAccessRule Rule in AccessRules)
- {
- if ((Convert.ToString(Rule.ObjectType)).Equals("ab721a53-1e2f-11d0-9819-00aa0040529b"))
- {
- if (Rule.AccessControlType.ToString() == "Deny")
- {
- String ObjectName = Convert.ToString(Rule.IdentityReference);
- if (ObjectName == "Everyone")
- {
- DenyEveryone = true;
- }
- if (ObjectName == "NT AUTHORITY\\SELF")
- {
- DenySelf = true;
- }
- }
- }
- }
- if (DenyEveryone && DenySelf)
- {
- CannotChangePassword = true;
- }
- else
- {
- CannotChangePassword = false;
- }
- }
- if (AdUser.Properties["lastlogontimestamp"].Count != 0)
- {
- LastLogonDate = DateTime.FromFileTime((long)(AdUser.Properties["lastlogontimestamp"][0]));
- DaysSinceLastLogon = Math.Abs((Date1 - (DateTime)LastLogonDate).Days);
- if (DaysSinceLastLogon > DormantTimeSpan)
- {
- Dormant = true;
- }
- }
- else
- {
- NeverLoggedIn = true;
- }
- if (AdUser.Properties["pwdLastSet"].Count != 0)
- {
- if (Convert.ToString(AdUser.Properties["pwdlastset"][0]) == "0")
- {
- if ((bool) PasswordNeverExpires == false)
- {
- MustChangePasswordatLogon = true;
- }
- }
- else
- {
- PasswordLastSet = DateTime.FromFileTime((long)(AdUser.Properties["pwdlastset"][0]));
- DaysSinceLastPasswordChange = Math.Abs((Date1 - (DateTime)PasswordLastSet).Days);
- if (DaysSinceLastPasswordChange > PassMaxAge)
- {
- PasswordNotChangedafterMaxAge = true;
- }
- }
- }
- if ((Int64) AdUser.Properties["accountExpires"][0] != (Int64) 9223372036854775807)
- {
- if ((Int64) AdUser.Properties["accountExpires"][0] != (Int64) 0)
- {
- try
- {
- //https://msdn.microsoft.com/en-us/library/ms675098(v=vs.85).aspx
- AccountExpires = DateTime.FromFileTime((long)(AdUser.Properties["accountExpires"][0]));
- AccountExpirationNumofDays = ((int)((DateTime)AccountExpires - Date1).Days);
- }
- catch //(Exception e)
- {
- // Console.WriteLine("{0} Exception caught.", e);
- }
- }
- }
- if ((bool) TrustedforDelegation)
- {
- DelegationType = "Unconstrained";
- DelegationServices = "Any";
- }
- if (AdUser.Properties["msDS-AllowedToDelegateTo"].Count >= 1)
- {
- DelegationType = "Constrained";
- for (int i = 0; i < AdUser.Properties["msDS-AllowedToDelegateTo"].Count; i++)
- {
- var delegateto = AdUser.Properties["msDS-AllowedToDelegateTo"][i];
- DelegationServices = DelegationServices + "," + Convert.ToString(delegateto);
- }
- DelegationServices = DelegationServices.TrimStart(',');
- }
- if ((bool) TrustedtoAuthforDelegation)
- {
- DelegationProtocol = "Any";
- }
- else if (DelegationType != null)
- {
- DelegationProtocol = "Kerberos";
- }
- if (AdUser.Properties["sidhistory"].Count >= 1)
- {
- string sids = "";
- for (int i = 0; i < AdUser.Properties["sidhistory"].Count; i++)
- {
- var history = AdUser.Properties["sidhistory"][i];
- sids = sids + "," + Convert.ToString(new SecurityIdentifier((byte[])history, 0));
- }
- SIDHistory = sids.TrimStart(',');
- }
- PSObject UserObj = new PSObject();
- UserObj.Members.Add(new PSNoteProperty("UserName", (AdUser.Properties["samaccountname"].Count != 0 ? AdUser.Properties["samaccountname"][0] : "")));
- UserObj.Members.Add(new PSNoteProperty("Name", (AdUser.Properties["name"].Count != 0 ? CleanString(AdUser.Properties["name"][0]) : "")));
- UserObj.Members.Add(new PSNoteProperty("Enabled", Enabled));
- UserObj.Members.Add(new PSNoteProperty("Must Change Password at Logon", MustChangePasswordatLogon));
- UserObj.Members.Add(new PSNoteProperty("Cannot Change Password", CannotChangePassword));
- UserObj.Members.Add(new PSNoteProperty("Password Never Expires", PasswordNeverExpires));
- UserObj.Members.Add(new PSNoteProperty("Reversible Password Encryption", ReversiblePasswordEncryption));
- UserObj.Members.Add(new PSNoteProperty("Smartcard Logon Required", SmartcardRequired));
- UserObj.Members.Add(new PSNoteProperty("Delegation Permitted", DelegationPermitted));
- UserObj.Members.Add(new PSNoteProperty("Kerberos DES Only", UseDESKeyOnly));
- UserObj.Members.Add(new PSNoteProperty("Kerberos RC4", KerberosRC4));
- UserObj.Members.Add(new PSNoteProperty("Kerberos AES-128bit", KerberosAES128));
- UserObj.Members.Add(new PSNoteProperty("Kerberos AES-256bit", KerberosAES256));
- UserObj.Members.Add(new PSNoteProperty("Does Not Require Pre Auth", DoesNotRequirePreAuth));
- UserObj.Members.Add(new PSNoteProperty("Never Logged in", NeverLoggedIn));
- UserObj.Members.Add(new PSNoteProperty("Logon Age (days)", DaysSinceLastLogon));
- UserObj.Members.Add(new PSNoteProperty("Password Age (days)", DaysSinceLastPasswordChange));
- UserObj.Members.Add(new PSNoteProperty("Dormant (> " + DormantTimeSpan + " days)", Dormant));
- UserObj.Members.Add(new PSNoteProperty("Password Age (> " + PassMaxAge + " days)", PasswordNotChangedafterMaxAge));
- UserObj.Members.Add(new PSNoteProperty("Account Locked Out", AccountLockedOut));
- UserObj.Members.Add(new PSNoteProperty("Password Expired", PasswordExpired));
- UserObj.Members.Add(new PSNoteProperty("Password Not Required", PasswordNotRequired));
- UserObj.Members.Add(new PSNoteProperty("Delegation Type", DelegationType));
- UserObj.Members.Add(new PSNoteProperty("Delegation Protocol", DelegationProtocol));
- UserObj.Members.Add(new PSNoteProperty("Delegation Services", DelegationServices));
- UserObj.Members.Add(new PSNoteProperty("Logon Workstations", (AdUser.Properties["userworkstations"].Count != 0 ? AdUser.Properties["userworkstations"][0] : "")));
- UserObj.Members.Add(new PSNoteProperty("AdminCount", (AdUser.Properties["admincount"].Count != 0 ? AdUser.Properties["admincount"][0] : "")));
- UserObj.Members.Add(new PSNoteProperty("Primary GroupID", (AdUser.Properties["primarygroupid"].Count != 0 ? AdUser.Properties["primarygroupid"][0] : "")));
- UserObj.Members.Add(new PSNoteProperty("SID", Convert.ToString(new SecurityIdentifier((byte[])AdUser.Properties["objectSID"][0], 0))));
- UserObj.Members.Add(new PSNoteProperty("SIDHistory", SIDHistory));
- UserObj.Members.Add(new PSNoteProperty("Description", (AdUser.Properties["Description"].Count != 0 ? CleanString(AdUser.Properties["Description"][0]) : "")));
- UserObj.Members.Add(new PSNoteProperty("Title", (AdUser.Properties["Title"].Count != 0 ? CleanString(AdUser.Properties["Title"][0]) : "")));
- UserObj.Members.Add(new PSNoteProperty("Department", (AdUser.Properties["Department"].Count != 0 ? CleanString(AdUser.Properties["Department"][0]) : "")));
- UserObj.Members.Add(new PSNoteProperty("Company", (AdUser.Properties["Company"].Count != 0 ? CleanString(AdUser.Properties["Company"][0]) : "")));
- UserObj.Members.Add(new PSNoteProperty("Manager", (AdUser.Properties["Manager"].Count != 0 ? CleanString(AdUser.Properties["Manager"][0]) : "")));
- UserObj.Members.Add(new PSNoteProperty("Info", (AdUser.Properties["info"].Count != 0 ? CleanString(AdUser.Properties["info"][0]) : "")));
- UserObj.Members.Add(new PSNoteProperty("Last Logon Date", LastLogonDate));
- UserObj.Members.Add(new PSNoteProperty("Password LastSet", PasswordLastSet));
- UserObj.Members.Add(new PSNoteProperty("Account Expiration Date", AccountExpires));
- UserObj.Members.Add(new PSNoteProperty("Account Expiration (days)", AccountExpirationNumofDays));
- UserObj.Members.Add(new PSNoteProperty("Mobile", (AdUser.Properties["mobile"].Count != 0 ? CleanString(AdUser.Properties["mobile"][0]) : "")));
- UserObj.Members.Add(new PSNoteProperty("Email", (AdUser.Properties["mail"].Count != 0 ? CleanString(AdUser.Properties["mail"][0]) : "")));
- UserObj.Members.Add(new PSNoteProperty("HomeDirectory", (AdUser.Properties["homedirectory"].Count != 0 ? AdUser.Properties["homedirectory"][0] : "")));
- UserObj.Members.Add(new PSNoteProperty("ProfilePath", (AdUser.Properties["profilepath"].Count != 0 ? AdUser.Properties["profilepath"][0] : "")));
- UserObj.Members.Add(new PSNoteProperty("ScriptPath", (AdUser.Properties["scriptpath"].Count != 0 ? AdUser.Properties["scriptpath"][0] : "")));
- UserObj.Members.Add(new PSNoteProperty("UserAccountControl", (AdUser.Properties["useraccountcontrol"].Count != 0 ? AdUser.Properties["useraccountcontrol"][0] : "")));
- UserObj.Members.Add(new PSNoteProperty("First Name", (AdUser.Properties["givenName"].Count != 0 ? CleanString(AdUser.Properties["givenName"][0]) : "")));
- UserObj.Members.Add(new PSNoteProperty("Middle Name", (AdUser.Properties["middleName"].Count != 0 ? CleanString(AdUser.Properties["middleName"][0]) : "")));
- UserObj.Members.Add(new PSNoteProperty("Last Name", (AdUser.Properties["sn"].Count != 0 ? CleanString(AdUser.Properties["sn"][0]) : "")));
- UserObj.Members.Add(new PSNoteProperty("Country", (AdUser.Properties["c"].Count != 0 ? CleanString(AdUser.Properties["c"][0]) : "")));
- UserObj.Members.Add(new PSNoteProperty("whenCreated", (AdUser.Properties["whencreated"].Count != 0 ? AdUser.Properties["whencreated"][0] : "")));
- UserObj.Members.Add(new PSNoteProperty("whenChanged", (AdUser.Properties["whenchanged"].Count != 0 ? AdUser.Properties["whenchanged"][0] : "")));
- UserObj.Members.Add(new PSNoteProperty("DistinguishedName", (AdUser.Properties["distinguishedname"].Count != 0 ? CleanString(AdUser.Properties["distinguishedname"][0]) : "")));
- UserObj.Members.Add(new PSNoteProperty("CanonicalName", (AdUser.Properties["canonicalname"].Count != 0 ? AdUser.Properties["canonicalname"][0] : "")));
- return new PSObject[] { UserObj };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class UserSPNRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- SearchResult AdUser = (SearchResult) record;
- List<PSObject> SPNList = new List<PSObject>();
- bool? Enabled = null;
- String Memberof = null;
- DateTime? PasswordLastSet = null;
- if (AdUser.Properties["pwdlastset"].Count != 0)
- {
- if (Convert.ToString(AdUser.Properties["pwdlastset"][0]) != "0")
- {
- PasswordLastSet = DateTime.FromFileTime((long)(AdUser.Properties["pwdLastSet"][0]));
- }
- }
- // When the user is not allowed to query the UserAccountControl attribute.
- if (AdUser.Properties["useraccountcontrol"].Count != 0)
- {
- var userFlags = (UACFlags) AdUser.Properties["useraccountcontrol"][0];
- Enabled = !((userFlags & UACFlags.ACCOUNTDISABLE) == UACFlags.ACCOUNTDISABLE);
- }
- String Description = (AdUser.Properties["Description"].Count != 0 ? CleanString(AdUser.Properties["Description"][0]) : "");
- String PrimaryGroupID = (AdUser.Properties["primarygroupid"].Count != 0 ? Convert.ToString(AdUser.Properties["primarygroupid"][0]) : "");
- if (AdUser.Properties["memberof"].Count != 0)
- {
- foreach (String Member in AdUser.Properties["memberof"])
- {
- Memberof = Memberof + "," + ((Convert.ToString(Member)).Split(',')[0]).Split('=')[1];
- }
- Memberof = Memberof.TrimStart(',');
- }
- foreach (String SPN in AdUser.Properties["serviceprincipalname"])
- {
- String[] SPNArray = SPN.Split('/');
- PSObject UserSPNObj = new PSObject();
- UserSPNObj.Members.Add(new PSNoteProperty("Name", AdUser.Properties["name"][0]));
- UserSPNObj.Members.Add(new PSNoteProperty("Username", AdUser.Properties["samaccountname"][0]));
- UserSPNObj.Members.Add(new PSNoteProperty("Enabled", Enabled));
- UserSPNObj.Members.Add(new PSNoteProperty("Service", SPNArray[0]));
- UserSPNObj.Members.Add(new PSNoteProperty("Host", SPNArray[1]));
- UserSPNObj.Members.Add(new PSNoteProperty("Password Last Set", PasswordLastSet));
- UserSPNObj.Members.Add(new PSNoteProperty("Description", Description));
- UserSPNObj.Members.Add(new PSNoteProperty("Primary GroupID", PrimaryGroupID));
- UserSPNObj.Members.Add(new PSNoteProperty("Memberof", Memberof));
- SPNList.Add( UserSPNObj );
- }
- return SPNList.ToArray();
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class GroupRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- SearchResult AdGroup = (SearchResult) record;
- String ManagedByValue = AdGroup.Properties["managedby"].Count != 0 ? Convert.ToString(AdGroup.Properties["managedby"][0]) : "";
- String ManagedBy = "";
- String GroupCategory = null;
- String GroupScope = null;
- String SIDHistory = "";
- if (AdGroup.Properties["managedBy"].Count != 0)
- {
- ManagedBy = (ManagedByValue.Split(',')[0]).Split('=')[1];
- }
- if (AdGroup.Properties["grouptype"].Count != 0)
- {
- var groupTypeFlags = (GroupTypeFlags) AdGroup.Properties["grouptype"][0];
- GroupCategory = (groupTypeFlags & GroupTypeFlags.SECURITY_ENABLED) == GroupTypeFlags.SECURITY_ENABLED ? "Security" : "Distribution";
- if ((groupTypeFlags & GroupTypeFlags.UNIVERSAL_GROUP) == GroupTypeFlags.UNIVERSAL_GROUP)
- {
- GroupScope = "Universal";
- }
- else if ((groupTypeFlags & GroupTypeFlags.GLOBAL_GROUP) == GroupTypeFlags.GLOBAL_GROUP)
- {
- GroupScope = "Global";
- }
- else if ((groupTypeFlags & GroupTypeFlags.DOMAIN_LOCAL_GROUP) == GroupTypeFlags.DOMAIN_LOCAL_GROUP)
- {
- GroupScope = "DomainLocal";
- }
- }
- if (AdGroup.Properties["sidhistory"].Count >= 1)
- {
- string sids = "";
- for (int i = 0; i < AdGroup.Properties["sidhistory"].Count; i++)
- {
- var history = AdGroup.Properties["sidhistory"][i];
- sids = sids + "," + Convert.ToString(new SecurityIdentifier((byte[])history, 0));
- }
- SIDHistory = sids.TrimStart(',');
- }
- PSObject GroupObj = new PSObject();
- GroupObj.Members.Add(new PSNoteProperty("Name", AdGroup.Properties["samaccountname"][0]));
- GroupObj.Members.Add(new PSNoteProperty("AdminCount", (AdGroup.Properties["admincount"].Count != 0 ? AdGroup.Properties["admincount"][0] : "")));
- GroupObj.Members.Add(new PSNoteProperty("GroupCategory", GroupCategory));
- GroupObj.Members.Add(new PSNoteProperty("GroupScope", GroupScope));
- GroupObj.Members.Add(new PSNoteProperty("ManagedBy", ManagedBy));
- GroupObj.Members.Add(new PSNoteProperty("SID", Convert.ToString(new SecurityIdentifier((byte[])AdGroup.Properties["objectSID"][0], 0))));
- GroupObj.Members.Add(new PSNoteProperty("SIDHistory", SIDHistory));
- GroupObj.Members.Add(new PSNoteProperty("Description", (AdGroup.Properties["Description"].Count != 0 ? CleanString(AdGroup.Properties["Description"][0]) : "")));
- GroupObj.Members.Add(new PSNoteProperty("whenCreated", AdGroup.Properties["whencreated"][0]));
- GroupObj.Members.Add(new PSNoteProperty("whenChanged", AdGroup.Properties["whenchanged"][0]));
- GroupObj.Members.Add(new PSNoteProperty("DistinguishedName", CleanString(AdGroup.Properties["distinguishedname"][0])));
- GroupObj.Members.Add(new PSNoteProperty("CanonicalName", AdGroup.Properties["canonicalname"][0]));
- return new PSObject[] { GroupObj };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class GroupRecordDictionaryProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- SearchResult AdGroup = (SearchResult) record;
- LDAPClass.AdGroupDictionary.Add((Convert.ToString(new SecurityIdentifier((byte[])AdGroup.Properties["objectSID"][0], 0))),(Convert.ToString(AdGroup.Properties["samaccountname"][0])));
- return new PSObject[] { };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class GroupMemberRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- // https://github.com/BloodHoundAD/BloodHound/blob/master/PowerShell/BloodHound.ps1
- SearchResult AdGroup = (SearchResult) record;
- List<PSObject> GroupsList = new List<PSObject>();
- string SamAccountType = AdGroup.Properties["samaccounttype"].Count != 0 ? Convert.ToString(AdGroup.Properties["samaccounttype"][0]) : "";
- string AccountType = "";
- string GroupName = "";
- string MemberUserName = "-";
- string MemberName = "";
- if (Groups.Contains(SamAccountType))
- {
- AccountType = "group";
- MemberName = ((Convert.ToString(AdGroup.Properties["DistinguishedName"][0])).Split(',')[0]).Split('=')[1];
- foreach (String GroupMember in AdGroup.Properties["memberof"])
- {
- GroupName = ((Convert.ToString(GroupMember)).Split(',')[0]).Split('=')[1];
- PSObject GroupMemberObj = new PSObject();
- GroupMemberObj.Members.Add(new PSNoteProperty("Group Name", GroupName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member UserName", MemberUserName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member Name", MemberName));
- GroupMemberObj.Members.Add(new PSNoteProperty("AccountType", AccountType));
- GroupsList.Add( GroupMemberObj );
- }
- }
- if (Users.Contains(SamAccountType))
- {
- AccountType = "user";
- MemberName = ((Convert.ToString(AdGroup.Properties["DistinguishedName"][0])).Split(',')[0]).Split('=')[1];
- MemberUserName = Convert.ToString(AdGroup.Properties["sAMAccountName"][0]);
- String PrimaryGroupID = Convert.ToString(AdGroup.Properties["primaryGroupID"][0]);
- try
- {
- GroupName = LDAPClass.AdGroupDictionary[LDAPClass.DomainSID + "-" + PrimaryGroupID];
- }
- catch //(Exception e)
- {
- //Console.WriteLine("{0} Exception caught.", e);
- GroupName = PrimaryGroupID;
- }
- {
- PSObject GroupMemberObj = new PSObject();
- GroupMemberObj.Members.Add(new PSNoteProperty("Group Name", GroupName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member UserName", MemberUserName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member Name", MemberName));
- GroupMemberObj.Members.Add(new PSNoteProperty("AccountType", AccountType));
- GroupsList.Add( GroupMemberObj );
- }
- foreach (String GroupMember in AdGroup.Properties["memberof"])
- {
- GroupName = ((Convert.ToString(GroupMember)).Split(',')[0]).Split('=')[1];
- PSObject GroupMemberObj = new PSObject();
- GroupMemberObj.Members.Add(new PSNoteProperty("Group Name", GroupName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member UserName", MemberUserName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member Name", MemberName));
- GroupMemberObj.Members.Add(new PSNoteProperty("AccountType", AccountType));
- GroupsList.Add( GroupMemberObj );
- }
- }
- if (Computers.Contains(SamAccountType))
- {
- AccountType = "computer";
- MemberName = ((Convert.ToString(AdGroup.Properties["DistinguishedName"][0])).Split(',')[0]).Split('=')[1];
- MemberUserName = Convert.ToString(AdGroup.Properties["sAMAccountName"][0]);
- String PrimaryGroupID = Convert.ToString(AdGroup.Properties["primaryGroupID"][0]);
- try
- {
- GroupName = LDAPClass.AdGroupDictionary[LDAPClass.DomainSID + "-" + PrimaryGroupID];
- }
- catch //(Exception e)
- {
- //Console.WriteLine("{0} Exception caught.", e);
- GroupName = PrimaryGroupID;
- }
- {
- PSObject GroupMemberObj = new PSObject();
- GroupMemberObj.Members.Add(new PSNoteProperty("Group Name", GroupName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member UserName", MemberUserName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member Name", MemberName));
- GroupMemberObj.Members.Add(new PSNoteProperty("AccountType", AccountType));
- GroupsList.Add( GroupMemberObj );
- }
- foreach (String GroupMember in AdGroup.Properties["memberof"])
- {
- GroupName = ((Convert.ToString(GroupMember)).Split(',')[0]).Split('=')[1];
- PSObject GroupMemberObj = new PSObject();
- GroupMemberObj.Members.Add(new PSNoteProperty("Group Name", GroupName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member UserName", MemberUserName));
- GroupMemberObj.Members.Add(new PSNoteProperty("Member Name", MemberName));
- GroupMemberObj.Members.Add(new PSNoteProperty("AccountType", AccountType));
- GroupsList.Add( GroupMemberObj );
- }
- }
- if (TrustAccounts.Contains(SamAccountType))
- {
- // TO DO
- }
- return GroupsList.ToArray();
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class OURecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- SearchResult AdOU = (SearchResult) record;
- PSObject OUObj = new PSObject();
- OUObj.Members.Add(new PSNoteProperty("Name", AdOU.Properties["name"][0]));
- OUObj.Members.Add(new PSNoteProperty("Depth", ((Convert.ToString(AdOU.Properties["distinguishedname"][0]).Split(new string[] { "OU=" }, StringSplitOptions.None)).Length -1)));
- OUObj.Members.Add(new PSNoteProperty("Description", (AdOU.Properties["description"].Count != 0 ? AdOU.Properties["description"][0] : "")));
- OUObj.Members.Add(new PSNoteProperty("whenCreated", AdOU.Properties["whencreated"][0]));
- OUObj.Members.Add(new PSNoteProperty("whenChanged", AdOU.Properties["whenchanged"][0]));
- OUObj.Members.Add(new PSNoteProperty("DistinguishedName", AdOU.Properties["distinguishedname"][0]));
- return new PSObject[] { OUObj };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class GPORecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- SearchResult AdGPO = (SearchResult) record;
- PSObject GPOObj = new PSObject();
- GPOObj.Members.Add(new PSNoteProperty("DisplayName", CleanString(AdGPO.Properties["displayname"][0])));
- GPOObj.Members.Add(new PSNoteProperty("GUID", CleanString(AdGPO.Properties["name"][0])));
- GPOObj.Members.Add(new PSNoteProperty("whenCreated", AdGPO.Properties["whenCreated"][0]));
- GPOObj.Members.Add(new PSNoteProperty("whenChanged", AdGPO.Properties["whenChanged"][0]));
- GPOObj.Members.Add(new PSNoteProperty("DistinguishedName", CleanString(AdGPO.Properties["distinguishedname"][0])));
- GPOObj.Members.Add(new PSNoteProperty("FilePath", AdGPO.Properties["gpcfilesyspath"][0]));
- return new PSObject[] { GPOObj };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class GPORecordDictionaryProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- SearchResult AdGPO = (SearchResult) record;
- LDAPClass.AdGPODictionary.Add((Convert.ToString(AdGPO.Properties["distinguishedname"][0]).ToUpper()), (Convert.ToString(AdGPO.Properties["displayname"][0])));
- return new PSObject[] { };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class SOMRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- SearchResult AdSOM = (SearchResult) record;
- List<PSObject> SOMsList = new List<PSObject>();
- int Depth = 0;
- bool BlockInheritance = false;
- bool? LinkEnabled = null;
- bool? Enforced = null;
- String gPLink = (AdSOM.Properties["gPLink"].Count != 0 ? Convert.ToString(AdSOM.Properties["gPLink"][0]) : "");
- String GPOName = null;
- Depth = ((Convert.ToString(AdSOM.Properties["distinguishedname"][0]).Split(new string[] { "OU=" }, StringSplitOptions.None)).Length -1);
- if (AdSOM.Properties["gPOptions"].Count != 0)
- {
- if ((int) AdSOM.Properties["gPOptions"][0] == 1)
- {
- BlockInheritance = true;
- }
- }
- var GPLinks = gPLink.Split(']', '[').Where(x => x.StartsWith("LDAP"));
- int Order = (GPLinks.ToArray()).Length;
- if (Order == 0)
- {
- PSObject SOMObj = new PSObject();
- SOMObj.Members.Add(new PSNoteProperty("Name", AdSOM.Properties["name"][0]));
- SOMObj.Members.Add(new PSNoteProperty("Depth", Depth));
- SOMObj.Members.Add(new PSNoteProperty("DistinguishedName", AdSOM.Properties["distinguishedname"][0]));
- SOMObj.Members.Add(new PSNoteProperty("Link Order", null));
- SOMObj.Members.Add(new PSNoteProperty("GPO", GPOName));
- SOMObj.Members.Add(new PSNoteProperty("Enforced", Enforced));
- SOMObj.Members.Add(new PSNoteProperty("Link Enabled", LinkEnabled));
- SOMObj.Members.Add(new PSNoteProperty("BlockInheritance", BlockInheritance));
- SOMObj.Members.Add(new PSNoteProperty("gPLink", gPLink));
- SOMObj.Members.Add(new PSNoteProperty("gPOptions", (AdSOM.Properties["gpoptions"].Count != 0 ? AdSOM.Properties["gpoptions"][0] : "")));
- SOMsList.Add( SOMObj );
- }
- foreach (String link in GPLinks)
- {
- String[] linksplit = link.Split('/', ';');
- if (!Convert.ToBoolean((Convert.ToInt32(linksplit[3]) & 1)))
- {
- LinkEnabled = true;
- }
- else
- {
- LinkEnabled = false;
- }
- if (Convert.ToBoolean((Convert.ToInt32(linksplit[3]) & 2)))
- {
- Enforced = true;
- }
- else
- {
- Enforced = false;
- }
- GPOName = LDAPClass.AdGPODictionary.ContainsKey(linksplit[2].ToUpper()) ? LDAPClass.AdGPODictionary[linksplit[2].ToUpper()] : linksplit[2].Split('=',',')[1];
- PSObject SOMObj = new PSObject();
- SOMObj.Members.Add(new PSNoteProperty("Name", AdSOM.Properties["name"][0]));
- SOMObj.Members.Add(new PSNoteProperty("Depth", Depth));
- SOMObj.Members.Add(new PSNoteProperty("DistinguishedName", AdSOM.Properties["distinguishedname"][0]));
- SOMObj.Members.Add(new PSNoteProperty("Link Order", Order));
- SOMObj.Members.Add(new PSNoteProperty("GPO", GPOName));
- SOMObj.Members.Add(new PSNoteProperty("Enforced", Enforced));
- SOMObj.Members.Add(new PSNoteProperty("Link Enabled", LinkEnabled));
- SOMObj.Members.Add(new PSNoteProperty("BlockInheritance", BlockInheritance));
- SOMObj.Members.Add(new PSNoteProperty("gPLink", gPLink));
- SOMObj.Members.Add(new PSNoteProperty("gPOptions", (AdSOM.Properties["gpoptions"].Count != 0 ? AdSOM.Properties["gpoptions"][0] : "")));
- SOMsList.Add( SOMObj );
- Order--;
- }
- return SOMsList.ToArray();
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class PrinterRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- SearchResult AdPrinter = (SearchResult) record;
- PSObject PrinterObj = new PSObject();
- PrinterObj.Members.Add(new PSNoteProperty("Name", AdPrinter.Properties["Name"][0]));
- PrinterObj.Members.Add(new PSNoteProperty("ServerName", AdPrinter.Properties["serverName"][0]));
- PrinterObj.Members.Add(new PSNoteProperty("ShareName", AdPrinter.Properties["printShareName"][0]));
- PrinterObj.Members.Add(new PSNoteProperty("DriverName", AdPrinter.Properties["driverName"][0]));
- PrinterObj.Members.Add(new PSNoteProperty("DriverVersion", AdPrinter.Properties["driverVersion"][0]));
- PrinterObj.Members.Add(new PSNoteProperty("PortName", AdPrinter.Properties["portName"][0]));
- PrinterObj.Members.Add(new PSNoteProperty("URL", AdPrinter.Properties["url"][0]));
- PrinterObj.Members.Add(new PSNoteProperty("whenCreated", AdPrinter.Properties["whenCreated"][0]));
- PrinterObj.Members.Add(new PSNoteProperty("whenChanged", AdPrinter.Properties["whenChanged"][0]));
- return new PSObject[] { PrinterObj };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class ComputerRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- SearchResult AdComputer = (SearchResult) record;
- bool Dormant = false;
- bool? Enabled = null;
- bool PasswordNotChangedafterMaxAge = false;
- bool? TrustedforDelegation = null;
- bool? TrustedtoAuthforDelegation = null;
- String DelegationType = null;
- String DelegationProtocol = null;
- String DelegationServices = null;
- String StrIPAddress = null;
- int? DaysSinceLastLogon = null;
- int? DaysSinceLastPasswordChange = null;
- DateTime? LastLogonDate = null;
- DateTime? PasswordLastSet = null;
- if (AdComputer.Properties["dnshostname"].Count != 0)
- {
- try
- {
- StrIPAddress = Convert.ToString(Dns.GetHostEntry(Convert.ToString(AdComputer.Properties["dnshostname"][0])).AddressList[0]);
- }
- catch
- {
- StrIPAddress = null;
- }
- }
- // When the user is not allowed to query the UserAccountControl attribute.
- if (AdComputer.Properties["useraccountcontrol"].Count != 0)
- {
- var userFlags = (UACFlags) AdComputer.Properties["useraccountcontrol"][0];
- Enabled = !((userFlags & UACFlags.ACCOUNTDISABLE) == UACFlags.ACCOUNTDISABLE);
- TrustedforDelegation = (userFlags & UACFlags.TRUSTED_FOR_DELEGATION) == UACFlags.TRUSTED_FOR_DELEGATION;
- TrustedtoAuthforDelegation = (userFlags & UACFlags.TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION) == UACFlags.TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION;
- }
- if (AdComputer.Properties["lastlogontimestamp"].Count != 0)
- {
- LastLogonDate = DateTime.FromFileTime((long)(AdComputer.Properties["lastlogontimestamp"][0]));
- DaysSinceLastLogon = Math.Abs((Date1 - (DateTime)LastLogonDate).Days);
- if (DaysSinceLastLogon > DormantTimeSpan)
- {
- Dormant = true;
- }
- }
- if (AdComputer.Properties["pwdlastset"].Count != 0)
- {
- PasswordLastSet = DateTime.FromFileTime((long)(AdComputer.Properties["pwdlastset"][0]));
- DaysSinceLastPasswordChange = Math.Abs((Date1 - (DateTime)PasswordLastSet).Days);
- if (DaysSinceLastPasswordChange > PassMaxAge)
- {
- PasswordNotChangedafterMaxAge = true;
- }
- }
- if ( ((bool) TrustedforDelegation) && ((int) AdComputer.Properties["primarygroupid"][0] == 515) )
- {
- DelegationType = "Unconstrained";
- DelegationServices = "Any";
- }
- if (AdComputer.Properties["msDS-AllowedToDelegateTo"].Count >= 1)
- {
- DelegationType = "Constrained";
- for (int i = 0; i < AdComputer.Properties["msDS-AllowedToDelegateTo"].Count; i++)
- {
- var delegateto = AdComputer.Properties["msDS-AllowedToDelegateTo"][i];
- DelegationServices = DelegationServices + "," + Convert.ToString(delegateto);
- }
- DelegationServices = DelegationServices.TrimStart(',');
- }
- if ((bool) TrustedtoAuthforDelegation)
- {
- DelegationProtocol = "Any";
- }
- else if (DelegationType != null)
- {
- DelegationProtocol = "Kerberos";
- }
- string SIDHistory = "";
- if (AdComputer.Properties["sidhistory"].Count >= 1)
- {
- string sids = "";
- for (int i = 0; i < AdComputer.Properties["sidhistory"].Count; i++)
- {
- var history = AdComputer.Properties["sidhistory"][i];
- sids = sids + "," + Convert.ToString(new SecurityIdentifier((byte[])history, 0));
- }
- SIDHistory = sids.TrimStart(',');
- }
- String OperatingSystem = CleanString((AdComputer.Properties["operatingsystem"].Count != 0 ? AdComputer.Properties["operatingsystem"][0] : "-") + " " + (AdComputer.Properties["operatingsystemhotfix"].Count != 0 ? AdComputer.Properties["operatingsystemhotfix"][0] : " ") + " " + (AdComputer.Properties["operatingsystemservicepack"].Count != 0 ? AdComputer.Properties["operatingsystemservicepack"][0] : " ") + " " + (AdComputer.Properties["operatingsystemversion"].Count != 0 ? AdComputer.Properties["operatingsystemversion"][0] : " "));
- PSObject ComputerObj = new PSObject();
- ComputerObj.Members.Add(new PSNoteProperty("Name", (AdComputer.Properties["name"].Count != 0 ? AdComputer.Properties["name"][0] : "")));
- ComputerObj.Members.Add(new PSNoteProperty("DNSHostName", (AdComputer.Properties["dnshostname"].Count != 0 ? AdComputer.Properties["dnshostname"][0] : "")));
- ComputerObj.Members.Add(new PSNoteProperty("Enabled", Enabled));
- ComputerObj.Members.Add(new PSNoteProperty("IPv4Address", StrIPAddress));
- ComputerObj.Members.Add(new PSNoteProperty("Operating System", OperatingSystem));
- ComputerObj.Members.Add(new PSNoteProperty("Logon Age (days)", DaysSinceLastLogon));
- ComputerObj.Members.Add(new PSNoteProperty("Password Age (days)", DaysSinceLastPasswordChange));
- ComputerObj.Members.Add(new PSNoteProperty("Dormant (> " + DormantTimeSpan + " days)", Dormant));
- ComputerObj.Members.Add(new PSNoteProperty("Password Age (> " + PassMaxAge + " days)", PasswordNotChangedafterMaxAge));
- ComputerObj.Members.Add(new PSNoteProperty("Delegation Type", DelegationType));
- ComputerObj.Members.Add(new PSNoteProperty("Delegation Protocol", DelegationProtocol));
- ComputerObj.Members.Add(new PSNoteProperty("Delegation Services", DelegationServices));
- ComputerObj.Members.Add(new PSNoteProperty("UserName", (AdComputer.Properties["samaccountname"].Count != 0 ? AdComputer.Properties["samaccountname"][0] : "")));
- ComputerObj.Members.Add(new PSNoteProperty("Primary Group ID", (AdComputer.Properties["primarygroupid"].Count != 0 ? AdComputer.Properties["primarygroupid"][0] : "")));
- ComputerObj.Members.Add(new PSNoteProperty("SID", Convert.ToString(new SecurityIdentifier((byte[])AdComputer.Properties["objectSID"][0], 0))));
- ComputerObj.Members.Add(new PSNoteProperty("SIDHistory", SIDHistory));
- ComputerObj.Members.Add(new PSNoteProperty("Description", (AdComputer.Properties["Description"].Count != 0 ? AdComputer.Properties["Description"][0] : "")));
- ComputerObj.Members.Add(new PSNoteProperty("ms-ds-CreatorSid", (AdComputer.Properties["ms-ds-CreatorSid"].Count != 0 ? Convert.ToString(new SecurityIdentifier((byte[])AdComputer.Properties["ms-ds-CreatorSid"][0], 0)) : "")));
- ComputerObj.Members.Add(new PSNoteProperty("Last Logon Date", LastLogonDate));
- ComputerObj.Members.Add(new PSNoteProperty("Password LastSet", PasswordLastSet));
- ComputerObj.Members.Add(new PSNoteProperty("UserAccountControl", (AdComputer.Properties["useraccountcontrol"].Count != 0 ? AdComputer.Properties["useraccountcontrol"][0] : "")));
- ComputerObj.Members.Add(new PSNoteProperty("whenCreated", AdComputer.Properties["whencreated"][0]));
- ComputerObj.Members.Add(new PSNoteProperty("whenChanged", AdComputer.Properties["whenchanged"][0]));
- ComputerObj.Members.Add(new PSNoteProperty("Distinguished Name", AdComputer.Properties["distinguishedname"][0]));
- return new PSObject[] { ComputerObj };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class ComputerSPNRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- SearchResult AdComputer = (SearchResult) record;
- List<PSObject> SPNList = new List<PSObject>();
- foreach (String SPN in AdComputer.Properties["serviceprincipalname"])
- {
- String[] SPNArray = SPN.Split('/');
- bool flag = true;
- foreach (PSObject Obj in SPNList)
- {
- if ( (String) Obj.Members["Service"].Value == SPNArray[0] )
- {
- Obj.Members["Host"].Value = String.Join(",", (Obj.Members["Host"].Value + "," + SPNArray[1]).Split(',').Distinct().ToArray());
- flag = false;
- }
- }
- if (flag)
- {
- PSObject ComputerSPNObj = new PSObject();
- ComputerSPNObj.Members.Add(new PSNoteProperty("Name", AdComputer.Properties["name"][0]));
- ComputerSPNObj.Members.Add(new PSNoteProperty("Service", SPNArray[0]));
- ComputerSPNObj.Members.Add(new PSNoteProperty("Host", SPNArray[1]));
- SPNList.Add( ComputerSPNObj );
- }
- }
- return SPNList.ToArray();
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class LAPSRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- SearchResult AdComputer = (SearchResult) record;
- bool PasswordStored = false;
- DateTime? CurrentExpiration = null;
- if (AdComputer.Properties["ms-mcs-admpwdexpirationtime"].Count != 0)
- {
- CurrentExpiration = DateTime.FromFileTime((long)(AdComputer.Properties["ms-mcs-admpwdexpirationtime"][0]));
- PasswordStored = true;
- }
- PSObject LAPSObj = new PSObject();
- LAPSObj.Members.Add(new PSNoteProperty("Hostname", (AdComputer.Properties["dnshostname"].Count != 0 ? AdComputer.Properties["dnshostname"][0] : AdComputer.Properties["cn"][0] )));
- LAPSObj.Members.Add(new PSNoteProperty("Stored", PasswordStored));
- LAPSObj.Members.Add(new PSNoteProperty("Readable", (AdComputer.Properties["ms-mcs-admpwd"].Count != 0 ? true : false)));
- LAPSObj.Members.Add(new PSNoteProperty("Password", (AdComputer.Properties["ms-mcs-admpwd"].Count != 0 ? AdComputer.Properties["ms-mcs-admpwd"][0] : null)));
- LAPSObj.Members.Add(new PSNoteProperty("Expiration", CurrentExpiration));
- return new PSObject[] { LAPSObj };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class SIDRecordDictionaryProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- SearchResult AdObject = (SearchResult) record;
- switch (Convert.ToString(AdObject.Properties["objectclass"][AdObject.Properties["objectclass"].Count-1]))
- {
- case "user":
- case "computer":
- case "group":
- LDAPClass.AdSIDDictionary.Add(Convert.ToString(new SecurityIdentifier((byte[])AdObject.Properties["objectSID"][0], 0)), (Convert.ToString(AdObject.Properties["name"][0])));
- break;
- }
- return new PSObject[] { };
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class DACLRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- SearchResult AdObject = (SearchResult) record;
- byte[] ntSecurityDescriptor = null;
- String Name = null;
- String Type = null;
- List<PSObject> DACLList = new List<PSObject>();
- Name = Convert.ToString(AdObject.Properties["name"][0]);
- switch (Convert.ToString(AdObject.Properties["objectclass"][AdObject.Properties["objectclass"].Count-1]))
- {
- case "user":
- Type = "User";
- break;
- case "computer":
- Type = "Computer";
- break;
- case "group":
- Type = "Group";
- break;
- case "container":
- Type = "Container";
- break;
- case "groupPolicyContainer":
- Type = "GPO";
- Name = Convert.ToString(AdObject.Properties["displayname"][0]);
- break;
- case "organizationalUnit":
- Type = "OU";
- break;
- case "domainDNS":
- Type = "Domain";
- break;
- default:
- Type = Convert.ToString(AdObject.Properties["objectclass"][AdObject.Properties["objectclass"].Count-1]);
- break;
- }
- // When the user is not allowed to query the ntsecuritydescriptor attribute.
- if (AdObject.Properties["ntsecuritydescriptor"].Count != 0)
- {
- ntSecurityDescriptor = (byte[]) AdObject.Properties["ntsecuritydescriptor"][0];
- }
- else
- {
- DirectoryEntry AdObjectEntry = ((SearchResult)record).GetDirectoryEntry();
- ntSecurityDescriptor = (byte[]) AdObjectEntry.ObjectSecurity.GetSecurityDescriptorBinaryForm();
- }
- if (ntSecurityDescriptor != null)
- {
- DirectoryObjectSecurity DirObjSec = new ActiveDirectorySecurity();
- DirObjSec.SetSecurityDescriptorBinaryForm(ntSecurityDescriptor);
- AuthorizationRuleCollection AccessRules = (AuthorizationRuleCollection) DirObjSec.GetAccessRules(true,true,typeof(System.Security.Principal.NTAccount));
- foreach (ActiveDirectoryAccessRule Rule in AccessRules)
- {
- String IdentityReference = Convert.ToString(Rule.IdentityReference);
- String Owner = Convert.ToString(DirObjSec.GetOwner(typeof(System.Security.Principal.SecurityIdentifier)));
- PSObject ObjectObj = new PSObject();
- ObjectObj.Members.Add(new PSNoteProperty("Name", CleanString(Name)));
- ObjectObj.Members.Add(new PSNoteProperty("Type", Type));
- ObjectObj.Members.Add(new PSNoteProperty("ObjectTypeName", LDAPClass.GUIDs[Convert.ToString(Rule.ObjectType)]));
- ObjectObj.Members.Add(new PSNoteProperty("InheritedObjectTypeName", LDAPClass.GUIDs[Convert.ToString(Rule.InheritedObjectType)]));
- ObjectObj.Members.Add(new PSNoteProperty("ActiveDirectoryRights", Rule.ActiveDirectoryRights));
- ObjectObj.Members.Add(new PSNoteProperty("AccessControlType", Rule.AccessControlType));
- ObjectObj.Members.Add(new PSNoteProperty("IdentityReferenceName", LDAPClass.AdSIDDictionary.ContainsKey(IdentityReference) ? LDAPClass.AdSIDDictionary[IdentityReference] : IdentityReference));
- ObjectObj.Members.Add(new PSNoteProperty("OwnerName", LDAPClass.AdSIDDictionary.ContainsKey(Owner) ? LDAPClass.AdSIDDictionary[Owner] : Owner));
- ObjectObj.Members.Add(new PSNoteProperty("Inherited", Rule.IsInherited));
- ObjectObj.Members.Add(new PSNoteProperty("ObjectFlags", Rule.ObjectFlags));
- ObjectObj.Members.Add(new PSNoteProperty("InheritanceFlags", Rule.InheritanceFlags));
- ObjectObj.Members.Add(new PSNoteProperty("InheritanceType", Rule.InheritanceType));
- ObjectObj.Members.Add(new PSNoteProperty("PropagationFlags", Rule.PropagationFlags));
- ObjectObj.Members.Add(new PSNoteProperty("ObjectType", Rule.ObjectType));
- ObjectObj.Members.Add(new PSNoteProperty("InheritedObjectType", Rule.InheritedObjectType));
- ObjectObj.Members.Add(new PSNoteProperty("IdentityReference", Rule.IdentityReference));
- ObjectObj.Members.Add(new PSNoteProperty("Owner", Owner));
- ObjectObj.Members.Add(new PSNoteProperty("DistinguishedName", AdObject.Properties["distinguishedname"][0]));
- DACLList.Add( ObjectObj );
- }
- }
- return DACLList.ToArray();
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- class SACLRecordProcessor : IRecordProcessor
- {
- public PSObject[] processRecord(Object record)
- {
- try
- {
- SearchResult AdObject = (SearchResult) record;
- byte[] ntSecurityDescriptor = null;
- String Name = null;
- String Type = null;
- List<PSObject> SACLList = new List<PSObject>();
- Name = Convert.ToString(AdObject.Properties["name"][0]);
- switch (Convert.ToString(AdObject.Properties["objectclass"][AdObject.Properties["objectclass"].Count-1]))
- {
- case "user":
- Type = "User";
- break;
- case "computer":
- Type = "Computer";
- break;
- case "group":
- Type = "Group";
- break;
- case "container":
- Type = "Container";
- break;
- case "groupPolicyContainer":
- Type = "GPO";
- Name = Convert.ToString(AdObject.Properties["displayname"][0]);
- break;
- case "organizationalUnit":
- Type = "OU";
- break;
- case "domainDNS":
- Type = "Domain";
- break;
- default:
- Type = Convert.ToString(AdObject.Properties["objectclass"][AdObject.Properties["objectclass"].Count-1]);
- break;
- }
- // When the user is not allowed to query the ntsecuritydescriptor attribute.
- if (AdObject.Properties["ntsecuritydescriptor"].Count != 0)
- {
- ntSecurityDescriptor = (byte[]) AdObject.Properties["ntsecuritydescriptor"][0];
- }
- else
- {
- DirectoryEntry AdObjectEntry = ((SearchResult)record).GetDirectoryEntry();
- ntSecurityDescriptor = (byte[]) AdObjectEntry.ObjectSecurity.GetSecurityDescriptorBinaryForm();
- }
- if (ntSecurityDescriptor != null)
- {
- DirectoryObjectSecurity DirObjSec = new ActiveDirectorySecurity();
- DirObjSec.SetSecurityDescriptorBinaryForm(ntSecurityDescriptor);
- AuthorizationRuleCollection AuditRules = (AuthorizationRuleCollection) DirObjSec.GetAuditRules(true,true,typeof(System.Security.Principal.NTAccount));
- foreach (ActiveDirectoryAuditRule Rule in AuditRules)
- {
- String IdentityReference = Convert.ToString(Rule.IdentityReference);
- PSObject ObjectObj = new PSObject();
- ObjectObj.Members.Add(new PSNoteProperty("Name", CleanString(Name)));
- ObjectObj.Members.Add(new PSNoteProperty("Type", Type));
- ObjectObj.Members.Add(new PSNoteProperty("ObjectTypeName", LDAPClass.GUIDs[Convert.ToString(Rule.ObjectType)]));
- ObjectObj.Members.Add(new PSNoteProperty("InheritedObjectTypeName", LDAPClass.GUIDs[Convert.ToString(Rule.InheritedObjectType)]));
- ObjectObj.Members.Add(new PSNoteProperty("ActiveDirectoryRights", Rule.ActiveDirectoryRights));
- ObjectObj.Members.Add(new PSNoteProperty("IdentityReferenceName", LDAPClass.AdSIDDictionary.ContainsKey(IdentityReference) ? LDAPClass.AdSIDDictionary[IdentityReference] : IdentityReference));
- ObjectObj.Members.Add(new PSNoteProperty("AuditFlags", Rule.AuditFlags));
- ObjectObj.Members.Add(new PSNoteProperty("ObjectFlags", Rule.ObjectFlags));
- ObjectObj.Members.Add(new PSNoteProperty("InheritanceFlags", Rule.InheritanceFlags));
- ObjectObj.Members.Add(new PSNoteProperty("InheritanceType", Rule.InheritanceType));
- ObjectObj.Members.Add(new PSNoteProperty("Inherited", Rule.IsInherited));
- ObjectObj.Members.Add(new PSNoteProperty("PropagationFlags", Rule.PropagationFlags));
- ObjectObj.Members.Add(new PSNoteProperty("ObjectType", Rule.ObjectType));
- ObjectObj.Members.Add(new PSNoteProperty("InheritedObjectType", Rule.InheritedObjectType));
- ObjectObj.Members.Add(new PSNoteProperty("IdentityReference", Rule.IdentityReference));
- SACLList.Add( ObjectObj );
- }
- }
- return SACLList.ToArray();
- }
- catch (Exception e)
- {
- Console.WriteLine("{0} Exception caught.", e);
- return new PSObject[] { };
- }
- }
- }
- //The interface and implmentation class used to handle the results (this implementation just writes the strings to a file)
- interface IResultsHandler
- {
- void processResults(Object[] t);
- Object[] finalise();
- }
- class SimpleResultsHandler : IResultsHandler
- {
- private Object lockObj = new Object();
- private List<Object> processed = new List<Object>();
- public SimpleResultsHandler()
- {
- }
- public void processResults(Object[] results)
- {
- lock (lockObj)
- {
- if (results.Length != 0)
- {
- for (var i = 0; i < results.Length; i++)
- {
- processed.Add((PSObject)results[i]);
- }
- }
- }
- }
- public Object[] finalise()
- {
- return processed.ToArray();
- }
- }
- }
- }
- "@
- #Add-Type -TypeDefinition $Source -ReferencedAssemblies ([System.String[]]@(([system.reflection.assembly]::LoadWithPartialName("Microsoft.ActiveDirectory.Management")).Location,([system.reflection.assembly]::LoadWithPartialName("System.DirectoryServices")).Location))
- # modified version from https://github.com/vletoux/SmbScanner/blob/master/smbscanner.ps1
- $PingCastleSMBScannerSource = @"
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.IO;
- using System.Net;
- using System.Net.Sockets;
- using System.Text;
- using System.Runtime.InteropServices;
- using System.Management.Automation;
- namespace ADRecon
- {
- public class PingCastleScannersSMBScanner
- {
- [StructLayout(LayoutKind.Explicit)]
- struct SMB_Header {
- [FieldOffset(0)]
- public UInt32 Protocol;
- [FieldOffset(4)]
- public byte Command;
- [FieldOffset(5)]
- public int Status;
- [FieldOffset(9)]
- public byte Flags;
- [FieldOffset(10)]
- public UInt16 Flags2;
- [FieldOffset(12)]
- public UInt16 PIDHigh;
- [FieldOffset(14)]
- public UInt64 SecurityFeatures;
- [FieldOffset(22)]
- public UInt16 Reserved;
- [FieldOffset(24)]
- public UInt16 TID;
- [FieldOffset(26)]
- public UInt16 PIDLow;
- [FieldOffset(28)]
- public UInt16 UID;
- [FieldOffset(30)]
- public UInt16 MID;
- };
- // https://msdn.microsoft.com/en-us/library/cc246529.aspx
- [StructLayout(LayoutKind.Explicit)]
- struct SMB2_Header {
- [FieldOffset(0)]
- public UInt32 ProtocolId;
- [FieldOffset(4)]
- public UInt16 StructureSize;
- [FieldOffset(6)]
- public UInt16 CreditCharge;
- [FieldOffset(8)]
- public UInt32 Status; // to do SMB3
- [FieldOffset(12)]
- public UInt16 Command;
- [FieldOffset(14)]
- public UInt16 CreditRequest_Response;
- [FieldOffset(16)]
- public UInt32 Flags;
- [FieldOffset(20)]
- public UInt32 NextCommand;
- [FieldOffset(24)]
- public UInt64 MessageId;
- [FieldOffset(32)]
- public UInt32 Reserved;
- [FieldOffset(36)]
- public UInt32 TreeId;
- [FieldOffset(40)]
- public UInt64 SessionId;
- [FieldOffset(48)]
- public UInt64 Signature1;
- [FieldOffset(56)]
- public UInt64 Signature2;
- }
- [StructLayout(LayoutKind.Explicit)]
- struct SMB2_NegotiateRequest
- {
- [FieldOffset(0)]
- public UInt16 StructureSize;
- [FieldOffset(2)]
- public UInt16 DialectCount;
- [FieldOffset(4)]
- public UInt16 SecurityMode;
- [FieldOffset(6)]
- public UInt16 Reserved;
- [FieldOffset(8)]
- public UInt32 Capabilities;
- [FieldOffset(12)]
- public Guid ClientGuid;
- [FieldOffset(28)]
- public UInt64 ClientStartTime;
- [FieldOffset(36)]
- public UInt16 DialectToTest;
- }
- const int SMB_COM_NEGOTIATE = 0x72;
- const int SMB2_NEGOTIATE = 0;
- const int SMB_FLAGS_CASE_INSENSITIVE = 0x08;
- const int SMB_FLAGS_CANONICALIZED_PATHS = 0x10;
- const int SMB_FLAGS2_LONG_NAMES = 0x0001;
- const int SMB_FLAGS2_EAS = 0x0002;
- const int SMB_FLAGS2_SECURITY_SIGNATURE_REQUIRED = 0x0010 ;
- const int SMB_FLAGS2_IS_LONG_NAME = 0x0040;
- const int SMB_FLAGS2_ESS = 0x0800;
- const int SMB_FLAGS2_NT_STATUS = 0x4000;
- const int SMB_FLAGS2_UNICODE = 0x8000;
- const int SMB_DB_FORMAT_DIALECT = 0x02;
- static byte[] GenerateSmbHeaderFromCommand(byte command)
- {
- SMB_Header header = new SMB_Header();
- header.Protocol = 0x424D53FF;
- header.Command = command;
- header.Status = 0;
- header.Flags = SMB_FLAGS_CASE_INSENSITIVE | SMB_FLAGS_CANONICALIZED_PATHS;
- header.Flags2 = SMB_FLAGS2_LONG_NAMES | SMB_FLAGS2_EAS | SMB_FLAGS2_SECURITY_SIGNATURE_REQUIRED | SMB_FLAGS2_IS_LONG_NAME | SMB_FLAGS2_ESS | SMB_FLAGS2_NT_STATUS | SMB_FLAGS2_UNICODE;
- header.PIDHigh = 0;
- header.SecurityFeatures = 0;
- header.Reserved = 0;
- header.TID = 0xffff;
- header.PIDLow = 0xFEFF;
- header.UID = 0;
- header.MID = 0;
- return getBytes(header);
- }
- static byte[] GenerateSmb2HeaderFromCommand(byte command)
- {
- SMB2_Header header = new SMB2_Header();
- header.ProtocolId = 0x424D53FE;
- header.Command = command;
- header.StructureSize = 64;
- header.Command = command;
- header.MessageId = 0;
- header.Reserved = 0xFEFF;
- return getBytes(header);
- }
- static byte[] getBytes(object structure)
- {
- int size = Marshal.SizeOf(structure);
- byte[] arr = new byte[size];
- IntPtr ptr = Marshal.AllocHGlobal(size);
- Marshal.StructureToPtr(structure, ptr, true);
- Marshal.Copy(ptr, arr, 0, size);
- Marshal.FreeHGlobal(ptr);
- return arr;
- }
- static byte[] getDialect(string dialect)
- {
- byte[] dialectBytes = Encoding.ASCII.GetBytes(dialect);
- byte[] output = new byte[dialectBytes.Length + 2];
- output[0] = 2;
- output[output.Length - 1] = 0;
- Array.Copy(dialectBytes, 0, output, 1, dialectBytes.Length);
- return output;
- }
- static byte[] GetNegotiateMessage(byte[] dialect)
- {
- byte[] output = new byte[dialect.Length + 3];
- output[0] = 0;
- output[1] = (byte) dialect.Length;
- output[2] = 0;
- Array.Copy(dialect, 0, output, 3, dialect.Length);
- return output;
- }
- // MS-SMB2 2.2.3 SMB2 NEGOTIATE Request
- static byte[] GetNegotiateMessageSmbv2(int DialectToTest)
- {
- SMB2_NegotiateRequest request = new SMB2_NegotiateRequest();
- request.StructureSize = 36;
- request.DialectCount = 1;
- request.SecurityMode = 1; // signing enabled
- request.ClientGuid = Guid.NewGuid();
- request.DialectToTest = (UInt16) DialectToTest;
- return getBytes(request);
- }
- static byte[] GetNegotiatePacket(byte[] header, byte[] smbPacket)
- {
- byte[] output = new byte[smbPacket.Length + header.Length + 4];
- output[0] = 0;
- output[1] = 0;
- output[2] = 0;
- output[3] = (byte)(smbPacket.Length + header.Length);
- Array.Copy(header, 0, output, 4, header.Length);
- Array.Copy(smbPacket, 0, output, 4 + header.Length, smbPacket.Length);
- return output;
- }
- public static bool DoesServerSupportDialect(string server, string dialect)
- {
- Trace.WriteLine("Checking " + server + " for SMBV1 dialect " + dialect);
- TcpClient client = new TcpClient();
- try
- {
- client.Connect(server, 445);
- }
- catch (Exception)
- {
- throw new Exception("port 445 is closed on " + server);
- }
- try
- {
- NetworkStream stream = client.GetStream();
- byte[] header = GenerateSmbHeaderFromCommand(SMB_COM_NEGOTIATE);
- byte[] dialectEncoding = getDialect(dialect);
- byte[] negotiatemessage = GetNegotiateMessage(dialectEncoding);
- byte[] packet = GetNegotiatePacket(header, negotiatemessage);
- stream.Write(packet, 0, packet.Length);
- stream.Flush();
- byte[] netbios = new byte[4];
- if (stream.Read(netbios, 0, netbios.Length) != netbios.Length)
- {
- return false;
- }
- byte[] smbHeader = new byte[Marshal.SizeOf(typeof(SMB_Header))];
- if (stream.Read(smbHeader, 0, smbHeader.Length) != smbHeader.Length)
- {
- return false;
- }
- byte[] negotiateresponse = new byte[3];
- if (stream.Read(negotiateresponse, 0, negotiateresponse.Length) != negotiateresponse.Length)
- {
- return false;
- }
- if (negotiateresponse[1] == 0 && negotiateresponse[2] == 0)
- {
- Trace.WriteLine("Checking " + server + " for SMBV1 dialect " + dialect + " = Supported");
- return true;
- }
- Trace.WriteLine("Checking " + server + " for SMBV1 dialect " + dialect + " = Not supported");
- return false;
- }
- catch (Exception)
- {
- throw new ApplicationException("Smb1 is not supported on " + server);
- }
- }
- public static bool DoesServerSupportDialectWithSmbV2(string server, int dialect, bool checkSMBSigning)
- {
- Trace.WriteLine("Checking " + server + " for SMBV2 dialect 0x" + dialect.ToString("X2"));
- TcpClient client = new TcpClient();
- try
- {
- client.Connect(server, 445);
- }
- catch (Exception)
- {
- throw new Exception("port 445 is closed on " + server);
- }
- try
- {
- NetworkStream stream = client.GetStream();
- byte[] header = GenerateSmb2HeaderFromCommand(SMB2_NEGOTIATE);
- byte[] negotiatemessage = GetNegotiateMessageSmbv2(dialect);
- byte[] packet = GetNegotiatePacket(header, negotiatemessage);
- stream.Write(packet, 0, packet.Length);
- stream.Flush();
- byte[] netbios = new byte[4];
- if( stream.Read(netbios, 0, netbios.Length) != netbios.Length)
- {
- return false;
- }
- byte[] smbHeader = new byte[Marshal.SizeOf(typeof(SMB2_Header))];
- if (stream.Read(smbHeader, 0, smbHeader.Length) != smbHeader.Length)
- {
- return false;
- }
- if (smbHeader[8] != 0 || smbHeader[9] != 0 || smbHeader[10] != 0 || smbHeader[11] != 0)
- {
- Trace.WriteLine("Checking " + server + " for SMBV2 dialect 0x" + dialect.ToString("X2") + " = Not supported via error code");
- return false;
- }
- byte[] negotiateresponse = new byte[6];
- if (stream.Read(negotiateresponse, 0, negotiateresponse.Length) != negotiateresponse.Length)
- {
- return false;
- }
- if (checkSMBSigning)
- {
- // https://support.microsoft.com/en-in/help/887429/overview-of-server-message-block-signing
- // https://msdn.microsoft.com/en-us/library/cc246561.aspx
- if (negotiateresponse[2] == 3)
- {
- Trace.WriteLine("Checking " + server + " for SMBV2 SMB Signing dialect 0x" + dialect.ToString("X2") + " = Supported");
- return true;
- }
- else
- {
- return false;
- }
- }
- int selectedDialect = negotiateresponse[5] * 0x100 + negotiateresponse[4];
- if (selectedDialect == dialect)
- {
- Trace.WriteLine("Checking " + server + " for SMBV2 dialect 0x" + dialect.ToString("X2") + " = Supported");
- return true;
- }
- Trace.WriteLine("Checking " + server + " for SMBV2 dialect 0x" + dialect.ToString("X2") + " = Not supported via not returned dialect");
- return false;
- }
- catch (Exception)
- {
- throw new ApplicationException("Smb2 is not supported on " + server);
- }
- }
- public static bool SupportSMB1(string server)
- {
- try
- {
- return DoesServerSupportDialect(server, "NT LM 0.12");
- }
- catch (Exception)
- {
- return false;
- }
- }
- public static bool SupportSMB2(string server)
- {
- try
- {
- return (DoesServerSupportDialectWithSmbV2(server, 0x0202, false) || DoesServerSupportDialectWithSmbV2(server, 0x0210, false));
- }
- catch (Exception)
- {
- return false;
- }
- }
- public static bool SupportSMB3(string server)
- {
- try
- {
- return (DoesServerSupportDialectWithSmbV2(server, 0x0300, false) || DoesServerSupportDialectWithSmbV2(server, 0x0302, false) || DoesServerSupportDialectWithSmbV2(server, 0x0311, false));
- }
- catch (Exception)
- {
- return false;
- }
- }
- public static string Name { get { return "smb"; } }
- public static PSObject GetPSObject(string computer)
- {
- PSObject DCSMBObj = new PSObject();
- if (computer == "")
- {
- DCSMBObj.Members.Add(new PSNoteProperty("SMB Port Open", null));
- DCSMBObj.Members.Add(new PSNoteProperty("SMB1(NT LM 0.12)", null));
- DCSMBObj.Members.Add(new PSNoteProperty("SMB2(0x0202)", null));
- DCSMBObj.Members.Add(new PSNoteProperty("SMB2(0x0210)", null));
- DCSMBObj.Members.Add(new PSNoteProperty("SMB3(0x0300)", null));
- DCSMBObj.Members.Add(new PSNoteProperty("SMB3(0x0302)", null));
- DCSMBObj.Members.Add(new PSNoteProperty("SMB3(0x0311)", null));
- DCSMBObj.Members.Add(new PSNoteProperty("SMB Signing", null));
- return DCSMBObj;
- }
- bool isPortOpened = true;
- bool SMBv1 = false;
- bool SMBv2_0x0202 = false;
- bool SMBv2_0x0210 = false;
- bool SMBv3_0x0300 = false;
- bool SMBv3_0x0302 = false;
- bool SMBv3_0x0311 = false;
- bool SMBSigning = false;
- try
- {
- try
- {
- SMBv1 = DoesServerSupportDialect(computer, "NT LM 0.12");
- }
- catch (ApplicationException)
- {
- }
- try
- {
- SMBv2_0x0202 = DoesServerSupportDialectWithSmbV2(computer, 0x0202, false);
- SMBv2_0x0210 = DoesServerSupportDialectWithSmbV2(computer, 0x0210, false);
- SMBv3_0x0300 = DoesServerSupportDialectWithSmbV2(computer, 0x0300, false);
- SMBv3_0x0302 = DoesServerSupportDialectWithSmbV2(computer, 0x0302, false);
- SMBv3_0x0311 = DoesServerSupportDialectWithSmbV2(computer, 0x0311, false);
- }
- catch (ApplicationException)
- {
- }
- }
- catch (Exception)
- {
- isPortOpened = false;
- }
- if (SMBv3_0x0311)
- {
- SMBSigning = DoesServerSupportDialectWithSmbV2(computer, 0x0311, true);
- }
- else if (SMBv3_0x0302)
- {
- SMBSigning = DoesServerSupportDialectWithSmbV2(computer, 0x0302, true);
- }
- else if (SMBv3_0x0300)
- {
- SMBSigning = DoesServerSupportDialectWithSmbV2(computer, 0x0300, true);
- }
- else if (SMBv2_0x0210)
- {
- SMBSigning = DoesServerSupportDialectWithSmbV2(computer, 0x0210, true);
- }
- else if (SMBv2_0x0202)
- {
- SMBSigning = DoesServerSupportDialectWithSmbV2(computer, 0x0202, true);
- }
- DCSMBObj.Members.Add(new PSNoteProperty("SMB Port Open", isPortOpened));
- DCSMBObj.Members.Add(new PSNoteProperty("SMB1(NT LM 0.12)", SMBv1));
- DCSMBObj.Members.Add(new PSNoteProperty("SMB2(0x0202)", SMBv2_0x0202));
- DCSMBObj.Members.Add(new PSNoteProperty("SMB2(0x0210)", SMBv2_0x0210));
- DCSMBObj.Members.Add(new PSNoteProperty("SMB3(0x0300)", SMBv3_0x0300));
- DCSMBObj.Members.Add(new PSNoteProperty("SMB3(0x0302)", SMBv3_0x0302));
- DCSMBObj.Members.Add(new PSNoteProperty("SMB3(0x0311)", SMBv3_0x0311));
- DCSMBObj.Members.Add(new PSNoteProperty("SMB Signing", SMBSigning));
- return DCSMBObj;
- }
- }
- }
- "@
- # Import the LogonUser, ImpersonateLoggedOnUser and RevertToSelf Functions from advapi32.dll and the CloseHandle Function from kernel32.dll
- # https://docs.microsoft.com/en-gb/powershell/module/Microsoft.PowerShell.Utility/Add-Type?view=powershell-5.1
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa378184(v=vs.85).aspx
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa378612(v=vs.85).aspx
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa379317(v=vs.85).aspx
- $Advapi32Def = @'
- [DllImport("advapi32.dll", SetLastError = true)]
- public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);
- [DllImport("advapi32.dll", SetLastError = true)]
- public static extern bool ImpersonateLoggedOnUser(IntPtr hToken);
- [DllImport("advapi32.dll", SetLastError = true)]
- public static extern bool RevertToSelf();
- '@
- # https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx
- $Kernel32Def = @'
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern bool CloseHandle(IntPtr hObject);
- '@
- Function Get-DateDiff
- {
- <#
- .SYNOPSIS
- Get difference between two dates.
- .DESCRIPTION
- Returns the difference between two dates.
- .PARAMETER Date1
- [DateTime]
- Date
- .PARAMETER Date2
- [DateTime]
- Date
- .OUTPUTS
- [System.ValueType.TimeSpan]
- Returns the difference between the two dates.
- #>
- param (
- [Parameter(Mandatory = $true)]
- [DateTime] $Date1,
- [Parameter(Mandatory = $true)]
- [DateTime] $Date2
- )
- If ($Date2 -gt $Date1)
- {
- $DDiff = $Date2 - $Date1
- }
- Else
- {
- $DDiff = $Date1 - $Date2
- }
- Return $DDiff
- }
- Function Get-DNtoFQDN
- {
- <#
- .SYNOPSIS
- Gets Domain Distinguished Name (DN) from the Fully Qualified Domain Name (FQDN).
- .DESCRIPTION
- Converts Domain Distinguished Name (DN) to Fully Qualified Domain Name (FQDN).
- .PARAMETER ADObjectDN
- [string]
- Domain Distinguished Name (DN)
- .OUTPUTS
- [String]
- Returns the Fully Qualified Domain Name (FQDN).
- .LINK
- https://adsecurity.org/?p=440
- #>
- param(
- [Parameter(Mandatory = $true)]
- [string] $ADObjectDN
- )
- $Index = $ADObjectDN.IndexOf('DC=')
- If ($Index)
- {
- $ADObjectDNDomainName = $($ADObjectDN.SubString($Index)) -replace 'DC=','' -replace ',','.'
- }
- Else
- {
- # Modified version from https://adsecurity.org/?p=440
- [array] $ADObjectDNArray = $ADObjectDN -Split ("DC=")
- $ADObjectDNArray | ForEach-Object {
- [array] $temp = $_ -Split (",")
- [string] $ADObjectDNArrayItemDomainName += $temp[0] + "."
- }
- $ADObjectDNDomainName = $ADObjectDNArrayItemDomainName.Substring(1, $ADObjectDNArrayItemDomainName.Length - 2)
- }
- Return $ADObjectDNDomainName
- }
- Function Export-ADRCSV
- {
- <#
- .SYNOPSIS
- Exports Object to a CSV file.
- .DESCRIPTION
- Exports Object to a CSV file using Export-CSV.
- .PARAMETER ADRObj
- [PSObject]
- ADRObj
- .PARAMETER ADFileName
- [String]
- Path to save the CSV File.
- .OUTPUTS
- CSV file.
- #>
- param(
- [Parameter(Mandatory = $true)]
- [ValidateNotNullOrEmpty()]
- [PSObject] $ADRObj,
- [Parameter(Mandatory = $true)]
- [ValidateNotNullOrEmpty()]
- [String] $ADFileName
- )
- Try
- {
- $ADRObj | Export-Csv -Path $ADFileName -NoTypeInformation
- }
- Catch
- {
- Write-Warning "[Export-ADRCSV] Failed to export $($ADFileName)."
- Write-Verbose "[EXCEPTION] $($_.Exception.Message)"
- }
- }
- Function Export-ADRXML
- {
- <#
- .SYNOPSIS
- Exports Object to a XML file.
- .DESCRIPTION
- Exports Object to a XML file using Export-Clixml.
- .PARAMETER ADRObj
- [PSObject]
- ADRObj
- .PARAMETER ADFileName
- [String]
- Path to save the XML File.
- .OUTPUTS
- XML file.
- #>
- param(
- [Parameter(Mandatory = $true)]
- [ValidateNotNullOrEmpty()]
- [PSObject] $ADRObj,
- [Parameter(Mandatory = $true)]
- [ValidateNotNullOrEmpty()]
- [String] $ADFileName
- )
- Try
- {
- (ConvertTo-Xml -NoTypeInformation -InputObject $ADRObj).Save($ADFileName)
- }
- Catch
- {
- Write-Warning "[Export-ADRXML] Failed to export $($ADFileName)."
- Write-Verbose "[EXCEPTION] $($_.Exception.Message)"
- }
- }
- Function Export-ADRJSON
- {
- <#
- .SYNOPSIS
- Exports Object to a JSON file.
- .DESCRIPTION
- Exports Object to a JSON file using ConvertTo-Json.
- .PARAMETER ADRObj
- [PSObject]
- ADRObj
- .PARAMETER ADFileName
- [String]
- Path to save the JSON File.
- .OUTPUTS
- JSON file.
- #>
- param(
- [Parameter(Mandatory = $true)]
- [ValidateNotNullOrEmpty()]
- [PSObject] $ADRObj,
- [Parameter(Mandatory = $true)]
- [ValidateNotNullOrEmpty()]
- [String] $ADFileName
- )
- Try
- {
- ConvertTo-JSON -InputObject $ADRObj | Out-File -FilePath $ADFileName
- }
- Catch
- {
- Write-Warning "[Export-ADRJSON] Failed to export $($ADFileName)."
- Write-Verbose "[EXCEPTION] $($_.Exception.Message)"
- }
- }
- Function Export-ADRHTML
- {
- <#
- .SYNOPSIS
- Exports Object to a HTML file.
- .DESCRIPTION
- Exports Object to a HTML file using ConvertTo-Html.
- .PARAMETER ADRObj
- [PSObject]
- ADRObj
- .PARAMETER ADFileName
- [String]
- Path to save the HTML File.
- .OUTPUTS
- HTML file.
- #>
- param(
- [Parameter(Mandatory = $true)]
- [ValidateNotNullOrEmpty()]
- [PSObject] $ADRObj,
- [Parameter(Mandatory = $true)]
- [ValidateNotNullOrEmpty()]
- [String] $ADFileName,
- [Parameter(Mandatory = $false)]
- [String] $ADROutputDir = $null
- )
- $Header = @"
- <style type="text/css">
- th {
- color:white;
- background-color:blue;
- }
- td, th {
- border:0px solid black;
- border-collapse:collapse;
- white-space:pre;
- }
- tr:nth-child(2n+1) {
- background-color: #dddddd;
- }
- tr:hover td {
- background-color: #c1d5f8;
- }
- table, tr, td, th {
- padding: 0px;
- margin: 0px;
- white-space:pre;
- }
- table {
- margin-left:1px;
- }
- </style>
- "@
- Try
- {
- If ($ADFileName.Contains("Index"))
- {
- $HTMLPath = -join($ADROutputDir,'\','HTML-Files')
- $HTMLPath = $((Convert-Path $HTMLPath).TrimEnd("\"))
- $HTMLFiles = Get-ChildItem -Path $HTMLPath -name
- $HTML = $HTMLFiles | ConvertTo-HTML -Title "ADRecon" -Property @{Label="Table of Contents";Expression={"<a href='$($_)'>$($_)</a>"}} -Head $Header
- Add-Type -AssemblyName System.Web
- [System.Web.HttpUtility]::HtmlDecode($HTML) | Out-File -FilePath $ADFileName
- }
- Else
- {
- If ($ADRObj -is [array])
- {
- $ADRObj | Select-Object * | ConvertTo-HTML -As Table -Head $Header | Out-File -FilePath $ADFileName
- }
- Else
- {
- ConvertTo-HTML -InputObject $ADRObj -As Table -Head $Header | Out-File -FilePath $ADFileName
- }
- }
- }
- Catch
- {
- Write-Warning "[Export-ADRHTML] Failed to export $($ADFileName)."
- Write-Verbose "[EXCEPTION] $($_.Exception.Message)"
- }
- }
- Function Export-ADR
- {
- <#
- .SYNOPSIS
- Helper function for all output types supported.
- .DESCRIPTION
- Helper function for all output types supported.
- .PARAMETER ADObjectDN
- [PSObject]
- ADRObj
- .PARAMETER ADROutputDir
- [String]
- Path for ADRecon output folder.
- .PARAMETER OutputType
- [array]
- Output Type.
- .PARAMETER ADRModuleName
- [String]
- Module Name.
- .OUTPUTS
- STDOUT, CSV, XML, JSON and/or HTML file, etc.
- #>
- param(
- [Parameter(Mandatory = $true)]
- [PSObject] $ADRObj,
- [Parameter(Mandatory = $true)]
- [String] $ADROutputDir,
- [Parameter(Mandatory = $true)]
- [array] $OutputType,
- [Parameter(Mandatory = $true)]
- [String] $ADRModuleName
- )
- Switch ($OutputType)
- {
- 'STDOUT'
- {
- If ($ADRModuleName -ne "AboutADRecon")
- {
- If ($ADRObj -is [array])
- {
- # Fix for InvalidOperationException: The object of type "Microsoft.PowerShell.Commands.Internal.Format.FormatStartData" is not valid or not in the correct sequence.
- $ADRObj | Out-String -Stream
- }
- Else
- {
- # Fix for InvalidOperationException: The object of type "Microsoft.PowerShell.Commands.Internal.Format.FormatStartData" is not valid or not in the correct sequence.
- $ADRObj | Format-List | Out-String -Stream
- }
- }
- }
- 'CSV'
- {
- $ADFileName = -join($ADROutputDir,'\','CSV-Files','\',$ADRModuleName,'.csv')
- Export-ADRCSV -ADRObj $ADRObj -ADFileName $ADFileName
- }
- 'XML'
- {
- $ADFileName = -join($ADROutputDir,'\','XML-Files','\',$ADRModuleName,'.xml')
- Export-ADRXML -ADRObj $ADRObj -ADFileName $ADFileName
- }
- 'JSON'
- {
- $ADFileName = -join($ADROutputDir,'\','JSON-Files','\',$ADRModuleName,'.json')
- Export-ADRJSON -ADRObj $ADRObj -ADFileName $ADFileName
- }
- 'HTML'
- {
- $ADFileName = -join($ADROutputDir,'\','HTML-Files','\',$ADRModuleName,'.html')
- Export-ADRHTML -ADRObj $ADRObj -ADFileName $ADFileName -ADROutputDir $ADROutputDir
- }
- }
- }
- Function Get-ADRExcelComObj
- {
- <#
- .SYNOPSIS
- Creates a ComObject to interact with Microsoft Excel.
- .DESCRIPTION
- Creates a ComObject to interact with Microsoft Excel if installed, else warning is raised.
- .OUTPUTS
- [System.__ComObject] and [System.MarshalByRefObject]
- Creates global variables $excel and $workbook.
- #>
- #Check if Excel is installed.
- Try
- {
- # Suppress verbose output
- $SaveVerbosePreference = $script:VerbosePreference
- $script:VerbosePreference = 'SilentlyContinue'
- $global:excel = New-Object -ComObject excel.application
- If ($SaveVerbosePreference)
- {
- $script:VerbosePreference = $SaveVerbosePreference
- Remove-Variable SaveVerbosePreference
- }
- }
- Catch
- {
- If ($SaveVerbosePreference)
- {
- $script:VerbosePreference = $SaveVerbosePreference
- Remove-Variable SaveVerbosePreference
- }
- Write-Warning "[Get-ADRExcelComObj] Excel does not appear to be installed. Skipping generation of ADRecon-Report.xlsx. Use the -GenExcel parameter to generate the ADRecon-Report.xslx on a host with Microsoft Excel installed."
- Write-Verbose "[EXCEPTION] $($_.Exception.Message)"
- Return $null
- }
- $excel.Visible = $true
- $excel.Interactive = $false
- $global:workbook = $excel.Workbooks.Add()
- If ($workbook.Worksheets.Count -eq 3)
- {
- $workbook.WorkSheets.Item(3).Delete()
- $workbook.WorkSheets.Item(2).Delete()
- }
- }
- Function Get-ADRExcelComObjRelease
- {
- <#
- .SYNOPSIS
- Releases the ComObject created to interact with Microsoft Excel.
- .DESCRIPTION
- Releases the ComObject created to interact with Microsoft Excel.
- .PARAMETER ComObjtoRelease
- ComObjtoRelease
- .PARAMETER Final
- Final
- #>
- param(
- [Parameter(Mandatory = $true)]
- $ComObjtoRelease,
- [Parameter(Mandatory = $false)]
- [bool] $Final = $false
- )
- # https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.releasecomobject(v=vs.110).aspx
- # https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.finalreleasecomobject(v=vs.110).aspx
- If ($Final)
- {
- [System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($ComObjtoRelease) | Out-Null
- }
- Else
- {
- [System.Runtime.InteropServices.Marshal]::ReleaseComObject($ComObjtoRelease) | Out-Null
- }
- [System.GC]::Collect()
- [System.GC]::WaitForPendingFinalizers()
- }
- Function Get-ADRExcelWorkbook
- {
- <#
- .SYNOPSIS
- Adds a WorkSheet to the Workbook.
- .DESCRIPTION
- Adds a WorkSheet to the Workbook using the $workboook global variable and assigns it a name.
- .PARAMETER name
- [string]
- Name of the WorkSheet.
- #>
- param (
- [Parameter(Mandatory = $true)]
- [string] $name
- )
- $workbook.Worksheets.Add() | Out-Null
- $worksheet = $workbook.Worksheets.Item(1)
- $worksheet.Name = $name
- Get-ADRExcelComObjRelease -ComObjtoRelease $worksheet
- Remove-Variable worksheet
- }
- Function Get-ADRExcelImport
- {
- <#
- .SYNOPSIS
- Helper to import CSV to the current WorkSheet.
- .DESCRIPTION
- Helper to import CSV to the current WorkSheet. Supports two methods.
- .PARAMETER ADFileName
- [string]
- Filename of the CSV file to import.
- .PARAMETER method
- [int]
- Method to use for the import.
- .PARAMETER row
- [int]
- Row.
- .PARAMETER column
- [int]
- Column.
- #>
- param (
- [Parameter(Mandatory = $true)]
- [string] $ADFileName,
- [Parameter(Mandatory = $false)]
- [int] $method = 1,
- [Parameter(Mandatory = $false)]
- [int] $row = 1,
- [Parameter(Mandatory = $false)]
- [int] $column = 1
- )
- $excel.ScreenUpdating = $false
- If ($method -eq 1)
- {
- If (Test-Path $ADFileName)
- {
- $worksheet = $workbook.Worksheets.Item(1)
- $TxtConnector = ("TEXT;" + $ADFileName)
- $CellRef = $worksheet.Range("A1")
- #Build, use and remove the text file connector
- $Connector = $worksheet.QueryTables.add($TxtConnector, $CellRef)
- #65001: Unicode (UTF-8)
- $worksheet.QueryTables.item($Connector.name).TextFilePlatform = 65001
- $worksheet.QueryTables.item($Connector.name).TextFileCommaDelimiter = $True
- $worksheet.QueryTables.item($Connector.name).TextFileParseType = 1
- $worksheet.QueryTables.item($Connector.name).Refresh() | Out-Null
- $worksheet.QueryTables.item($Connector.name).delete()
- Get-ADRExcelComObjRelease -ComObjtoRelease $CellRef
- Remove-Variable CellRef
- Get-ADRExcelComObjRelease -ComObjtoRelease $Connector
- Remove-Variable Connector
- $listObject = $worksheet.ListObjects.Add([Microsoft.Office.Interop.Excel.XlListObjectSourceType]::xlSrcRange, $worksheet.UsedRange, $null, [Microsoft.Office.Interop.Excel.XlYesNoGuess]::xlYes, $null)
- $listObject.TableStyle = "TableStyleLight2" # Style Cheat Sheet: https://msdn.microsoft.com/en-au/library/documentformat.openxml.spreadsheet.tablestyle.aspx
- $worksheet.UsedRange.EntireColumn.AutoFit() | Out-Null
- }
- Remove-Variable ADFileName
- }
- Elseif ($method -eq 2)
- {
- $worksheet = $workbook.Worksheets.Item(1)
- If (Test-Path $ADFileName)
- {
- $ADTemp = Import-Csv -Path $ADFileName
- $ADTemp | ForEach-Object {
- Foreach ($prop in $_.PSObject.Properties)
- {
- $worksheet.Cells.Item($row, $column) = $prop.Name
- $worksheet.Cells.Item($row, $column + 1) = $prop.Value
- $row++
- }
- }
- Remove-Variable ADTemp
- $listObject = $worksheet.ListObjects.Add([Microsoft.Office.Interop.Excel.XlListObjectSourceType]::xlSrcRange, $worksheet.UsedRange, $null, [Microsoft.Office.Interop.Excel.XlYesNoGuess]::xlYes, $null)
- $listObject.TableStyle = "TableStyleLight2" # Style Cheat Sheet: https://msdn.microsoft.com/en-au/library/documentformat.openxml.spreadsheet.tablestyle.aspx
- $usedRange = $worksheet.UsedRange
- $usedRange.EntireColumn.AutoFit() | Out-Null
- }
- Else
- {
- $worksheet.Cells.Item($row, $column) = "Error!"
- }
- Remove-Variable ADFileName
- }
- $excel.ScreenUpdating = $true
- Get-ADRExcelComObjRelease -ComObjtoRelease $worksheet
- Remove-Variable worksheet
- }
- # Thanks Anant Shrivastava for the suggestion of using Pivot Tables for generation of the Stats sheets.
- Function Get-ADRExcelPivotTable
- {
- <#
- .SYNOPSIS
- Helper to add Pivot Table to the current WorkSheet.
- .DESCRIPTION
- Helper to add Pivot Table to the current WorkSheet.
- .PARAMETER SrcSheetName
- [string]
- Source Sheet Name.
- .PARAMETER PivotTableName
- [string]
- Pivot Table Name.
- .PARAMETER PivotRows
- [array]
- Row names from Source Sheet.
- .PARAMETER PivotColumns
- [array]
- Column names from Source Sheet.
- .PARAMETER PivotFilters
- [array]
- Row/Column names from Source Sheet to use as filters.
- .PARAMETER PivotValues
- [array]
- Row/Column names from Source Sheet to use for Values.
- .PARAMETER PivotPercentage
- [array]
- Row/Column names from Source Sheet to use for Percentage.
- .PARAMETER PivotLocation
- [array]
- Location of the Pivot Table in Row/Column.
- #>
- param (
- [Parameter(Mandatory = $true)]
- [string] $SrcSheetName,
- [Parameter(Mandatory = $true)]
- [string] $PivotTableName,
- [Parameter(Mandatory = $false)]
- [array] $PivotRows,
- [Parameter(Mandatory = $false)]
- [array] $PivotColumns,
- [Parameter(Mandatory = $false)]
- [array] $PivotFilters,
- [Parameter(Mandatory = $false)]
- [array] $PivotValues,
- [Parameter(Mandatory = $false)]
- [array] $PivotPercentage,
- [Parameter(Mandatory = $false)]
- [string] $PivotLocation = "R1C1"
- )
- $excel.ScreenUpdating = $false
- $SrcWorksheet = $workbook.Sheets.Item($SrcSheetName)
- $workbook.ShowPivotTableFieldList = $false
- # https://msdn.microsoft.com/en-us/vba/excel-vba/articles/xlpivottablesourcetype-enumeration-excel
- # https://msdn.microsoft.com/en-us/vba/excel-vba/articles/xlpivottableversionlist-enumeration-excel
- # https://msdn.microsoft.com/en-us/vba/excel-vba/articles/xlpivotfieldorientation-enumeration-excel
- # https://msdn.microsoft.com/en-us/vba/excel-vba/articles/constants-enumeration-excel
- # https://msdn.microsoft.com/en-us/vba/excel-vba/articles/xlsortorder-enumeration-excel
- # https://msdn.microsoft.com/en-us/vba/excel-vba/articles/xlpivotfiltertype-enumeration-excel
- # xlDatabase = 1 # this just means local sheet data
- # xlPivotTableVersion12 = 3 # Excel 2007
- $PivotFailed = $false
- Try
- {
- $PivotCaches = $workbook.PivotCaches().Create([Microsoft.Office.Interop.Excel.XlPivotTableSourceType]::xlDatabase, $SrcWorksheet.UsedRange, [Microsoft.Office.Interop.Excel.XlPivotTableVersionList]::xlPivotTableVersion12)
- }
- Catch
- {
- $PivotFailed = $true
- Write-Verbose "[EXCEPTION] $($_.Exception.Message)"
- }
- If ( $PivotFailed -eq $true )
- {
- $rows = $SrcWorksheet.UsedRange.Rows.Count
- If ($SrcSheetName -eq "Computer SPNs")
- {
- $PivotCols = "A1:B"
- }
- ElseIf ($SrcSheetName -eq "Users")
- {
- $PivotCols = "A1:AI"
- }
- $UsedRange = $SrcWorksheet.Range($PivotCols+$rows)
- $PivotCaches = $workbook.PivotCaches().Create([Microsoft.Office.Interop.Excel.XlPivotTableSourceType]::xlDatabase, $UsedRange, [Microsoft.Office.Interop.Excel.XlPivotTableVersionList]::xlPivotTableVersion12)
- Remove-Variable rows
- Remove-Variable PivotCols
- Remove-Variable UsedRange
- }
- Remove-Variable PivotFailed
- $PivotTable = $PivotCaches.CreatePivotTable($PivotLocation,$PivotTableName)
- # $workbook.ShowPivotTableFieldList = $true
- If ($PivotRows)
- {
- ForEach ($Row in $PivotRows)
- {
- $PivotField = $PivotTable.PivotFields($Row)
- $PivotField.Orientation = [Microsoft.Office.Interop.Excel.XlPivotFieldOrientation]::xlRowField
- }
- }
- If ($PivotColumns)
- {
- ForEach ($Col in $PivotColumns)
- {
- $PivotField = $PivotTable.PivotFields($Col)
- $PivotField.Orientation = [Microsoft.Office.Interop.Excel.XlPivotFieldOrientation]::xlColumnField
- }
- }
- If ($PivotFilters)
- {
- ForEach ($Fil in $PivotFilters)
- {
- $PivotField = $PivotTable.PivotFields($Fil)
- $PivotField.Orientation = [Microsoft.Office.Interop.Excel.XlPivotFieldOrientation]::xlPageField
- }
- }
- If ($PivotValues)
- {
- ForEach ($Val in $PivotValues)
- {
- $PivotField = $PivotTable.PivotFields($Val)
- $PivotField.Orientation = [Microsoft.Office.Interop.Excel.XlPivotFieldOrientation]::xlDataField
- }
- }
- If ($PivotPercentage)
- {
- ForEach ($Val in $PivotPercentage)
- {
- $PivotField = $PivotTable.PivotFields($Val)
- $PivotField.Orientation = [Microsoft.Office.Interop.Excel.XlPivotFieldOrientation]::xlDataField
- $PivotField.Calculation = [Microsoft.Office.Interop.Excel.XlPivotFieldCalculation]::xlPercentOfTotal
- $PivotTable.ShowValuesRow = $false
- }
- }
- # $PivotFields.Caption = ""
- $excel.ScreenUpdating = $true
- Get-ADRExcelComObjRelease -ComObjtoRelease $PivotField
- Remove-Variable PivotField
- Get-ADRExcelComObjRelease -ComObjtoRelease $PivotTable
- Remove-Variable PivotTable
- Get-ADRExcelComObjRelease -ComObjtoRelease $PivotCaches
- Remove-Variable PivotCaches
- Get-ADRExcelComObjRelease -ComObjtoRelease $SrcWorksheet
- Remove-Variable SrcWorksheet
- }
- Function Get-ADRExcelAttributeStats
- {
- <#
- .SYNOPSIS
- Helper to add Attribute Stats to the current WorkSheet.
- .DESCRIPTION
- Helper to add Attribute Stats to the current WorkSheet.
- .PARAMETER SrcSheetName
- [string]
- Source Sheet Name.
- .PARAMETER Title1
- [string]
- Title1.
- .PARAMETER Title2
- [string]
- Title2.
- .PARAMETER ObjAttributes
- [OrderedDictionary]
- Attributes.
- #>
- param (
- [Parameter(Mandatory = $true)]
- [string] $SrcSheetName,
- [Parameter(Mandatory = $true)]
- [string] $Title1,
- [Parameter(Mandatory = $true)]
- [string] $Title2,
- [Parameter(Mandatory = $true)]
- [System.Object] $ObjAttributes
- )
- $excel.ScreenUpdating = $false
- $worksheet = $workbook.Worksheets.Item(1)
- $SrcWorksheet = $workbook.Sheets.Item($SrcSheetName)
- $row = 1
- $column = 1
- $worksheet.Cells.Item($row, $column) = $Title1
- $worksheet.Cells.Item($row,$column).Style = "Heading 2"
- $worksheet.Cells.Item($row,$column).HorizontalAlignment = -4108
- $MergeCells = $worksheet.Range("A1:C1")
- $MergeCells.Select() | Out-Null
- $MergeCells.MergeCells = $true
- Remove-Variable MergeCells
- Get-ADRExcelPivotTable -SrcSheetName $SrcSheetName -PivotTableName "User Status" -PivotRows @("Enabled") -PivotValues @("UserName") -PivotPercentage @("UserName") -PivotLocation "R2C1"
- $excel.ScreenUpdating = $false
- $row = 2
- "Type","Count","Percentage" | ForEach-Object {
- $worksheet.Cells.Item($row, $column) = $_
- $worksheet.Cells.Item($row, $column).Font.Bold = $True
- $column++
- }
- $row = 3
- $column = 1
- For($row = 3; $row -le 6; $row++)
- {
- $temptext = [string] $worksheet.Cells.Item($row, $column).Text
- switch ($temptext.ToUpper())
- {
- "TRUE" { $worksheet.Cells.Item($row, $column) = "Enabled" }
- "FALSE" { $worksheet.Cells.Item($row, $column) = "Disabled" }
- "GRAND TOTAL" { $worksheet.Cells.Item($row, $column) = "Total" }
- }
- }
- $row = 1
- $column = 6
- $worksheet.Cells.Item($row, $column) = $Title2
- $worksheet.Cells.Item($row,$column).Style = "Heading 2"
- $worksheet.Cells.Item($row,$column).HorizontalAlignment = -4108
- $MergeCells = $worksheet.Range("F1:L1")
- $MergeCells.Select() | Out-Null
- $MergeCells.MergeCells = $true
- Remove-Variable MergeCells
- $row++
- "Category","Enabled Count","Enabled Percentage","Disabled Count","Disabled Percentage","Total Count","Total Percentage" | ForEach-Object {
- $worksheet.Cells.Item($row, $column) = $_
- $worksheet.Cells.Item($row, $column).Font.Bold = $True
- $column++
- }
- $ExcelColumn = ($SrcWorksheet.Columns.Find("Enabled"))
- $EnabledColAddress = "$($ExcelColumn.Address($false,$false).Substring(0,$ExcelColumn.Address($false,$false).Length-1)):$($ExcelColumn.Address($false,$false).Substring(0,$ExcelColumn.Address($false,$false).Length-1))"
- $column = 6
- $i = 2
- $ObjAttributes.keys | ForEach-Object {
- $ExcelColumn = ($SrcWorksheet.Columns.Find($_))
- $ColAddress = "$($ExcelColumn.Address($false,$false).Substring(0,$ExcelColumn.Address($false,$false).Length-1)):$($ExcelColumn.Address($false,$false).Substring(0,$ExcelColumn.Address($false,$false).Length-1))"
- $row++
- $i++
- If ($_ -eq "Delegation Typ")
- {
- $worksheet.Cells.Item($row, $column) = "Unconstrained Delegation"
- }
- ElseIf ($_ -eq "Delegation Type")
- {
- $worksheet.Cells.Item($row, $column) = "Constrained Delegation"
- }
- Else
- {
- $worksheet.Cells.Item($row, $column).Formula = '=' + $SrcWorksheet.Name + '!' + $ExcelColumn.Address($false,$false)
- }
- $worksheet.Cells.Item($row, $column+1).Formula = '=COUNTIFS(' + $SrcWorksheet.Name + '!' + $EnabledColAddress + ',"TRUE",' + $SrcWorksheet.Name + '!' + $ColAddress + ',' + $ObjAttributes[$_] + ')'
- $worksheet.Cells.Item($row, $column+2).Formula = '=IFERROR(G' + $i + '/VLOOKUP("Enabled",A3:B6,2,FALSE),0)'
- $worksheet.Cells.Item($row, $column+3).Formula = '=COUNTIFS(' + $SrcWorksheet.Name + '!' + $EnabledColAddress + ',"FALSE",' + $SrcWorksheet.Name + '!' + $ColAddress + ',' + $ObjAttributes[$_] + ')'
- $worksheet.Cells.Item($row, $column+4).Formula = '=IFERROR(I' + $i + '/VLOOKUP("Disabled",A3:B6,2,FALSE),0)'
- If ( ($_ -eq "SIDHistory") -or ($_ -eq "ms-ds-CreatorSid") )
- {
- $worksheet.Cells.Item($row, $column+5).Formula = '=COUNTIF(' + $SrcWorksheet.Name + '!' + $ColAddress + ',' + $ObjAttributes[$_] + ')-1'
- }
- Else
- {
- $worksheet.Cells.Item($row, $column+5).Formula = '=COUNTIF(' + $SrcWorksheet.Name + '!' + $ColAddress + ',' + $ObjAttributes[$_] + ')'
- }
- $worksheet.Cells.Item($row, $column+6).Formula = '=IFERROR(K' + $i + '/VLOOKUP("Total",A3:B6,2,FALSE),0)'
- }
- # http://www.excelhowto.com/macros/formatting-a-range-of-cells-in-excel-vba/
- "H", "J" , "L" | ForEach-Object {
- $rng = $_ + $($row - $ObjAttributes.Count + 1) + ":" + $_ + $($row)
- $worksheet.Range($rng).NumberFormat = "0.00%"
- }
- $excel.ScreenUpdating = $true
- Get-ADRExcelComObjRelease -ComObjtoRelease $SrcWorksheet
- Remove-Variable SrcWorksheet
- Get-ADRExcelComObjRelease -ComObjtoRelease $worksheet
- Remove-Variable worksheet
- }
- Function Get-ADRExcelChart
- {
- <#
- .SYNOPSIS
- Helper to add charts to the current WorkSheet.
- .DESCRIPTION
- Helper to add charts to the current WorkSheet.
- .PARAMETER ChartType
- [int]
- Chart Type.
- .PARAMETER ChartLayout
- [int]
- Chart Layout.
- .PARAMETER ChartTitle
- [string]
- Title of the Chart.
- .PARAMETER RangetoCover
- WorkSheet Range to be covered by the Chart.
- .PARAMETER ChartData
- Data for the Chart.
- .PARAMETER StartRow
- Start row to calculate data for the Chart.
- .PARAMETER StartColumn
- Start column to calculate data for the Chart.
- #>
- param (
- [Parameter(Mandatory = $true)]
- [string] $ChartType,
- [Parameter(Mandatory = $true)]
- [int] $ChartLayout,
- [Parameter(Mandatory = $true)]
- [string] $ChartTitle,
- [Parameter(Mandatory = $true)]
- $RangetoCover,
- [Parameter(Mandatory = $false)]
- $ChartData = $null,
- [Parameter(Mandatory = $false)]
- $StartRow = $null,
- [Parameter(Mandatory = $false)]
- $StartColumn = $null
- )
- $excel.ScreenUpdating = $false
- $excel.DisplayAlerts = $false
- $worksheet = $workbook.Worksheets.Item(1)
- $chart = $worksheet.Shapes.AddChart().Chart
- # https://msdn.microsoft.com/en-us/vba/excel-vba/articles/xlcharttype-enumeration-excel
- $chart.chartType = [int]([Microsoft.Office.Interop.Excel.XLChartType]::$ChartType)
- $chart.ApplyLayout($ChartLayout)
- If ($null -eq $ChartData)
- {
- If ($null -eq $StartRow)
- {
- $start = $worksheet.Range("A1")
- }
- Else
- {
- $start = $worksheet.Range($StartRow)
- }
- # get the last cell
- $X = $worksheet.Range($start,$start.End([Microsoft.Office.Interop.Excel.XLDirection]::xlDown))
- If ($null -eq $StartColumn)
- {
- $start = $worksheet.Range("B1")
- }
- Else
- {
- $start = $worksheet.Range($StartColumn)
- }
- # get the last cell
- $Y = $worksheet.Range($start,$start.End([Microsoft.Office.Interop.Excel.XLDirection]::xlDown))
- $ChartData = $worksheet.Range($X,$Y)
- Get-ADRExcelComObjRelease -ComObjtoRelease $X
- Remove-Variable X
- Get-ADRExcelComObjRelease -ComObjtoRelease $Y
- Remove-Variable Y
- Get-ADRExcelComObjRelease -ComObjtoRelease $start
- Remove-Variable start
- }
- $chart.SetSourceData($ChartData)
- # https://docs.microsoft.com/en-us/dotnet/api/microsoft.office.interop.excel.chartclass.plotby?redirectedfrom=MSDN&view=excel-pia#Microsoft_Office_Interop_Excel_ChartClass_PlotBy
- $chart.PlotBy = [Microsoft.Office.Interop.Excel.XlRowCol]::xlColumns
- $chart.seriesCollection(1).Select() | Out-Null
- $chart.SeriesCollection(1).ApplyDataLabels() | out-Null
- # modify the chart title
- $chart.HasTitle = $True
- $chart.ChartTitle.Text = $ChartTitle
- # Reposition the Chart
- $temp = $worksheet.Range($RangetoCover)
- # $chart.parent.placement = 3
- $chart.parent.top = $temp.Top
- $chart.parent.left = $temp.Left
- $chart.parent.width = $temp.Width
- If ($ChartTitle -ne "Privileged Groups in AD")
- {
- $chart.parent.height = $temp.Height
- }
- # $chart.Legend.Delete()
- $excel.ScreenUpdating = $true
- $excel.DisplayAlerts = $true
- Get-ADRExcelComObjRelease -ComObjtoRelease $chart
- Remove-Variable chart
- Get-ADRExcelComObjRelease -ComObjtoRelease $ChartData
- Remove-Variable ChartData
- Get-ADRExcelComObjRelease -ComObjtoRelease $temp
- Remove-Variable temp
- Get-ADRExcelComObjRelease -ComObjtoRelease $worksheet
- Remove-Variable worksheet
- }
- Function Get-ADRExcelSort
- {
- <#
- .SYNOPSIS
- Sorts a WorkSheet in the active Workbook.
- .DESCRIPTION
- Sorts a WorkSheet in the active Workbook.
- .PARAMETER ColumnName
- [string]
- Name of the Column.
- #>
- param (
- [Parameter(Mandatory = $true)]
- [string] $ColumnName
- )
- $worksheet = $workbook.Worksheets.Item(1)
- $worksheet.Activate();
- $ExcelColumn = ($worksheet.Columns.Find($ColumnName))
- If ($ExcelColumn)
- {
- If ($ExcelColumn.Text -ne $ColumnName)
- {
- $BeginAddress = $ExcelColumn.Address(0,0,1,1)
- $End = $False
- Do {
- Write-Verbose "[Get-ADRExcelSort] $($ExcelColumn.Text) selected instead of $($ColumnName) in the $($worksheet.Name) worksheet."
- $ExcelColumn = ($worksheet.Columns.FindNext($ExcelColumn))
- $Address = $ExcelColumn.Address(0,0,1,1)
- If ( ($Address -eq $BeginAddress) -or ($ExcelColumn.Text -eq $ColumnName) )
- {
- $End = $True
- }
- } Until ($End -eq $True)
- }
- If ($ExcelColumn.Text -eq $ColumnName)
- {
- # Sort by Column
- $workSheet.ListObjects.Item(1).Sort.SortFields.Clear()
- $workSheet.ListObjects.Item(1).Sort.SortFields.Add($ExcelColumn) | Out-Null
- $worksheet.ListObjects.Item(1).Sort.Apply()
- }
- Else
- {
- Write-Verbose "[Get-ADRExcelSort] $($ColumnName) not found in the $($worksheet.Name) worksheet."
- }
- }
- Else
- {
- Write-Verbose "[Get-ADRExcelSort] $($ColumnName) not found in the $($worksheet.Name) worksheet."
- }
- Get-ADRExcelComObjRelease -ComObjtoRelease $worksheet
- Remove-Variable worksheet
- }
- Function Export-ADRExcel
- {
- <#
- .SYNOPSIS
- Automates the generation of the ADRecon report.
- .DESCRIPTION
- Automates the generation of the ADRecon report. If specific files exist, they are imported into the ADRecon report.
- .PARAMETER ExcelPath
- [string]
- Path for ADRecon output folder containing the CSV files to generate the ADRecon-Report.xlsx
- .OUTPUTS
- Creates the ADRecon-Report.xlsx report in the folder.
- #>
- param(
- [Parameter(Mandatory = $true)]
- [string] $ExcelPath
- )
- $ExcelPath = $((Convert-Path $ExcelPath).TrimEnd("\"))
- $ReportPath = -join($ExcelPath,'\','CSV-Files')
- If (!(Test-Path $ReportPath))
- {
- Write-Warning "[Export-ADRExcel] Could not locate the CSV-Files directory ... Exiting"
- Write-Verbose "[EXCEPTION] $($_.Exception.Message)"
- Return $null
- }
- Get-ADRExcelComObj
- If ($excel)
- {
- Write-Output "[*] Generating ADRecon-Report.xlsx"
- $ADFileName = -join($ReportPath,'\','AboutADRecon.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelImport -ADFileName $ADFileName
- Remove-Variable ADFileName
- $workbook.Worksheets.Item(1).Name = "About ADRecon"
- $workbook.Worksheets.Item(1).Hyperlinks.Add($workbook.Worksheets.Item(1).Cells.Item(3,2) , "https://github.com/sense-of-security/ADRecon", "" , "", "github.com/sense-of-security/ADRecon") | Out-Null
- $workbook.Worksheets.Item(1).UsedRange.EntireColumn.AutoFit() | Out-Null
- }
- $ADFileName = -join($ReportPath,'\','Forest.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelWorkbook -Name "Forest"
- Get-ADRExcelImport -ADFileName $ADFileName
- Remove-Variable ADFileName
- }
- $ADFileName = -join($ReportPath,'\','Domain.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelWorkbook -Name "Domain"
- Get-ADRExcelImport -ADFileName $ADFileName
- $DomainObj = Import-CSV -Path $ADFileName
- Remove-Variable ADFileName
- $DomainName = -join($DomainObj[0].Value,"-")
- Remove-Variable DomainObj
- }
- $ADFileName = -join($ReportPath,'\','Trusts.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelWorkbook -Name "Trusts"
- Get-ADRExcelImport -ADFileName $ADFileName
- Remove-Variable ADFileName
- }
- $ADFileName = -join($ReportPath,'\','Subnets.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelWorkbook -Name "Subnets"
- Get-ADRExcelImport -ADFileName $ADFileName
- Remove-Variable ADFileName
- }
- $ADFileName = -join($ReportPath,'\','Sites.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelWorkbook -Name "Sites"
- Get-ADRExcelImport -ADFileName $ADFileName
- Remove-Variable ADFileName
- }
- $ADFileName = -join($ReportPath,'\','FineGrainedPasswordPolicy.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelWorkbook -Name "Fine Grained Password Policy"
- Get-ADRExcelImport -ADFileName $ADFileName
- Remove-Variable ADFileName
- }
- $ADFileName = -join($ReportPath,'\','DefaultPasswordPolicy.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelWorkbook -Name "Default Password Policy"
- Get-ADRExcelImport -ADFileName $ADFileName
- Remove-Variable ADFileName
- $excel.ScreenUpdating = $false
- $worksheet = $workbook.Worksheets.Item(1)
- # https://docs.microsoft.com/en-us/office/vba/api/excel.xlhalign
- $worksheet.Range("B2:G10").HorizontalAlignment = -4108
- # https://docs.microsoft.com/en-us/office/vba/api/excel.range.borderaround
- "A2:B10", "C2:D10", "E2:F10", "G2:G10" | ForEach-Object {
- $worksheet.Range($_).BorderAround(1) | Out-Null
- }
- # https://docs.microsoft.com/en-us/dotnet/api/microsoft.office.interop.excel.formatconditions.add?view=excel-pia
- # $worksheet.Range().FormatConditions.Add
- # http://dmcritchie.mvps.org/excel/colors.htm
- # Values for Font.ColorIndex
- $ObjValues = @(
- # PCI Enforce password history (passwords)
- "C2", '=IF(B2<4,TRUE, FALSE)'
- # PCI Maximum password age (days)
- "C3", '=IF(OR(B3=0,B3>90),TRUE, FALSE)'
- # PCI Minimum password age (days)
- # PCI Minimum password length (characters)
- "C5", '=IF(B5<7,TRUE, FALSE)'
- # PCI Password must meet complexity requirements
- "C6", '=IF(B6<>TRUE,TRUE, FALSE)'
- # PCI Store password using reversible encryption for all users in the domain
- # PCI Account lockout duration (mins)
- "C8", '=IF(AND(B8>=1,B8<30),TRUE, FALSE)'
- # PCI Account lockout threshold (attempts)
- "C9", '=IF(OR(B9=0,B9>6),TRUE, FALSE)'
- # PCI Reset account lockout counter after (mins)
- # ASD ISM Enforce password history (passwords)
- "E2", '=IF(B2<8,TRUE, FALSE)'
- # ASD ISM Maximum password age (days)
- "E3", '=IF(OR(B3=0,B3>90),TRUE, FALSE)'
- # ASD ISM Minimum password age (days)
- "E4", '=IF(B4=0,TRUE, FALSE)'
- # ASD ISM Minimum password length (characters)
- "E5", '=IF(B5<13,TRUE, FALSE)'
- # ASD ISM Password must meet complexity requirements
- "E6", '=IF(B6<>TRUE,TRUE, FALSE)'
- # ASD ISM Store password using reversible encryption for all users in the domain
- # ASD ISM Account lockout duration (mins)
- # ASD ISM Account lockout threshold (attempts)
- "E9", '=IF(OR(B9=0,B9>5),TRUE, FALSE)'
- # ASD ISM Reset account lockout counter after (mins)
- # CIS Benchmark Enforce password history (passwords)
- "G2", '=IF(B2<24,TRUE, FALSE)'
- # CIS Benchmark Maximum password age (days)
- "G3", '=IF(OR(B3=0,B3>60),TRUE, FALSE)'
- # CIS Benchmark Minimum password age (days)
- "G4", '=IF(B4=0,TRUE, FALSE)'
- # CIS Benchmark Minimum password length (characters)
- "G5", '=IF(B5<14,TRUE, FALSE)'
- # CIS Benchmark Password must meet complexity requirements
- "G6", '=IF(B6<>TRUE,TRUE, FALSE)'
- # CIS Benchmark Store password using reversible encryption for all users in the domain
- "G7", '=IF(B7<>FALSE,TRUE, FALSE)'
- # CIS Benchmark Account lockout duration (mins)
- "G8", '=IF(AND(B8>=1,B8<15),TRUE, FALSE)'
- # CIS Benchmark Account lockout threshold (attempts)
- "G9", '=IF(OR(B9=0,B9>10),TRUE, FALSE)'
- # CIS Benchmark Reset account lockout counter after (mins)
- "G10", '=IF(B10<15,TRUE, FALSE)' )
- For ($i = 0; $i -lt $($ObjValues.Count); $i++)
- {
- $worksheet.Range($ObjValues[$i]).FormatConditions.Add([Microsoft.Office.Interop.Excel.XlFormatConditionType]::xlExpression, 0, $ObjValues[$i+1]) | Out-Null
- $i++
- }
- "C2", "C3" , "C5", "C6", "C8", "C9", "E2", "E3" , "E4", "E5", "E6", "E9", "G2", "G3", "G4", "G5", "G6", "G7", "G8", "G9", "G10" | ForEach-Object {
- $worksheet.Range($_).FormatConditions.Item(1).StopIfTrue = $false
- $worksheet.Range($_).FormatConditions.Item(1).Font.ColorIndex = 3
- }
- $workbook.Worksheets.Item(1).Hyperlinks.Add($workbook.Worksheets.Item(1).Cells.Item(1,4) , "https://www.pcisecuritystandards.org/document_library?category=pcidss&document=pci_dss", "" , "", "PCI DSS v3.2.1") | Out-Null
- $workbook.Worksheets.Item(1).Hyperlinks.Add($workbook.Worksheets.Item(1).Cells.Item(1,6) , "https://acsc.gov.au/infosec/ism/", "" , "", "2018 ISM Controls") | Out-Null
- $workbook.Worksheets.Item(1).Hyperlinks.Add($workbook.Worksheets.Item(1).Cells.Item(1,7) , "https://www.cisecurity.org/benchmark/microsoft_windows_server/", "" , "", "CIS Benchmark 2016") | Out-Null
- $excel.ScreenUpdating = $true
- Get-ADRExcelComObjRelease -ComObjtoRelease $worksheet
- Remove-Variable worksheet
- }
- $ADFileName = -join($ReportPath,'\','DomainControllers.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelWorkbook -Name "Domain Controllers"
- Get-ADRExcelImport -ADFileName $ADFileName
- Remove-Variable ADFileName
- }
- $ADFileName = -join($ReportPath,'\','DACLs.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelWorkbook -Name "DACLs"
- Get-ADRExcelImport -ADFileName $ADFileName
- Remove-Variable ADFileName
- }
- $ADFileName = -join($ReportPath,'\','SACLs.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelWorkbook -Name "SACLs"
- Get-ADRExcelImport -ADFileName $ADFileName
- Remove-Variable ADFileName
- }
- $ADFileName = -join($ReportPath,'\','GPOs.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelWorkbook -Name "GPOs"
- Get-ADRExcelImport -ADFileName $ADFileName
- Remove-Variable ADFileName
- }
- $ADFileName = -join($ReportPath,'\','gPLinks.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelWorkbook -Name "gPLinks"
- Get-ADRExcelImport -ADFileName $ADFileName
- Remove-Variable ADFileName
- }
- $ADFileName = -join($ReportPath,'\','DNSNodes','.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelWorkbook -Name "DNS Records"
- Get-ADRExcelImport -ADFileName $ADFileName
- Remove-Variable ADFileName
- }
- $ADFileName = -join($ReportPath,'\','DNSZones.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelWorkbook -Name "DNS Zones"
- Get-ADRExcelImport -ADFileName $ADFileName
- Remove-Variable ADFileName
- }
- $ADFileName = -join($ReportPath,'\','Printers.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelWorkbook -Name "Printers"
- Get-ADRExcelImport -ADFileName $ADFileName
- Remove-Variable ADFileName
- }
- $ADFileName = -join($ReportPath,'\','BitLockerRecoveryKeys.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelWorkbook -Name "BitLocker"
- Get-ADRExcelImport -ADFileName $ADFileName
- Remove-Variable ADFileName
- }
- $ADFileName = -join($ReportPath,'\','LAPS.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelWorkbook -Name "LAPS"
- Get-ADRExcelImport -ADFileName $ADFileName
- Remove-Variable ADFileName
- }
- $ADFileName = -join($ReportPath,'\','ComputerSPNs.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelWorkbook -Name "Computer SPNs"
- Get-ADRExcelImport -ADFileName $ADFileName
- Remove-Variable ADFileName
- Get-ADRExcelSort -ColumnName "Name"
- }
- $ADFileName = -join($ReportPath,'\','Computers.csv')
- If (Test-Path $ADFileName)
- {
- Get-ADRExcelWorkbook -Name "Computers"
- Get-ADRExcelImport -ADFileName $ADFileName
- Remove-Variable ADFileName
- Get-ADRExcelSort -ColumnName "UserName"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement