55using System . Net . Sockets ;
66using System . Text ;
77using System . Threading . Tasks ;
8+ using SharpHoundRPC ;
89
910namespace SharpHoundCommonLib . Processors {
1011 /// <summary>
@@ -16,43 +17,85 @@ namespace SharpHoundCommonLib.Processors {
1617 /// </summary>
1718 /// <param name="timeoutMs"></param>
1819 /// <param name="log"></param>
19- public class SmbProcessor ( int timeoutMs , ILogger log = null ) {
20- private readonly ILogger _log = log ?? Logging . LogProvider . CreateLogger ( "SmbProcessor" ) ;
21-
22- public async Task < APIResult < SmbInfo > > Scan ( string host ) {
23- var scanner = new SmbScanner ( ) ;
24- var result = await scanner . Scan ( host , 445 , timeoutMs ) ;
25-
26- if ( result . Success && result . Info != null ) {
27- var info = new SmbInfo ( ) {
28- SigningEnabled = result . Info . SmbSigning ,
29- OsVersion = result . Info . OsVersion ,
30- OsBuild = result . Info . OsBuildNumber . ToString ( ) ,
31- DnsComputerName = result . Info . DnsComputerName ,
32- } ;
33-
34- return APIResult < SmbInfo > . Success ( info ) ;
35- } else {
36- return APIResult < SmbInfo > . Failure ( result . ErrorMessage ?? "Unknown error" ) ;
20+ public class SmbProcessor
21+ {
22+ //TODO: Have this class take in our portscanner class and use that
23+ public delegate Task ComputerStatusDelegate ( CSVComputerStatus status ) ;
24+ private readonly ILogger _log ;
25+ private readonly SmbScanner _smbScanner ;
26+ private readonly int _timeoutMs ;
27+
28+ public SmbProcessor ( int timeoutMs , SmbScanner smbScanner = null , ILogger log = null )
29+ {
30+ _timeoutMs = timeoutMs ;
31+ _smbScanner = smbScanner ?? new SmbScanner ( ) ;
32+ _log = log ?? Logging . LogProvider . CreateLogger ( "SmbProcessor" ) ;
33+ }
34+
35+ public event ComputerStatusDelegate ComputerStatusEvent ;
36+ public virtual async Task < APIResult < SmbInfo > > Scan ( string host , TimeSpan timeout = default ) {
37+ if ( timeout == default ) {
38+ timeout = TimeSpan . FromMinutes ( 2 ) ;
3739 }
40+
41+ var result = await Task . Run ( ( ) => _smbScanner . Scan ( host , 445 , _timeoutMs ) ) . TimeoutAfter ( timeout ) ;
42+
43+ if ( result . IsFailed ) {
44+ await SendComputerStatus ( new CSVComputerStatus {
45+ Status = result . Error ,
46+ Task = "SmbScan" ,
47+ ComputerName = host
48+ } ) ;
49+ _log . LogTrace ( "SmbScan failed on {ComputerName}: {Status}" , host , result . Status ) ;
50+ return APIResult < SmbInfo > . Failure ( result . Status . ToString ( ) ) ;
51+ }
52+
53+ if ( result . Value . Info == null )
54+ {
55+ await SendComputerStatus ( new CSVComputerStatus {
56+ Status = result . Error ?? "Unknown error" ,
57+ Task = "SmbScan" ,
58+ ComputerName = host
59+ } ) ;
60+ _log . LogTrace ( "SmbScan failed on {ComputerName}: {Status}" , host , result . Status ) ;
61+ return APIResult < SmbInfo > . Failure ( result . Error ?? "Unknown error" ) ;
62+ }
63+
64+ _log . LogDebug ( "SmbScan succeeded on {ComputerName}" , host ) ;
65+ await SendComputerStatus ( new CSVComputerStatus {
66+ Status = CSVComputerStatus . StatusSuccess ,
67+ Task = "SmbScan" ,
68+ ComputerName = host
69+ } ) ;
70+
71+ var info = new SmbInfo ( ) {
72+ SigningEnabled = result . Value . Info . SmbSigning ,
73+ OsVersion = result . Value . Info . OsVersion ,
74+ OsBuild = result . Value . Info . OsBuildNumber . ToString ( ) ,
75+ DnsComputerName = result . Value . Info . DnsComputerName ,
76+ } ;
77+
78+ return APIResult < SmbInfo > . Success ( info ) ;
79+
80+ }
81+
82+ private async Task SendComputerStatus ( CSVComputerStatus status ) {
83+ if ( ComputerStatusEvent is not null ) await ComputerStatusEvent . Invoke ( status ) ;
3884 }
3985 }
4086
41-
4287 public enum SmbVersion {
4388 Unknown ,
4489 SMBv1 ,
4590 SMBv2
4691 }
4792
48- public class SmbScanResult {
49- public SmbScanResult ( string host ) {
93+ public class SmbScanInfo {
94+ public SmbScanInfo ( string host ) {
5095 Host = host ;
5196 }
5297
5398 public string Host { get ; set ; }
54- public bool Success { get ; set ; }
55- public string ErrorMessage { get ; set ; }
5699 public NTLMInfo Info { get ; set ; }
57100 public SmbVersion SmbVersion { get ; set ; }
58101 }
@@ -150,9 +193,8 @@ public static NTLMInfo FromBytes(byte[] buf) {
150193 }
151194
152195 public class SmbScanner {
153- public async Task < SmbScanResult > Scan ( string host , int port , int timeoutMs = 10000 ) {
154- var result = new SmbScanResult ( host ) {
155- Success = false ,
196+ public virtual async Task < SharpHoundRPC . Result < SmbScanInfo > > Scan ( string host , int port , int timeoutMs = 10000 ) {
197+ var scanInfo = new SmbScanInfo ( host ) {
156198 SmbVersion = SmbVersion . Unknown
157199 } ;
158200
@@ -162,8 +204,7 @@ public async Task<SmbScanResult> Scan(string host, int port, int timeoutMs = 100
162204 smbClient = await ConnectAsync ( host , port , timeoutMs ) ;
163205
164206 if ( ! smbClient . Connected ) {
165- result . ErrorMessage = "SMBInfo can't connect!" ;
166- return result ;
207+ return SharpHoundRPC . Result < SmbScanInfo > . Fail ( "SMBInfo can't connect!" ) ;
167208 }
168209
169210 var smbClientStream = smbClient . GetStream ( ) ;
@@ -199,14 +240,13 @@ public async Task<SmbScanResult> Scan(string host, int port, int timeoutMs = 100
199240 }
200241
201242 if ( ss . Length >= 2 ) {
202- result . Info = NTLMInfo . FromBytes ( smbClientReceive ) ;
203- result . Info . NativeOs = ss [ 0 ] ;
204- result . Info . NativeLanManager = ss [ 1 ] ;
205- result . Info . SmbSigning = signingEnabled ;
243+ scanInfo . Info = NTLMInfo . FromBytes ( smbClientReceive ) ;
244+ scanInfo . Info . NativeOs = ss [ 0 ] ;
245+ scanInfo . Info . NativeLanManager = ss [ 1 ] ;
246+ scanInfo . Info . SmbSigning = signingEnabled ;
206247 }
207248
208- result . SmbVersion = SmbVersion . SMBv1 ;
209- result . Success = true ;
249+ scanInfo . SmbVersion = SmbVersion . SMBv1 ;
210250 } catch {
211251 // If SMBv1 fails, try SMBv2 with a new connection
212252 if ( smbClient != null ) {
@@ -221,8 +261,7 @@ public async Task<SmbScanResult> Scan(string host, int port, int timeoutMs = 100
221261 if ( BitConverter . ToString ( [
222262 smbClientReceive [ 4 ] , smbClientReceive [ 5 ] , smbClientReceive [ 6 ] , smbClientReceive [ 7 ]
223263 ] ) . ToLower ( ) == "ff-53-4d-42" ) {
224- result . ErrorMessage = "Could not connect with SMBv2" ;
225- return result ;
264+ return SharpHoundRPC . Result < SmbScanInfo > . Fail ( "Could not connect with SMBv2" ) ;
226265 }
227266
228267 var signingEnabled = BitConverter . ToString ( [ smbClientReceive [ 70 ] ] ) == "03" ;
@@ -233,19 +272,18 @@ public async Task<SmbScanResult> Scan(string host, int port, int timeoutMs = 100
233272 smbClientReceive = await SendStreamAsync ( smbClientStream , GetNTLMSSPNegotiatev2Data ( smbPackets ) ,
234273 operationCts . Token ) ;
235274
236- result . Info = NTLMInfo . FromBytes ( smbClientReceive ) ;
237- result . Info . SmbSigning = smbPackets . SMB_Signing ;
275+ scanInfo . Info = NTLMInfo . FromBytes ( smbClientReceive ) ;
276+ scanInfo . Info . SmbSigning = smbPackets . SMB_Signing ;
238277
239- result . SmbVersion = SmbVersion . SMBv2 ;
240- result . Success = true ;
278+ scanInfo . SmbVersion = SmbVersion . SMBv2 ;
241279 }
242280 } catch ( Exception ex ) {
243- result . ErrorMessage = ex . Message ;
281+ return SharpHoundRPC . Result < SmbScanInfo > . Fail ( ex . Message ) ;
244282 } finally {
245283 smbClient ? . Close ( ) ;
246284 }
247285
248- return result ;
286+ return SharpHoundRPC . Result < SmbScanInfo > . Ok ( scanInfo ) ;
249287 }
250288
251289 private static async Task < TcpClient > ConnectAsync ( string host , int port , int timeoutMs ) {
0 commit comments