private void BuildDirectDelegationData() { if (domainInfo.ForestFunctionality < 2) { return; } var map = new Dictionary <string, List <string> >(StringComparer.OrdinalIgnoreCase); WorkOnReturnedObjectByADWS callback = (ADItem aditem) => { foreach (var d in aditem.msDSAllowedToDelegateTo) { var spn = d.Split('/'); if (spn.Length < 2) { continue; } if (!map.ContainsKey(spn[1])) { map[spn[1]] = new List <string>(); } var sid = aditem.ObjectSid.Value; if (!map[spn[1]].Contains(sid)) { map[spn[1]].Add(sid); } } }; adws.Enumerate(domainInfo.DefaultNamingContext, "(&(msDS-AllowedToDelegateTo=*)((userAccountControl:1.2.840.113556.1.4.804:=16777216)))", new string[] { "objectSid", "msDS-AllowedToDelegateTo" }, callback); RelationFactory.InitializeDelegation(map); }
private ADDomainInfo GetDomainInformation(ADWebService adws) { ADDomainInfo domainInfo = null; domainInfo = adws.DomainInfo; if (adws.useLdap) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Performance warning: using LDAP instead of ADWS"); Console.ResetColor(); } // adding the domain sid string[] properties = new string[] { "objectSid", }; WorkOnReturnedObjectByADWS callback = (ADItem aditem) => { domainInfo.DomainSid = aditem.ObjectSid; }; adws.Enumerate(domainInfo.DefaultNamingContext, "(&(objectClass=domain)(distinguishedName=" + domainInfo.DefaultNamingContext + "))", properties, callback); // adding the domain Netbios name string[] propertiesNetbios = new string[] { "nETBIOSName" }; adws.Enumerate("CN=Partitions," + domainInfo.ConfigurationNamingContext, "(&(objectCategory=crossRef)(systemFlags:1.2.840.113556.1.4.803:=3)(nETBIOSName=*)(nCName=" + domainInfo.DefaultNamingContext + "))", propertiesNetbios, (ADItem aditem) => { domainInfo.NetBIOSName = aditem.NetBIOSName; } , "OneLevel"); return(domainInfo); }
public void Export(string filename) { DisplayAdvancement("Starting"); using (ADWebService adws = new ADWebService(Server, Port, Credential)) { string[] propertiesLaps = new string[] { "schemaIDGUID" }; // note: the LDAP request does not contain ms-MCS-AdmPwd because in the old time, MS consultant was installing customized version of the attriute, * being replaced by the company name // check the oid instead ? (which was the same even if the attribute name was not) adws.Enumerate(adws.DomainInfo.SchemaNamingContext, "(name=ms-*-AdmPwd)", propertiesLaps, (ADItem aditem) => { LAPSSchemaId = aditem.SchemaIDGUID; }, "OneLevel"); using (StreamWriter sw = File.CreateText(filename)) { sw.WriteLine("DistinguishedName\tIdentity\tAccessRule"); var domainInfo = adws.DomainInfo; EnrichDomainInfo(adws, domainInfo); BuildUserList(adws, domainInfo); WorkOnReturnedObjectByADWS callback = ((ADItem x) => { if (x.NTSecurityDescriptor != null) { var Owner = x.NTSecurityDescriptor.GetOwner(typeof(SecurityIdentifier)); var match = MatchesUsersToCheck(Owner); if (match != null) { sw.WriteLine(x.DistinguishedName + "\t" + match.Value.Value + "\tOwner"); } foreach (ActiveDirectoryAccessRule accessrule in x.NTSecurityDescriptor.GetAccessRules(true, false, typeof(SecurityIdentifier))) { // ignore audit / denied ace if (accessrule.AccessControlType != AccessControlType.Allow) { continue; } match = MatchesUsersToCheck(accessrule.IdentityReference); if (!match.HasValue) { continue; } if (MatchesBadACL(accessrule)) { sw.WriteLine(x.DistinguishedName + "\t" + match.Value.Value + "\t" + accessrule.ActiveDirectoryRights.ToString()); } } } } ); DisplayAdvancement("Analyzing AD Objects"); adws.Enumerate(domainInfo.DefaultNamingContext, "(objectClass=*)", new string[] { "distinguishedName", "nTSecurityDescriptor" }, callback); DisplayAdvancement("Analyzing files"); CheckFilePermission(domainInfo, sw, adws); DisplayAdvancement("Done"); } } }
private ADItem Search(ADWebService adws, ADDomainInfo domainInfo, string userName) { ADItem output = null; WorkOnReturnedObjectByADWS callback = (ADItem aditem) => { output = aditem; }; if (userName.StartsWith("S-1-5")) { adws.Enumerate(domainInfo.DefaultNamingContext, "(objectSid=" + ADConnection.EncodeSidToString(userName) + ")", properties, callback); if (output != null) { return(output); } } if (userName.StartsWith("CN=") && userName.EndsWith(domainInfo.DefaultNamingContext)) { adws.Enumerate(domainInfo.DefaultNamingContext, "(distinguishedName=" + ADConnection.EscapeLDAP(userName) + ")", properties, callback); if (output != null) { return(output); } } if (userName.Length <= 20) { adws.Enumerate(domainInfo.DefaultNamingContext, "(&(objectCategory=person)(objectClass=user)(sAMAccountName=" + ADConnection.EscapeLDAP(userName) + "))", properties, callback); if (output != null) { return(output); } } adws.Enumerate(domainInfo.DefaultNamingContext, "(cn=" + ADConnection.EscapeLDAP(userName) + ")", properties, callback); if (output != null) { return(output); } adws.Enumerate(domainInfo.DefaultNamingContext, "(displayName=" + ADConnection.EscapeLDAP(userName) + ")", properties, callback); if (output != null) { return(output); } return(output); }
public void Export(string filename) { ADDomainInfo domainInfo = null; using (ADWebService adws = new ADWebService(Server, Port, Credential)) { domainInfo = adws.DomainInfo; DisplayAdvancement("Iterating through user objects (all except disabled ones)"); string[] properties = new string[] { "DistinguishedName", "sAMAccountName", "userAccountControl", "whenCreated", "lastLogonTimestamp", }; using (var sw = File.CreateText(filename)) { sw.WriteLine("SAMAccountName\tDN\tWhen Created\tLast Logon Timestamp"); WorkOnReturnedObjectByADWS callback = (ADItem x) => { sw.WriteLine(x.SAMAccountName + "\t" + x.DistinguishedName + "\t" + x.WhenCreated.ToString("u") + "\t" + x.LastLogonTimestamp.ToString("u") + "\t" + x.PwdLastSet.ToString("u")); }; adws.Enumerate(domainInfo.DefaultNamingContext, "(&(objectClass=user)(objectCategory=person)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(!(sAMAccountName=krbtgt)))", properties, callback); } DisplayAdvancement("Done"); } }
List <string> GetListOfComputerToExplore() { ADDomainInfo domainInfo = null; List <string> computers = new List <string>(); using (ADWebService adws = new ADWebService(Server, Port, Credential)) { domainInfo = adws.DomainInfo; string[] properties = new string[] { "dNSHostName", "primaryGroupID" }; WorkOnReturnedObjectByADWS callback = (ADItem x) => { computers.Add(x.DNSHostName); }; string filterClause = null; switch (ScanningMode) { case 3: filterClause = "(!(operatingSystem=*server*))"; break; case 4: filterClause = "(operatingSystem=*server*)"; break; } adws.Enumerate(domainInfo.DefaultNamingContext, "(&(ObjectCategory=computer)" + filterClause + "(!userAccountControl:1.2.840.113556.1.4.803:=2)(lastLogonTimeStamp>=" + DateTime.Now.AddDays(-60).ToFileTimeUtc() + "))", properties, callback); } return(computers); }
private ADItem Search(ADWebService adws, ADDomainInfo domainInfo, string userName) { ADItem output = null; string[] properties = new string[] { "distinguishedName", "displayName", "name", "objectSid", }; WorkOnReturnedObjectByADWS callback = (ADItem aditem) => { output = aditem; }; if (userName.StartsWith("S-1-5")) { adws.Enumerate(domainInfo.DefaultNamingContext, "(objectSid=" + ADConnection.EncodeSidToString(userName) + ")", properties, callback); } adws.Enumerate(domainInfo.DefaultNamingContext, "(sAMAccountName=" + ADConnection.EscapeLDAP(userName) + ")", properties, callback); if (output != null) { return(output); } adws.Enumerate(domainInfo.DefaultNamingContext, "(cn=" + ADConnection.EscapeLDAP(userName) + ")", properties, callback); if (output != null) { return(output); } adws.Enumerate(domainInfo.DefaultNamingContext, "(displayName=" + ADConnection.EscapeLDAP(userName) + ")", properties, callback); if (output != null) { return(output); } return(output); }
private void AddDnsAdmins(GraphObjectReference objectReference) { string[] properties = new string[] { "name", "objectSid" }; bool dnsAdminFound = false; WorkOnReturnedObjectByADWS callback = (ADItem x) => { objectReference.Objects[CompromiseGraphDataTypology.PrivilegedAccount].Add(new GraphSingleObject(x.ObjectSid.Value, GraphObjectReference.DnsAdministrators, CompromiseGraphDataObjectRisk.Medium)); dnsAdminFound = true; }; // we do a one level search just case the group is in the default position adws.Enumerate("CN=Users," + domainInfo.DefaultNamingContext, "(&(objectClass=group)(description=DNS Administrators Group))", properties, callback, "OneLevel"); if (!dnsAdminFound) { adws.Enumerate("CN=Users," + domainInfo.DefaultNamingContext, "(&(objectClass=group)(sAMAccountName=DNSAdmins))", properties, callback, "OneLevel"); } if (!dnsAdminFound) { // then full tree. This is an optimization for LDAP request adws.Enumerate(domainInfo.DefaultNamingContext, "(&(objectClass=group)(description=DNS Administrators Group))", properties, callback); } if (!dnsAdminFound) { adws.Enumerate(domainInfo.DefaultNamingContext, "(&(objectClass=group)(sAMAccountName=DNSAdmins))", properties, callback); } }
public void Export(string filename) { DisplayAdvancement("Starting"); using (ADWebService adws = new ADWebService(Server, Port, Credential)) { using (StreamWriter sw = File.CreateText(filename)) { sw.WriteLine("DistinguishedName\tIdentity\tAccessRule"); var domainInfo = adws.DomainInfo; EnrichDomainInfo(adws, domainInfo); BuildUserList(adws, domainInfo); WorkOnReturnedObjectByADWS callback = ((ADItem x) => { if (x.NTSecurityDescriptor != null) { var Owner = x.NTSecurityDescriptor.GetOwner(typeof(SecurityIdentifier)); var match = MatchesUsersToCheck(Owner); if (match != null) { sw.WriteLine(x.DistinguishedName + "\t" + match.Value.Value + "\tOwner"); } foreach (ActiveDirectoryAccessRule accessrule in x.NTSecurityDescriptor.GetAccessRules(true, false, typeof(SecurityIdentifier))) { // ignore audit / denied ace if (accessrule.AccessControlType != AccessControlType.Allow) { continue; } match = MatchesUsersToCheck(accessrule.IdentityReference); if (!match.HasValue) { continue; } if (MatchesBadACL(accessrule)) { sw.WriteLine(x.DistinguishedName + "\t" + match.Value.Value + "\t" + accessrule.ActiveDirectoryRights.ToString()); } } } } ); DisplayAdvancement("Analyzing AD Objects"); adws.Enumerate(domainInfo.DefaultNamingContext, "(objectClass=*)", new string[] { "distinguishedName", "nTSecurityDescriptor" }, callback); DisplayAdvancement("Analyzing files"); CheckFilePermission(domainInfo, sw); DisplayAdvancement("Done"); } } }
private void EnrichDomainInfo(ADWebService adws, ADDomainInfo domainInfo) { // adding the domain sid string[] properties = new string[] { "objectSid", }; WorkOnReturnedObjectByADWS callback = (ADItem aditem) => { domainInfo.DomainSid = aditem.ObjectSid; }; adws.Enumerate(domainInfo.DefaultNamingContext, "(&(objectClass=domain)(distinguishedName=" + domainInfo.DefaultNamingContext + "))", properties, callback); }
private void ExportSIDData(ADWebService adws, ADDomainInfo domainInfo, RelationFactory relationFactory, List <string> sids) { WorkOnReturnedObjectByADWS callback = (ADItem aditem) => { relationFactory.AnalyzeADObject(aditem); }; foreach (string sid in sids) { adws.Enumerate(domainInfo.DefaultNamingContext, "(objectSid=" + ADConnection.EncodeSidToString(sid) + ")", properties, callback); } }
private void ExportCNData(ADWebService adws, ADDomainInfo domainInfo, RelationFactory relationFactory, List <string> cns) { WorkOnReturnedObjectByADWS callback = (ADItem aditem) => { relationFactory.AnalyzeADObject(aditem); }; foreach (string cn in cns) { adws.Enumerate(domainInfo.DefaultNamingContext, "(distinguishedName=" + ADConnection.EscapeLDAP(cn) + ")", properties, callback); } }
private Dictionary <uint, string> BuildAllAttributeDictionnary(ADWebService adws) { var output = new Dictionary <uint, string>(); string[] properties = new string[] { "lDAPDisplayName", "attributeID" }; WorkOnReturnedObjectByADWS callback = (ADItem x) => { output[TransformOidToAttId(x.AttributeID, x.lDAPDisplayName)] = x.lDAPDisplayName; }; adws.Enumerate(adws.DomainInfo.SchemaNamingContext, "(&(objectclass=attributeSchema)(lDAPDisplayName=*))", properties, callback, "Subtree"); return(output); }
private void ExportPrimaryGroupData(ADWebService adws, ADDomainInfo domainInfo, RelationFactory relationFactory, List <int> primaryGroupIDs) { WorkOnReturnedObjectByADWS callback = (ADItem aditem) => { relationFactory.AnalyzeADObject(aditem); }; foreach (int id in primaryGroupIDs) { adws.Enumerate(domainInfo.DefaultNamingContext, "(primaryGroupID=" + id + ")", properties, callback); } }
public void Export(string filename) { ADDomainInfo domainInfo = null; DisplayAdvancement("Starting"); ADWebService.ConnectionType = ADConnectionType.LDAPOnly; using (ADWebService adws = new ADWebService(Server, Port, Credential)) { DisplayAdvancement("Connected"); domainInfo = adws.DomainInfo; DisplayAdvancement("Building a list of all OU"); var exploration = adws.BuildOUExplorationList(domainInfo.DefaultNamingContext, 10); int currentOU = 1; int error = 0; using (StreamWriter sw = File.CreateText(filename)) { sw.WriteLine("OU\tstatus"); foreach (var ou in exploration) { DisplayAdvancement(" * Exporting OU=" + ou.OU + "(" + currentOU++ + "/" + exploration.Count + ") Type:" + ou.Scope); try { adws.Enumerate(ou.OU, "(objectClass=*)", new string[] { "distinguishedName" }, (ADItem x) => { }, ou.Scope); sw.WriteLine(ou.OU + "\tOK"); } catch (DirectoryServicesCOMException ex) { if (ex.ExtendedError == 234) { error++; Console.ForegroundColor = ConsoleColor.Red; DisplayAdvancement("The OU " + ou.OU + " has a problem"); Console.ResetColor(); sw.WriteLine(ou.OU + "\tNot OK"); } } catch (Exception) { } } } DisplayAdvancement(error + " error(s) found"); } }
List<string> GetListOfComputerToExplore() { ADDomainInfo domainInfo = null; List<string> computers = new List<string>(); using (ADWebService adws = new ADWebService(Server, Port, Credential)) { domainInfo = adws.DomainInfo; string[] properties = new string[] { "dNSHostName", "primaryGroupID" }; WorkOnReturnedObjectByADWS callback = (ADItem x) => { computers.Add(x.DNSHostName); }; adws.Enumerate(domainInfo.DefaultNamingContext, "(&(ObjectCategory=computer)(!userAccountControl:1.2.840.113556.1.4.803:=2)(lastLogonTimeStamp>=" + DateTime.Now.AddDays(-40).ToFileTimeUtc() + "))", properties, callback); } return computers; }
private ADDomainInfo GetDomainInformation(ADWebService adws) { ADDomainInfo domainInfo = null; domainInfo = adws.DomainInfo; if (adws.useLdap) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Performance warning: using LDAP instead of ADWS"); Console.ResetColor(); } // adding the domain sid string[] properties = new string[] { "objectSid", }; WorkOnReturnedObjectByADWS callback = (ADItem aditem) => { domainInfo.DomainSid = aditem.ObjectSid; }; adws.Enumerate(domainInfo.DefaultNamingContext, "(&(objectClass=domain)(distinguishedName=" + domainInfo.DefaultNamingContext + "))", properties, callback); return(domainInfo); }
public override void Export(string filename) { ADDomainInfo domainInfo = null; using (ADWebService adws = new ADWebService(Server, Port, Credential)) { domainInfo = adws.DomainInfo; int export = 0; using (StreamWriter sw = File.CreateText(filename)) { var header = new List <string>(); var hcprop = AddData.GetProperties(); header.Add("DistinguishedName"); header.Add("sAMAccountName"); header.Add("scriptPath"); header.Add("primaryGroupID"); header.Add("lastLogonTimestamp"); header.Add("pwdLastSet"); header.Add("whenCreated"); header.Add("objectClass"); header.Add("userAccountControl"); header.AddRange(hcprop); sw.WriteLine(string.Join("\t", header.ToArray())); WorkOnReturnedObjectByADWS callback = (ADItem x) => { var d = new AddData(); HealthcheckAnalyzer.ProcessAccountData(d, x, false); if ((++export % 500) == 0) { DisplayAdvancement("Exported: " + export); } var data = new List <string>(); data.Add(x.DistinguishedName); data.Add(x.SAMAccountName); data.Add(x.ScriptPath); data.Add(x.PrimaryGroupID.ToString()); data.Add(x.LastLogonTimestamp.ToString("u")); data.Add(x.PwdLastSet.ToString("u")); data.Add(x.WhenCreated.ToString("u")); data.Add(x.Class); data.Add(x.UserAccountControl.ToString()); foreach (var p in hcprop) { data.Add(d.PropertiesSet.Contains(p).ToString()); } sw.WriteLine(string.Join("\t", data.ToArray())); }; DisplayAdvancement("Starting"); adws.Enumerate(domainInfo.DefaultNamingContext, HealthcheckAnalyzer.userFilter, HealthcheckAnalyzer.userProperties, callback, "SubTree"); DisplayAdvancement("Done"); } } }
public void Export(string filename) { List <string> reference = new List <string>(); ADDomainInfo domainInfo = null; Dictionary <uint, string> attReference = null; DisplayAdvancement("Starting"); using (FileStream fsRepl = File.Create(filename + ".replData")) using (StreamWriter swRepl = new StreamWriter(fsRepl)) using (ADWebService adws = new ADWebService(Server, Port, Credential)) { domainInfo = adws.DomainInfo; DisplayAdvancement("Connected"); attReference = BuildAllAttributeDictionnary(adws); string[] properties = new string[] { "distinguishedName", "replPropertyMetaData" }; int id = 0; WorkOnReturnedObjectByADWS callback = (ADItem x) => { if (String.IsNullOrEmpty(x.DistinguishedName) || x.ReplPropertyMetaData == null) { return; } reference.Add(x.DistinguishedName); foreach (var attId in x.ReplPropertyMetaData.Keys) { var usn = x.ReplPropertyMetaData[attId].UsnLocalChange; var date = x.ReplPropertyMetaData[attId].LastOriginatingChange; swRepl.WriteLine("{0:X8},{1:X8},{2:X8},{3:X16}", usn, id, attId, date.ToFileTime()); } id++; if (id % 1000 == 0) { DisplayAdvancement(id + " objects enumerated"); } }; adws.Enumerate(domainInfo.DefaultNamingContext, "(objectClass=*)", properties, callback, "Subtree"); } DisplayAdvancement("All objects enumerated"); DisplayAdvancement("Sorting data"); Process process = new Process(); // Configure the process using the StartInfo properties. process.StartInfo.FileName = "sort.exe"; process.StartInfo.Arguments = filename + ".replData /o " + filename + ".replData2"; process.StartInfo.WindowStyle = ProcessWindowStyle.Maximized; process.Start(); process.WaitForExit(); // Waits here for the process to exit. DisplayAdvancement("data sorted"); File.Delete(filename + ".replData"); int l = 0; DateTime refDate = DateTime.MinValue; using (StreamWriter sw = File.CreateText(filename)) using (var sr = new StreamReader(filename + ".replData2")) { sw.WriteLine("PreviousUsn,PreviousObject,PreviousAttribute,PreviousDate,NewUsn,NewObject,NewAttribute,NewDate"); string previousLine = null; while (!sr.EndOfStream) { string line = sr.ReadLine(); var elt = line.Split(','); int usn = Convert.ToInt32(elt[0], 16); int id = Convert.ToInt32(elt[1], 16); uint attId = Convert.ToUInt32(elt[2], 16); DateTime date = DateTime.FromFileTime(Convert.ToInt64(elt[3], 16)); if (l != 0 && refDate.AddDays(-7) > date) { string obj = reference[id]; string attribute = "unknown(" + attId + ")"; if (attReference.ContainsKey(attId)) { attribute = attReference[attId]; } var previousElt = previousLine.Split(','); uint previousAttId = Convert.ToUInt32(previousElt[2], 16); string Previousattribute = "unknown(" + previousAttId + ")"; if (attReference.ContainsKey(previousAttId)) { Previousattribute = attReference[previousAttId]; } int previousUsn = Convert.ToInt32(previousElt[0], 16); DateTime previousDate = DateTime.FromFileTime(Convert.ToInt64(previousElt[3], 16)); sw.WriteLine(previousUsn + "," + reference[Convert.ToInt32(previousElt[1], 16)] + "," + Previousattribute + "," + previousDate.ToString("u") + "," + usn + "," + obj + "," + attribute + "," + date.ToString("u")); } refDate = date; l++; previousLine = line; } } File.Delete(filename + ".replData2"); }
public void Export(string filename) { ADDomainInfo domainInfo = null; using (ADWebService adws = new ADWebService(Server, Port, Credential)) { domainInfo = adws.DomainInfo; var computers = new List <Computer>(); DisplayAdvancement("Resolving LAPS attribute"); var attributeAdmPwd = "ms-Mcs-AdmPwd"; string[] propertiesLaps = new string[] { "name" }; // note: the LDAP request does not contain ms-MCS-AdmPwd because in the old time, MS consultant was installing customized version of the attriute, * being replaced by the company name // check the oid instead ? (which was the same even if the attribute name was not) adws.Enumerate(domainInfo.SchemaNamingContext, "(name=ms-*-AdmPwd)", propertiesLaps, (ADItem aditem) => { attributeAdmPwd = aditem.Name; }, "OneLevel"); DisplayAdvancement("LAPS attribute is " + attributeAdmPwd); DisplayAdvancement("Iterating through computer objects (all except disabled ones)"); string[] properties = new string[] { "DistinguishedName", "dNSHostName", "msDS-ReplAttributeMetaData", "whenCreated", "lastLogonTimestamp", "operatingSystem" }; WorkOnReturnedObjectByADWS callback = (ADItem x) => { var computer = new Computer() { DN = x.DistinguishedName, DNS = x.DNSHostName, WhenCreated = x.WhenCreated, LastLogonTimestamp = x.LastLogonTimestamp, OperatingSystem = x.OperatingSystem, }; if (x.msDSReplAttributeMetaData.ContainsKey(attributeAdmPwd)) { computer.HasLAPS = true; computer.LAPSLastChange = x.msDSReplAttributeMetaData[attributeAdmPwd].LastOriginatingChange; } computers.Add(computer); }; adws.Enumerate(domainInfo.DefaultNamingContext, "(&(ObjectCategory=computer)(!userAccountControl:1.2.840.113556.1.4.803:=2))", properties, callback); DisplayAdvancement("Looking for BitLocker information"); foreach (var computer in computers) { WorkOnReturnedObjectByADWS callbackBitLocker = (ADItem x) => { const string re1 = "CN=" + "([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\\\\\+|-)[0-9]{2}:[0-9]{2})\\{" + "([A-Z0-9]{8}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{12})" + "\\},"; Regex r = new Regex(re1, RegexOptions.IgnoreCase | RegexOptions.Singleline); Match m = r.Match(x.DistinguishedName); if (m.Success) { computer.HasBitLocker = true; // + sign has to be escaped in LDAP var date = DateTime.Parse(m.Groups[1].ToString().Replace("\\+", "+")); if (computer.BitLockerLastChange < date) { computer.BitLockerLastChange = date; } //string guid = m.Groups[2].ToString(); } else { Trace.WriteLine("Object found but didn't match the regex: " + x.DistinguishedName); } var d = x.DistinguishedName; }; adws.Enumerate(computer.DN, "(objectClass=*)", null, callbackBitLocker, "OneLevel"); } DisplayAdvancement("Writing to file"); using (var sw = File.CreateText(filename)) { sw.WriteLine("DN\tDNS\tWhen Created\tLast Logon Timestamp\tOperating System\tHasLAPS\tLAPS changed date\tHasBitlocker\tBitlocker change date"); foreach (var computer in computers) { sw.WriteLine(computer.DN + "\t" + computer.DNS + "\t" + computer.WhenCreated.ToString("u") + "\t" + computer.LastLogonTimestamp.ToString("u") + "\t" + computer.OperatingSystem + "\t" + computer.HasLAPS + "\t" + (computer.HasLAPS ? computer.LAPSLastChange.ToString("u") : "") + "\t" + computer.HasBitLocker + "\t" + (computer.HasBitLocker ? computer.BitLockerLastChange.ToString("u") : "")); } } DisplayAdvancement("Done"); } }