Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
1159 lines (1051 sloc) 50.3 KB
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.DirectoryServices.Protocols;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
using Sharphound2.OutputObjects;
using static Sharphound2.Sharphound;
namespace Sharphound2.Enumeration
{
internal class EnumerationRunner
{
private int _lastCount;
private int _currentCount;
private readonly Options _options;
private readonly System.Timers.Timer _statusTimer;
private readonly Utils _utils;
private string _currentDomainSid;
private string _currentDomain;
private Stopwatch _watch;
private int _noPing;
private int _timeouts;
public EnumerationRunner(Options opts)
{
_options = opts;
_utils = Utils.Instance;
_statusTimer = new System.Timers.Timer();
_statusTimer.Elapsed += (sender, e) =>
{
PrintStatus();
};
_statusTimer.AutoReset = false;
_statusTimer.Interval = _options.StatusInterval;
}
private void PrintStatus()
{
var l = _lastCount;
var c = _currentCount;
var progressStr = $"Status: {c} objects enumerated (+{c - l} {(float)c / (_watch.ElapsedMilliseconds / 1000)}/s --- Using {Process.GetCurrentProcess().PrivateMemorySize64 / 1024 / 1024 } MB RAM )";
Console.WriteLine(progressStr);
_lastCount = _currentCount;
_statusTimer.Start();
}
public void StartStealthEnumeration()
{
foreach (var domainName in _utils.GetDomainList())
{
var output = new BlockingCollection<Wrapper<OutputBase>>();
var writer = _options.Uri == null
? StartOutputWriter(output)
: StartRestWriter(output);
_currentCount = 0;
_timeouts = 0;
_noPing = 0;
_watch = Stopwatch.StartNew();
Console.WriteLine($"Starting stealth enumeration for {domainName}");
var domainSid = _utils.GetDomainSid(domainName);
var data = LdapFilter.GetLdapFilter(_options.CollectMethod, _options.ExcludeDC, true);
_statusTimer.Start();
switch (_options.CollectMethod)
{
case CollectionMethod.ObjectProps:
Console.WriteLine("Doing stealth enumeration for object properties");
foreach (var entry in _utils.DoSearch(data.Filter, SearchScope.Subtree, data.Properties, domainName))
{
var resolved = entry.ResolveAdEntry();
if (resolved == null)
{
_currentCount++;
continue;
}
OutputBase props;
if (resolved.ObjectType.Equals("computer"))
{
props = ObjectPropertyHelpers.GetComputerProps(entry, resolved);
}
else
{
props = ObjectPropertyHelpers.GetUserProps(entry, resolved);
}
if (props != null)
output.Add(new Wrapper<OutputBase> {Item = props});
_currentCount++;
}
break;
case CollectionMethod.Session:
Console.WriteLine("Doing stealth enumeration for sessions");
foreach (var path in SessionHelpers.CollectStealthTargets(domainName))
{
if (!_utils.PingHost(path.BloodHoundDisplay))
{
_noPing++;
_currentCount++;
continue;
}
try
{
var sessions = SessionHelpers.GetNetSessions(path, domainName);
foreach (var s in sessions)
{
output.Add(new Wrapper<OutputBase> {Item = s});
}
}
catch (TimeoutException)
{
_timeouts++;
}
_currentCount++;
}
break;
case CollectionMethod.ComputerOnly:
Console.WriteLine("Doing stealth enumeration for sessions");
foreach (var path in SessionHelpers.CollectStealthTargets(domainName))
{
if (!_utils.PingHost(path.BloodHoundDisplay))
{
_noPing++;
_currentCount++;
continue;
}
try
{
var sessions = SessionHelpers.GetNetSessions(path, domainName);
foreach (var s in sessions)
{
output.Add(new Wrapper<OutputBase> {Item = s});
}
}
catch (TimeoutException)
{
_timeouts++;
}
_currentCount++;
}
Console.WriteLine("Doing stealth enumeration for admins");
foreach (var entry in _utils.DoSearch(
data.Filter, SearchScope.Subtree,
data.Properties, domainName))
{
foreach (var admin in LocalAdminHelpers.GetGpoAdmins(entry, domainName))
{
output.Add(new Wrapper<OutputBase> {Item = admin});
}
_currentCount++;
}
break;
case CollectionMethod.Default:
Console.WriteLine("Doing stealth enumeration for sessions");
foreach (var path in SessionHelpers.CollectStealthTargets(domainName))
{
if (!_utils.PingHost(path.BloodHoundDisplay))
{
_noPing++;
_currentCount++;
continue;
}
try
{
var sessions = SessionHelpers.GetNetSessions(path, domainName);
foreach (var s in sessions)
{
output.Add(new Wrapper<OutputBase> {Item = s});
}
}
catch (TimeoutException)
{
_timeouts++;
}
_currentCount++;
}
Console.WriteLine("Doing stealth enumeration for admins");
foreach (var entry in _utils.DoSearch(
"(&(objectCategory=groupPolicyContainer)(name=*)(gpcfilesyspath=*))", SearchScope.Subtree,
new[] { "displayname", "name", "gpcfilesyspath" }, domainName))
{
foreach (var admin in LocalAdminHelpers.GetGpoAdmins(entry, domainName))
{
output.Add(new Wrapper<OutputBase>{Item = admin});
_currentCount++;
}
}
Console.WriteLine("Doing stealth enumeration for groups");
foreach (var entry in _utils.DoSearch("(|(memberof=*)(primarygroupid=*))",
SearchScope.Subtree,
new[]
{
"samaccountname", "distinguishedname", "dnshostname", "samaccounttype",
"primarygroupid", "memberof", "serviceprincipalname"
}, domainName))
{
var resolved = entry.ResolveAdEntry();
if (resolved == null)
{
_currentCount++;
continue;
}
if (!_utils.PingHost(resolved.BloodHoundDisplay))
{
_noPing++;
_currentCount++;
continue;
}
foreach (var group in GroupHelpers.ProcessAdObject(entry, resolved, domainSid))
{
output.Add(new Wrapper<OutputBase> {Item = group});
}
}
break;
case CollectionMethod.SessionLoop:
Console.WriteLine("Doing stealth enumeration for sessions");
foreach (var path in SessionHelpers.CollectStealthTargets(domainName))
{
if (!_utils.PingHost(path.BloodHoundDisplay))
{
_noPing++;
_currentCount++;
continue;
}
try
{
var sessions = SessionHelpers.GetNetSessions(path, domainName);
foreach (var s in sessions)
{
output.Add(new Wrapper<OutputBase> {Item = s});
}
}
catch (TimeoutException)
{
_timeouts++;
}
_currentCount++;
}
break;
case CollectionMethod.LoggedOn:
Console.WriteLine("Doing LoggedOn enumeration for stealth targets");
foreach (var path in SessionHelpers.CollectStealthTargets(domainName))
{
if (!_utils.PingHost(path.BloodHoundDisplay))
{
_noPing++;
_currentCount++;
continue;
}
var sessions = SessionHelpers.GetNetLoggedOn(path, domainName);
foreach (var s in sessions)
{
output.Add(new Wrapper<OutputBase> { Item = s });
}
sessions = SessionHelpers.GetRegistryLoggedOn(path);
foreach (var s in sessions)
{
output.Add(new Wrapper<OutputBase> { Item = s });
}
_currentCount++;
}
break;
case CollectionMethod.Group:
Console.WriteLine("Doing stealth enumeration for groups");
foreach (var entry in _utils.DoSearch(data.Filter,
SearchScope.Subtree,
data.Properties, domainName))
{
var resolved = entry.ResolveAdEntry();
if (resolved == null)
{
_currentCount++;
continue;
}
foreach (var group in GroupHelpers.ProcessAdObject(entry, resolved, domainSid))
{
output.Add(new Wrapper<OutputBase> { Item = group });
}
_currentCount++;
}
break;
case CollectionMethod.LocalGroup:
//This case will never happen
break;
case CollectionMethod.GPOLocalGroup:
Console.WriteLine("Doing stealth enumeration for admins");
foreach (var entry in _utils.DoSearch(
data.Filter, SearchScope.Subtree,
data.Properties, domainName))
{
foreach (var admin in LocalAdminHelpers.GetGpoAdmins(entry, domainName))
{
output.Add(new Wrapper<OutputBase> { Item = admin });
}
_currentCount++;
}
break;
case CollectionMethod.Trusts:
var trusts = DomainTrustEnumeration.DoTrustEnumeration(domainName);
foreach (var trust in trusts)
{
_currentCount++;
output.Add(new Wrapper<OutputBase> {Item = trust});
}
break;
case CollectionMethod.ACL:
Console.WriteLine("Doing stealth enumeration for ACLs");
foreach (var entry in _utils.DoSearch(
data.Filter,
SearchScope.Subtree,
data.Properties, domainName))
{
foreach (var acl in AclHelpers.ProcessAdObject(entry, domainName))
{
output.Add(new Wrapper<OutputBase>{Item = acl});
}
_currentCount++;
}
foreach (var a in AclHelpers.GetSyncers())
{
output.Add(new Wrapper<OutputBase> { Item = a });
}
AclHelpers.ClearSyncers();
break;
default:
throw new ArgumentOutOfRangeException();
}
output.CompleteAdding();
Utils.Verbose("Waiting for writer thread to finish");
writer.Wait();
_statusTimer.Stop();
PrintStatus();
Console.WriteLine($"Finished stealth enumeration for {domainName} in {_watch.Elapsed}");
Console.WriteLine($"{_noPing} hosts failed ping. {_timeouts} hosts timedout.");
}
if (!_options.CollectMethod.Equals(CollectionMethod.SessionLoop)) return;
if (_options.MaxLoopTime != null)
{
if (DateTime.Now > _options.LoopEnd)
{
Console.WriteLine("Exiting session loop as LoopEndTime as passed");
return;
}
}
Console.WriteLine($"Starting next session run in {_options.LoopTime} minutes");
new ManualResetEvent(false).WaitOne(_options.LoopTime * 60 * 1000);
if (_options.MaxLoopTime != null)
{
if (DateTime.Now > _options.LoopEnd)
{
Console.WriteLine("Exiting session loop as LoopEndTime as passed");
return;
}
}
Console.WriteLine("Starting next enumeration loop");
StartStealthEnumeration();
}
public void StartEnumeration()
{
//Let's determine what LDAP filter we need first
var data = LdapFilter.GetLdapFilter(_options.CollectMethod, _options.ExcludeDC, _options.Stealth);
var ldapFilter = data.Filter;
var props = data.Properties;
var c = _options.CollectMethod;
foreach (var domainName in _utils.GetDomainList())
{
_noPing = 0;
_timeouts = 0;
Console.WriteLine($"Starting enumeration for {domainName}");
_watch = Stopwatch.StartNew();
_currentDomain = domainName;
_currentDomainSid = _utils.GetDomainSid(domainName);
_currentCount = 0;
var outputQueue = new BlockingCollection<Wrapper<OutputBase>>();
if (_options.ComputerFile == null)
{
var inputQueue = new BlockingCollection<Wrapper<SearchResultEntry>>(1000);
var taskhandles = new Task[_options.Threads];
var writer = _options.Uri == null
? StartOutputWriter(outputQueue)
: StartRestWriter(outputQueue);
if (c.Equals(CollectionMethod.Trusts) ||
c.Equals(CollectionMethod.Default))
{
foreach (var domain in DomainTrustEnumeration.DoTrustEnumeration(domainName))
{
outputQueue.Add(new Wrapper<OutputBase> {Item = domain});
}
if (_options.CollectMethod.Equals(CollectionMethod.Trusts))
{
outputQueue.CompleteAdding();
writer.Wait();
continue;
}
}
if (c.Equals(CollectionMethod.Container))
{
foreach (var container in ContainerHelpers.GetContainersForDomain(domainName))
{
outputQueue.Add(new Wrapper<OutputBase> { Item = container });
}
if (_options.CollectMethod.Equals(CollectionMethod.Container))
{
outputQueue.CompleteAdding();
writer.Wait();
continue;
}
}
for (var i = 0; i < _options.Threads; i++)
{
taskhandles[i] = StartRunner(inputQueue, outputQueue);
}
_statusTimer.Start();
IEnumerable<Wrapper<SearchResultEntry>> items;
if ((c.Equals(CollectionMethod.ComputerOnly) || c.Equals(CollectionMethod.Session) ||
c.Equals(CollectionMethod.LocalGroup) || c.Equals(CollectionMethod.LoggedOn)) &&
_options.Ou != null)
{
items = _utils.DoWrappedSearch(ldapFilter, SearchScope.Subtree, props, domainName, _options.Ou);
}
else
{
items = _utils.DoWrappedSearch(ldapFilter, SearchScope.Subtree, props, domainName);
}
foreach (var item in items)
{
inputQueue.Add(item);
}
inputQueue.CompleteAdding();
Utils.Verbose("Waiting for enumeration threads to finish");
Task.WaitAll(taskhandles);
_statusTimer.Stop();
if (_options.CollectMethod.Equals(CollectionMethod.ACL))
{
foreach (var a in AclHelpers.GetSyncers())
{
outputQueue.Add(new Wrapper<OutputBase> {Item = a});
}
AclHelpers.ClearSyncers();
}
PrintStatus();
outputQueue.CompleteAdding();
Utils.Verbose("Waiting for writer thread to finish");
writer.Wait();
_watch.Stop();
Console.WriteLine($"Finished enumeration for {domainName} in {_watch.Elapsed}");
Console.WriteLine($"{_noPing} hosts failed ping. {_timeouts} hosts timedout.");
_watch = null;
}
else
{
var inputQueue = new BlockingCollection<Wrapper<string>>(1000);
var taskhandles = new Task[_options.Threads];
var writer = _options.Uri == null ? StartOutputWriter(outputQueue) : StartRestWriter(outputQueue);
for (var i = 0; i < _options.Threads; i++)
{
taskhandles[i] = StartCompListRunner(inputQueue, outputQueue);
}
_statusTimer.Start();
using (var reader = new StreamReader(_options.ComputerFile))
{
string line;
while ((line = reader.ReadLine()) != null)
{
inputQueue.Add(new Wrapper<string> {Item = line});
}
inputQueue.CompleteAdding();
}
Utils.Verbose("Waiting for enumeration threads to finish");
Task.WaitAll(taskhandles);
_statusTimer.Stop();
PrintStatus();
outputQueue.CompleteAdding();
Utils.Verbose("Waiting for writer thread to finish");
writer.Wait();
_watch.Stop();
Console.WriteLine($"Finished enumeration for {domainName} in {_watch.Elapsed}");
Console.WriteLine($"{_noPing} hosts failed ping. {_timeouts} hosts timedout.");
_watch = null;
}
}
if (!_options.CollectMethod.Equals(CollectionMethod.SessionLoop)) return;
if (_options.MaxLoopTime != null)
{
if (DateTime.Now > _options.LoopEnd)
{
Console.WriteLine("Exiting session loop as LoopEndTime as passed");
return;
}
}
Console.WriteLine($"Starting next session run in {_options.LoopTime} minutes");
new ManualResetEvent(false).WaitOne(_options.LoopTime * 60 * 1000);
if (_options.MaxLoopTime != null)
{
if (DateTime.Now > _options.LoopEnd)
{
Console.WriteLine("Exiting session loop as LoopEndTime as passed");
return;
}
}
Console.WriteLine("Starting next enumeration loop");
StartEnumeration();
}
private Task StartRunner(BlockingCollection<Wrapper<SearchResultEntry>> processQueue, BlockingCollection<Wrapper<OutputBase>> writeQueue)
{
return Task.Factory.StartNew(() =>
{
foreach (var wrapper in processQueue.GetConsumingEnumerable())
{
var entry = wrapper.Item;
var resolved = entry.ResolveAdEntry();
if (resolved == null)
{
Interlocked.Increment(ref _currentCount);
wrapper.Item = null;
continue;
}
switch (_options.CollectMethod)
{
case CollectionMethod.ObjectProps:
{
OutputBase props;
if (resolved.ObjectType.Equals("computer"))
{
props = ObjectPropertyHelpers.GetComputerProps(entry, resolved);
}
else
{
props = ObjectPropertyHelpers.GetUserProps(entry, resolved);
}
if (props != null)
writeQueue.Add(new Wrapper<OutputBase> { Item = props });
}
break;
case CollectionMethod.Group:
{
var groups = GroupHelpers.ProcessAdObject(entry, resolved, _currentDomainSid);
foreach (var g in groups)
{
writeQueue.Add(new Wrapper<OutputBase> { Item = g });
}
}
break;
case CollectionMethod.ComputerOnly:
{
if (!_utils.PingHost(resolved.BloodHoundDisplay))
{
Interlocked.Increment(ref _noPing);
break;
}
try
{
var admins = LocalAdminHelpers.GetSamAdmins(resolved);
foreach (var admin in admins)
{
writeQueue.Add(new Wrapper<OutputBase> { Item = admin });
}
}
catch (TimeoutException)
{
Interlocked.Increment(ref _timeouts);
}
if (_options.ExcludeDC && entry.DistinguishedName.Contains("OU=Domain Controllers"))
{
break;
}
try
{
var sessions = SessionHelpers.GetNetSessions(resolved, _currentDomain);
foreach (var session in sessions)
{
writeQueue.Add(new Wrapper<OutputBase> {Item = session});
}
}
catch (TimeoutException)
{
Interlocked.Increment(ref _timeouts);
}
}
break;
case CollectionMethod.LocalGroup:
{
if (!_utils.PingHost(resolved.BloodHoundDisplay))
{
Interlocked.Increment(ref _noPing);
break;
}
try
{
var admins = LocalAdminHelpers.GetSamAdmins(resolved);
foreach (var admin in admins)
{
writeQueue.Add(new Wrapper<OutputBase> {Item = admin});
}
}
catch (TimeoutException)
{
Interlocked.Increment(ref _timeouts);
}
}
break;
case CollectionMethod.GPOLocalGroup:
foreach (var admin in LocalAdminHelpers.GetGpoAdmins(entry, _currentDomain))
{
writeQueue.Add(new Wrapper<OutputBase> {Item = admin});
}
break;
case CollectionMethod.Session:
{
if (!_utils.PingHost(resolved.BloodHoundDisplay))
{
Interlocked.Increment(ref _noPing);
break;
}
if (_options.ExcludeDC && entry.DistinguishedName.Contains("OU=Domain Controllers"))
{
break;
}
try
{
var sessions = SessionHelpers.GetNetSessions(resolved, _currentDomain);
foreach (var session in sessions)
{
writeQueue.Add(new Wrapper<OutputBase> { Item = session });
}
}
catch (TimeoutException)
{
Interlocked.Increment(ref _timeouts);
}
}
break;
case CollectionMethod.LoggedOn:
{
if (!_utils.PingHost(resolved.BloodHoundDisplay))
{
Interlocked.Increment(ref _noPing);
break;
}
var sessions =
SessionHelpers.GetNetLoggedOn(resolved,
_currentDomain);
foreach (var s in sessions)
{
writeQueue.Add(new Wrapper<OutputBase> { Item = s });
}
sessions = SessionHelpers.GetRegistryLoggedOn(resolved);
foreach (var s in sessions)
{
writeQueue.Add(new Wrapper<OutputBase> { Item = s });
}
}
break;
case CollectionMethod.Trusts:
break;
case CollectionMethod.ACL:
{
var acls = AclHelpers.ProcessAdObject(entry, _currentDomain);
foreach (var a in acls)
{
writeQueue.Add(new Wrapper<OutputBase>{Item = a});
}
}
break;
case CollectionMethod.SessionLoop:
{
if (!_utils.PingHost(resolved.BloodHoundDisplay))
{
Interlocked.Increment(ref _noPing);
break;
}
if (_options.ExcludeDC && entry.DistinguishedName.Contains("OU=Domain Controllers"))
{
break;
}
try
{
var sessions = SessionHelpers.GetNetSessions(resolved, _currentDomain);
foreach (var session in sessions)
{
writeQueue.Add(new Wrapper<OutputBase> { Item = session });
}
}
catch (TimeoutException)
{
Interlocked.Increment(ref _timeouts);
}
}
break;
case CollectionMethod.Default:
{
var groups = GroupHelpers.ProcessAdObject(entry, resolved, _currentDomainSid);
foreach (var g in groups)
{
writeQueue.Add(new Wrapper<OutputBase> { Item = g });
}
if (!resolved.ObjectType.Equals("computer"))
{
break;
}
if (_options.Ou != null && !entry.DistinguishedName.Contains(_options.Ou))
{
break;
}
if (!_utils.PingHost(resolved.BloodHoundDisplay))
{
Interlocked.Increment(ref _noPing);
break;
}
try
{
var admins = LocalAdminHelpers.GetSamAdmins(resolved);
foreach (var admin in admins)
{
writeQueue.Add(new Wrapper<OutputBase> { Item = admin });
}
}
catch (TimeoutException)
{
Interlocked.Increment(ref _timeouts);
}
if (_options.ExcludeDC && entry.DistinguishedName.Contains("OU=Domain Controllers"))
{
break;
}
try
{
var sessions = SessionHelpers.GetNetSessions(resolved, _currentDomain);
foreach (var session in sessions)
{
writeQueue.Add(new Wrapper<OutputBase> { Item = session });
}
}
catch (TimeoutException)
{
Interlocked.Increment(ref _timeouts);
}
}
break;
default:
throw new ArgumentOutOfRangeException();
}
Interlocked.Increment(ref _currentCount);
wrapper.Item = null;
}
}, TaskCreationOptions.LongRunning);
}
private Task StartCompListRunner(BlockingCollection<Wrapper<string>> input,
BlockingCollection<Wrapper<OutputBase>> output)
{
return Task.Factory.StartNew(() =>
{
foreach (var wrapper in input.GetConsumingEnumerable())
{
var item = wrapper.Item;
var resolved = _utils.ResolveHost(item);
if (!_utils.PingHost(resolved))
{
Interlocked.Increment(ref _currentCount);
Interlocked.Increment(ref _noPing);
continue;
}
var netbios = Utils.GetComputerNetbiosName(resolved);
var fullItem = new ResolvedEntry
{
BloodHoundDisplay = resolved,
ComputerSamAccountName = netbios
};
var c = _options.CollectMethod;
if (c.Equals(CollectionMethod.Session) ||
c.Equals(CollectionMethod.SessionLoop) ||
c.Equals(CollectionMethod.ComputerOnly))
{
try
{
var sessions = SessionHelpers.GetNetSessions(fullItem, _currentDomain);
foreach (var session in sessions)
output.Add(new Wrapper<OutputBase> {Item = session});
}
catch (TimeoutException)
{
Interlocked.Increment(ref _timeouts);
}
}
if (c.Equals(CollectionMethod.LocalGroup) || c.Equals(CollectionMethod.ComputerOnly))
{
try
{
var admins = LocalAdminHelpers.GetSamAdmins(fullItem);
foreach (var admin in admins)
output.Add(new Wrapper<OutputBase> {Item = admin});
}
catch (TimeoutException)
{
Interlocked.Increment(ref _timeouts);
}
}
if (c.Equals(CollectionMethod.LoggedOn))
{
var sessions = SessionHelpers.GetNetLoggedOn(fullItem, _currentDomain);
sessions = sessions.Concat(SessionHelpers.GetRegistryLoggedOn(fullItem));
foreach (var session in sessions)
output.Add(new Wrapper<OutputBase> {Item = session});
}
Interlocked.Increment(ref _currentCount);
wrapper.Item = null;
}
});
}
private Task StartOutputWriter(BlockingCollection<Wrapper<OutputBase>> output)
{
return Task.Factory.StartNew(() =>
{
var adminCount = 0;
var sessionCount = 0;
var aclCount = 0;
var groupCount = 0;
var userPropsCount = 0;
var compPropsCount = 0;
var containerCount = 0;
var gplinkCount = 0;
StreamWriter admins = null;
StreamWriter sessions = null;
StreamWriter acls = null;
StreamWriter groups = null;
StreamWriter trusts = null;
StreamWriter userprops = null;
StreamWriter compprops = null;
StreamWriter containers = null;
StreamWriter gplinks = null;
foreach (var obj in output.GetConsumingEnumerable())
{
var item = obj.Item;
if (item is GroupMember)
{
if (groups == null)
{
var f = Utils.GetCsvFileName("group_membership.csv");
Utils.AddUsedFile(f);
var exists = File.Exists(f);
groups = new StreamWriter(f, exists);
if (!exists)
groups.WriteLine("GroupName,AccountName,AccountType");
}
groups.WriteLine(item.ToCsv());
groupCount++;
if (groupCount % 100 == 0)
{
groups.Flush();
}
}else if (item is Container)
{
if (containers == null)
{
var f = Utils.GetCsvFileName("container_structure.csv");
Utils.AddUsedFile(f);
var exists = File.Exists(f);
containers = new StreamWriter(f, exists);
if (!exists)
containers.WriteLine("ContainerType,ContainerName,ContainerGUID,ContainerBlocksInheritance,ObjectType,ObjectName");
}
containers.WriteLine(item.ToCsv());
containerCount++;
if (containerCount % 100 == 0)
{
containers.Flush();
}
}else if (item is GpLink)
{
if (gplinks == null)
{
var f = Utils.GetCsvFileName("container_gplinks.csv");
Utils.AddUsedFile(f);
var exists = File.Exists(f);
gplinks = new StreamWriter(f, exists);
if (!exists)
gplinks.WriteLine("ObjectType,ObjectName,ObjectGUID,GPODisplayName,GPOGuid,IsEnforced");
}
gplinks.WriteLine(item.ToCsv());
gplinkCount++;
if (gplinkCount % 100 == 0)
{
gplinks.Flush();
}
}
else if (item is UserProp)
{
if (userprops == null)
{
var f = Utils.GetCsvFileName("user_props.csv");
Utils.AddUsedFile(f);
var exists = File.Exists(f);
userprops = new StreamWriter(f, exists);
if (!exists)
userprops.WriteLine("AccountName,DisplayName,Enabled,PwdLastSet,LastLogon,Sid,SidHistory,HasSPN,ServicePrincipalNames,Email");
}
userprops.WriteLine(item.ToCsv());
userPropsCount++;
if (userPropsCount % 100 == 0)
{
userprops.Flush();
}
}
else if (item is ComputerProp)
{
if (compprops == null)
{
var f = Utils.GetCsvFileName("computer_props.csv");
Utils.AddUsedFile(f);
var exists = File.Exists(f);
compprops = new StreamWriter(f, exists);
if (!exists)
compprops.WriteLine("AccountName,Enabled,UnconstrainedDelegation,PwdLastSet,LastLogon,OperatingSystem,Sid");
}
compprops.WriteLine(item.ToCsv());
compPropsCount++;
if (compPropsCount % 100 == 0)
{
compprops.Flush();
}
}
else if (item is Session)
{
if (sessions == null)
{
var f = Utils.GetCsvFileName("sessions.csv");
Utils.AddUsedFile(f);
var exists = File.Exists(f);
sessions = new StreamWriter(f, exists);
if (!exists)
sessions.WriteLine("UserName,ComputerName,Weight");
}
sessions.WriteLine(item.ToCsv());
sessionCount++;
if (sessionCount % 100 == 0)
{
sessions.Flush();
}
}
else if (item is LocalAdmin)
{
if (admins == null)
{
var f = Utils.GetCsvFileName("local_admins.csv");
Utils.AddUsedFile(f);
var exists = File.Exists(f);
admins = new StreamWriter(f, exists);
if (!exists)
admins.WriteLine("ComputerName,AccountName,AccountType");
}
admins.WriteLine(item.ToCsv());
adminCount++;
if (adminCount % 100 == 0)
{
admins.Flush();
}
}
else if (item is ACL)
{
if (acls == null)
{
var f = Utils.GetCsvFileName("acls.csv");
Utils.AddUsedFile(f);
var exists = File.Exists(f);
acls = new StreamWriter(f, exists);
if (!exists)
acls.WriteLine(
"ObjectName,ObjectType,PrincipalName,PrincipalType,ActiveDirectoryRights,ACEType,AccessControlType,IsInherited");
}
acls.WriteLine(item.ToCsv());
aclCount++;
if (aclCount % 100 == 0)
{
acls.Flush();
}
}
else if (item is DomainTrust)
{
if (trusts == null)
{
var f = Utils.GetCsvFileName("trusts.csv");
Utils.AddUsedFile(f);
var exists = File.Exists(f);
trusts = new StreamWriter(f, exists);
if (!exists)
trusts.WriteLine("SourceDomain,TargetDomain,TrustDirection,TrustType,Transitive");
}
trusts.WriteLine(item.ToCsv());
trusts.Flush();
}
obj.Item = null;
}
groups?.Dispose();
sessions?.Dispose();
acls?.Dispose();
admins?.Dispose();
trusts?.Dispose();
userprops?.Dispose();
compprops?.Dispose();
containers?.Dispose();
gplinks?.Dispose();
}, TaskCreationOptions.LongRunning);
}
private Task StartRestWriter(BlockingCollection<Wrapper<OutputBase>> output)
{
return Task.Factory.StartNew(() =>
{
var objectCount = 0;
using (var client = new WebClient())
{
client.Headers.Add("content-type", "application/json");
client.Headers.Add("Accept", "application/json; charset=UTF-8");
client.Headers.Add("Authorization", _options.GetEncodedUserPass());
var coll = new RestOutput();
var serializer = new JavaScriptSerializer();
foreach (var obj in output.GetConsumingEnumerable())
{
var item = obj.Item;
if (item is DomainTrust temp)
{
foreach (var x in temp.ToMultipleParam())
{
coll.AddNewData(temp.TypeHash(), x);
}
}else if (item is ACL acl)
{
foreach (var x in acl.GetAllTypeHashes())
{
coll.AddNewData(x, acl.ToParam());
}
}
else
{
coll.AddNewData(item.TypeHash(), item.ToParam());
}
obj.Item = null;
objectCount++;
if (objectCount % 500 != 0) continue;
var data = serializer.Serialize(coll.GetStatements());
client.UploadData(_options.GetURI(), "POST", Encoding.Default.GetBytes(data));
coll.Reset();
}
var remainingData = serializer.Serialize(coll.GetStatements());
client.UploadData(_options.GetURI(), "POST", Encoding.Default.GetBytes(remainingData));
//var responseArray = client.UploadData(_options.GetURI(), "POST", Encoding.Default.GetBytes(remainingData));
//Console.WriteLine(Encoding.ASCII.GetString(responseArray));
}
}, TaskCreationOptions.LongRunning);
}
}
}