Skip to content

Commit 35b3425

Browse files
committed
Merge branch 'v4' into poc/metrics
2 parents f6df3ca + 52b978a commit 35b3425

15 files changed

Lines changed: 1057 additions & 311 deletions

src/CommonLib/Helpers.cs

Lines changed: 1 addition & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@
77
using System.Text.RegularExpressions;
88
using SharpHoundCommonLib.Enums;
99
using Microsoft.Extensions.Logging;
10-
using System.IO;
11-
using System.Security;
12-
using SharpHoundCommonLib.Processors;
13-
using Microsoft.Win32;
1410
using System.Threading.Tasks;
1511

1612
namespace SharpHoundCommonLib {
@@ -151,7 +147,7 @@ public static string DistinguishedNameToDomain(string distinguishedName) {
151147
}
152148

153149
/// <summary>
154-
/// Converts a domain name to a distinguished name using simple string substitution
150+
/// Converts a domain name to a distinguished name using simple string substitution
155151
/// </summary>
156152
/// <param name="domainName"></param>
157153
/// <returns></returns>
@@ -258,44 +254,6 @@ public static bool IsSidFiltered(string sid) {
258254
return false;
259255
}
260256

261-
public static RegistryResult GetRegistryKeyData(string target, string subkey, string subvalue, ILogger log) {
262-
var data = new RegistryResult();
263-
264-
try {
265-
var baseKey = OpenRemoteRegistry(target);
266-
var value = baseKey.GetValue(subkey, subvalue);
267-
data.Value = value;
268-
269-
data.Collected = true;
270-
}
271-
catch (IOException e) {
272-
log.LogDebug(e, "Error getting data from registry for {Target}: {RegSubKey}:{RegValue}",
273-
target, subkey, subvalue);
274-
data.FailureReason = "Target machine was not found or not connectable";
275-
}
276-
catch (SecurityException e) {
277-
log.LogDebug(e, "Error getting data from registry for {Target}: {RegSubKey}:{RegValue}",
278-
target, subkey, subvalue);
279-
data.FailureReason = "User does not have the proper permissions to perform this operation";
280-
}
281-
catch (UnauthorizedAccessException e) {
282-
log.LogDebug(e, "Error getting data from registry for {Target}: {RegSubKey}:{RegValue}",
283-
target, subkey, subvalue);
284-
data.FailureReason = "User does not have the necessary registry rights";
285-
}
286-
catch (Exception e) {
287-
log.LogDebug(e, "Error getting data from registry for {Target}: {RegSubKey}:{RegValue}",
288-
target, subkey, subvalue);
289-
data.FailureReason = e.Message;
290-
}
291-
292-
return data;
293-
}
294-
295-
public static IRegistryKey OpenRemoteRegistry(string target) {
296-
return SHRegistryKey.Connect(RegistryHive.LocalMachine, target).GetAwaiter().GetResult();
297-
}
298-
299257
public static string[] AuthenticationOIDs = new string[] {
300258
CommonOids.ClientAuthentication,
301259
CommonOids.PKINITClientAuthentication,

src/CommonLib/IRegistryAccessor.cs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
using System;
2+
using System.IO;
3+
using System.Security;
4+
using System.Threading.Tasks;
5+
using Microsoft.Extensions.Logging;
6+
using Microsoft.Win32;
7+
using SharpHoundCommonLib.Processors;
8+
9+
namespace SharpHoundCommonLib {
10+
public interface IRegistryAccessor {
11+
public RegistryResult GetRegistryKeyData(string target, string subkey, string subvalue);
12+
public IRegistryKey OpenRemoteRegistry(string target);
13+
public Task<IRegistryKey> Connect(RegistryHive hive, string machineName);
14+
}
15+
16+
public class RegistryAccessor : IRegistryAccessor {
17+
private readonly ILogger _log;
18+
private readonly AdaptiveTimeout _adaptiveTimeout;
19+
20+
public RegistryAccessor(ILogger log = null) {
21+
_log = log ?? Logging.LogProvider.CreateLogger(nameof(RegistryAccessor));
22+
_adaptiveTimeout = new AdaptiveTimeout(maxTimeout: TimeSpan.FromSeconds(10), _log);
23+
}
24+
25+
public RegistryResult GetRegistryKeyData(string target, string subkey, string subvalue) {
26+
var data = new RegistryResult();
27+
28+
try {
29+
using (var baseKey = OpenRemoteRegistry(target)) {
30+
var value = baseKey.GetValue(subkey, subvalue);
31+
data.Value = value;
32+
data.Collected = true;
33+
}
34+
}
35+
catch (IOException e) {
36+
_log.LogDebug(e, "Error getting data from registry for {Target}: {RegSubKey}:{RegValue}",
37+
target, subkey, subvalue);
38+
data.FailureReason = "Target machine was not found or not connectable";
39+
}
40+
catch (SecurityException e) {
41+
_log.LogDebug(e, "Error getting data from registry for {Target}: {RegSubKey}:{RegValue}",
42+
target, subkey, subvalue);
43+
data.FailureReason = "User does not have the proper permissions to perform this operation";
44+
}
45+
catch (UnauthorizedAccessException e) {
46+
_log.LogDebug(e, "Error getting data from registry for {Target}: {RegSubKey}:{RegValue}",
47+
target, subkey, subvalue);
48+
data.FailureReason = "User does not have the necessary registry rights";
49+
}
50+
catch (Exception e) {
51+
_log.LogDebug(e, "Error getting data from registry for {Target}: {RegSubKey}:{RegValue}",
52+
target, subkey, subvalue);
53+
data.FailureReason = e.Message;
54+
}
55+
56+
return data;
57+
}
58+
59+
public IRegistryKey OpenRemoteRegistry(string target) {
60+
return Connect(RegistryHive.LocalMachine, target).GetAwaiter().GetResult();
61+
}
62+
63+
/// <summary>
64+
/// Gets a handle to a remote registry.
65+
/// </summary>
66+
/// <param name="hive"></param>
67+
/// <param name="machineName"></param>
68+
/// <returns></returns>
69+
/// <exception cref="TimeoutException"></exception>
70+
/// <exception cref="ArgumentException"></exception>
71+
/// <exception cref="System.IO.IOException"></exception>
72+
/// <exception cref="ArgumentNullException"></exception>
73+
/// <exception cref="System.Security.SecurityException"></exception>
74+
/// <exception cref="UnauthorizedAccessException"></exception>
75+
public async Task<IRegistryKey> Connect(RegistryHive hive, string machineName) {
76+
var remoteKey = await _adaptiveTimeout.ExecuteWithTimeout((_) => RegistryKey.OpenRemoteBaseKey(hive, machineName));
77+
if (remoteKey.IsSuccess)
78+
return new SHRegistryKey(remoteKey.Value);
79+
throw new TimeoutException($"Failed to connect to registry on {machineName}: {remoteKey.Error}");
80+
}
81+
}
82+
}

src/CommonLib/IRegistryKey.cs

Lines changed: 4 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
using System;
2-
using System.Threading.Tasks;
32
using Microsoft.Win32;
43

54
namespace SharpHoundCommonLib {
6-
public interface IRegistryKey {
5+
public interface IRegistryKey: IDisposable {
76
public object GetValue(string subkey, string name);
87
public string[] GetSubKeyNames();
98
}
109

11-
public class SHRegistryKey : IRegistryKey, IDisposable {
10+
public class SHRegistryKey : IRegistryKey {
1211
private readonly RegistryKey _currentKey;
13-
private static readonly AdaptiveTimeout _adaptiveTimeout = new AdaptiveTimeout(maxTimeout: TimeSpan.FromSeconds(10), Logging.LogProvider.CreateLogger(nameof(SHRegistryKey)));
14-
15-
private SHRegistryKey(RegistryKey registryKey) {
12+
13+
public SHRegistryKey(RegistryKey registryKey) {
1614
_currentKey = registryKey;
1715
}
1816

@@ -23,38 +21,8 @@ public object GetValue(string subkey, string name) {
2321

2422
public string[] GetSubKeyNames() => _currentKey.GetSubKeyNames();
2523

26-
/// <summary>
27-
/// Gets a handle to a remote registry.
28-
/// </summary>
29-
/// <param name="hive"></param>
30-
/// <param name="machineName"></param>
31-
/// <returns></returns>
32-
/// <exception cref="TimeoutException"></exception>
33-
/// <exception cref="ArgumentException"></exception>
34-
/// <exception cref="System.IO.IOException"></exception>
35-
/// <exception cref="ArgumentNullException"></exception>
36-
/// <exception cref="System.Security.SecurityException"></exception>
37-
/// <exception cref="UnauthorizedAccessException"></exception>
38-
public static async Task<SHRegistryKey> Connect(RegistryHive hive, string machineName) {
39-
var remoteKey = await _adaptiveTimeout.ExecuteWithTimeout((_) => RegistryKey.OpenRemoteBaseKey(hive, machineName));
40-
if (remoteKey.IsSuccess)
41-
return new SHRegistryKey(remoteKey.Value);
42-
throw new TimeoutException($"Failed to connect to registry on {machineName}: {remoteKey.Error}");
43-
}
44-
4524
public void Dispose() {
4625
_currentKey.Dispose();
4726
}
4827
}
49-
50-
public class MockRegistryKey : IRegistryKey {
51-
public virtual object GetValue(string subkey, string name) {
52-
//Unimplemented
53-
return default;
54-
}
55-
56-
public virtual string[] GetSubKeyNames() {
57-
throw new NotImplementedException();
58-
}
59-
}
6028
}

0 commit comments

Comments
 (0)