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+ }
0 commit comments