diff --git a/src/Client/Enums.cs b/src/Client/Enums.cs index cec91c5..1cd0e61 100644 --- a/src/Client/Enums.cs +++ b/src/Client/Enums.cs @@ -32,8 +32,9 @@ public enum CollectionMethodOptions SmbInfo, NTLMRegistry, Site, + AzureRegistry, // Re-introduce this when we're ready for Event Log collection // EventLogs, All } -} \ No newline at end of file +} diff --git a/src/Options.cs b/src/Options.cs index 1c22af4..91e816e 100644 --- a/src/Options.cs +++ b/src/Options.cs @@ -14,7 +14,7 @@ public class Options // Options that affect what is collected [Option('c', "collectionmethods", Default = new[] { "Default" }, HelpText = - "Collection Methods: Group, LocalGroup, LocalAdmin, RDP, DCOM, PSRemote, Session, Trusts, ACL, Container, ComputerOnly, GPOLocalGroup, LoggedOn, ObjectProps, SPNTargets, UserRights, Default, DCOnly, CARegistry, DCRegistry, CertServices, Site, WebClientService, LdapServices, SmbInfo, NTLMRegistry, All")] + "Collection Methods: Group, LocalGroup, LocalAdmin, RDP, DCOM, PSRemote, Session, Trusts, ACL, Container, ComputerOnly, GPOLocalGroup, LoggedOn, ObjectProps, SPNTargets, UserRights, Default, DCOnly, CARegistry, DCRegistry, CertServices, Site, WebClientService, LdapServices, SmbInfo, NTLMRegistry, AzureRegistry, All")] public IEnumerable CollectionMethods { get; set; } [Option('d', "domain", Default = null, HelpText = "Specify domain to enumerate")] @@ -211,7 +211,9 @@ internal bool ResolveCollectionMethods(ILogger logger, out CollectionMethod reso CollectionMethodOptions.LdapServices => CollectionMethod.LdapServices, CollectionMethodOptions.SmbInfo => CollectionMethod.SmbInfo, CollectionMethodOptions.NTLMRegistry => CollectionMethod.NTLMRegistry, - CollectionMethodOptions.Site => CollectionMethod.Site, + CollectionMethodOptions.Site => CollectionMethod.Site, + CollectionMethodOptions.AzureRegistry => CollectionMethod.AzureRegistry, + // Re-introduce this when we're ready for Event Log collection // CollectionMethodOptions.EventLogs => CollectionMethod.EventLogs, CollectionMethodOptions.All => CollectionMethod.All, @@ -278,6 +280,11 @@ internal bool ResolveCollectionMethods(ILogger logger, out CollectionMethod reso updates.Add("[-] Removed NTLMRegistry Collection"); } + if ((resolved & CollectionMethod.AzureRegistry) != 0) { + resolved ^= CollectionMethod.AzureRegistry; + updates.Add("[-] Removed AzureRegistry Collection"); + } + if (localGroupRemoved) { resolved |= CollectionMethod.GPOLocalGroup; diff --git a/src/PowerShell/Template.ps1 b/src/PowerShell/Template.ps1 index 676e789..53c8ded 100644 --- a/src/PowerShell/Template.ps1 +++ b/src/PowerShell/Template.ps1 @@ -35,6 +35,7 @@ UserRights - Collect User Rights Assignment from domain computers (needs admin) CARegistry - Collect ADCS properties from registry of Certificate Authority servers DCRegistry - Collect properties from registry of Domain Controller servers + AzureRegistry - Read Registry for Azure specific values such as the Azure guest VmId and add it to each Computer object's properties CertServices - Collect ADCS objects from Certificate Services Site - Collect AD site, site server, and site subnet data All - Collect all data diff --git a/src/Runtime/ObjectProcessors.cs b/src/Runtime/ObjectProcessors.cs index a60e786..66c975f 100644 --- a/src/Runtime/ObjectProcessors.cs +++ b/src/Runtime/ObjectProcessors.cs @@ -385,16 +385,22 @@ await HandleCompStatusEvent(new CSVComputerStatus { if (_methods.HasFlag(CollectionMethod.NTLMRegistry)) { await _context.DoDelay(); - var processor = _registryProcessorMap.GetOrAdd( - resolvedSearchResult.DomainSid, - _ => new Lazy(() => { - var newProcessor = new RegistryProcessor(null, new StrategyExecutor(), resolvedSearchResult.Domain); - newProcessor.ComputerStatusEvent += HandleCompStatusEvent; - return newProcessor; - })).Value; + var processor = GetRegistryProcessor(resolvedSearchResult); ret.NTLMRegistryData = await processor.ReadRegistrySettings(resolvedSearchResult.DisplayName); } + if (_methods.HasFlag(CollectionMethod.AzureRegistry)) { + await _context.DoDelay(); + var processor = GetRegistryProcessor(resolvedSearchResult); + + // Currently these values are added as properties. Future work is needed to refine to a more dedicated + // portion of the return object, as more collected values fill this returned object. + var azureRegistryData = await processor.ReadAzureRegistryData(apiName); + if (azureRegistryData.Collected) { + ret.Properties["azvmid"] = azureRegistryData.Result.VmId; + } + } + if (_methods.HasFlag(CollectionMethod.WebClientService)) { ret.IsWebClientRunning = await _webClientProcessor.IsWebClientRunning(apiName); } @@ -437,6 +443,16 @@ await HandleCompStatusEvent(new CSVComputerStatus { return ret; } + private RegistryProcessor GetRegistryProcessor(ResolvedSearchResult resolvedSearchResult) { + return _registryProcessorMap.GetOrAdd( + resolvedSearchResult.DomainSid, + _ => new Lazy(() => { + var processor = new RegistryProcessor(null, new StrategyExecutor(), resolvedSearchResult.Domain); + processor.ComputerStatusEvent += HandleCompStatusEvent; + return processor; + })).Value; + } + private async void ProcessDomainController(ResolvedSearchResult resolvedSearchResult, Computer ret, string apiName) { _log.LogDebug("Processing DC: {dc}", apiName);