@@ -22,8 +22,10 @@ Module WindowsServiceHelper
2222 Private PrivilegeMappingDictionary As New Dictionary( Of String , String )
2323
2424 Sub FillInConstants()
25+ DynaLog.LogMessage( "Clearing dictionaries..." )
2526 PrivilegeConstantDictionary.Clear()
2627 PrivilegeMappingDictionary.Clear()
28+ DynaLog.LogMessage( "Filling privilege constant dictionary..." )
2729 PrivilegeConstantDictionary.Add( "SE_ASSIGNPRIMARYTOKEN_NAME" ,
2830 New NTSecurityPrivilegeConstant(
2931 "SeAssignPrimaryTokenPrivilege" ,
@@ -205,15 +207,18 @@ Module WindowsServiceHelper
205207 "Not applicable" ,
206208 "Required to read unsolicited input from a terminal device." ))
207209
210+ DynaLog.LogMessage( "Filling privilege mapping dictionary..." )
208211 For Each key As String In PrivilegeConstantDictionary.Keys
209212 Dim privilegeConstant As NTSecurityPrivilegeConstant = PrivilegeConstantDictionary( key )
210213 PrivilegeMappingDictionary.Add(privilegeConstant.ConstantNameText, key )
211214 Next
212215 End Sub
213216
214217 Private Function ResolveIndirectString(source As String ) As String
218+ DynaLog.LogMessage( "Resolving indirect string " & source & "..." )
215219 Dim buffer As New StringBuilder( 260 )
216220 Dim hr As Integer = NativeMethods.SHLoadIndirectString(source, buffer, buffer.Capacity, IntPtr.Zero)
221+ DynaLog.LogMessage( "Resolver Result: " & hr)
217222 If hr = 0 Then
218223 Return buffer.ToString()
219224 Else
@@ -222,10 +227,14 @@ Module WindowsServiceHelper
222227 End Function
223228
224229 Private Function ParseInfLine(line As String ) As Tuple( Of String , String )
230+ DynaLog.LogMessage( "Parsing provided INF file line..." )
231+ DynaLog.LogMessage( "- Line: " & line)
225232 Dim noComment = line.Split( ";"c )( 0 ).Trim()
226233 Dim parts = noComment.Split( ","c )
227234
235+ DynaLog.LogMessage( "Line Parts Length: " & parts.Length)
228236 If parts.Length < 2 Then
237+ DynaLog.LogMessage( "Line Parts Length below minimum threshold." )
229238 Return Nothing
230239 End If
231240
@@ -236,9 +245,13 @@ Module WindowsServiceHelper
236245 End Function
237246
238247 Private Function ResolveInfToken(infPath As String , token As String ) As String
248+ DynaLog.LogMessage( "Resolving INF File Tokens..." )
249+ DynaLog.LogMessage( "- INF File Path: " & infPath)
250+ DynaLog.LogMessage( "- Token: " & token)
239251 Try
240252 Dim key As String = token.Trim( "%"c )
241253
254+ DynaLog.LogMessage( "Opening file for read access..." )
242255 Dim lines As String () = File.ReadAllLines(infPath)
243256 Dim inStrings As Boolean = False
244257 For Each line In lines
@@ -253,12 +266,13 @@ Module WindowsServiceHelper
253266
254267 Dim match = Regex.Match(lineTrim, "^(?<k>[^\s=]+)\s*=\s*""?(?<v>[^""]+)""?$" )
255268 If match.Success AndAlso match.Groups( "k" ).Value.Equals( key , StringComparison.OrdinalIgnoreCase) Then
269+ DynaLog.LogMessage( "Found a suitable match! Returning..." )
256270 Return match.Groups( "v" ).Value
257271 End If
258272 End If
259273 Next
260274 Catch ex As Exception
261-
275+ DynaLog.LogMessage( "Could not resolve token. Error message: " & ex.Message)
262276 End Try
263277 Return ""
264278 End Function
@@ -267,21 +281,31 @@ Module WindowsServiceHelper
267281 ' For the required privileges a service may have, we have to fill in the constants first so that we don't have things like
268282 ' "SeUndockPrivilege", "SeShutdownPrivilege"; but rather "Remove computer from docking station", and so on... we want the
269283 ' friendly things.
284+ DynaLog.LogMessage( "Preparing to get all services in this image..." )
285+ DynaLog.LogMessage( "- Mount Path: " & MountPath)
286+ DynaLog.LogMessage( "Filling dictionaries..." )
270287 FillInConstants()
271288 Dim serviceList As New List( Of WindowsService)
272289
273290 ' Time to load up a registry hive
291+ DynaLog.LogMessage( "Loading mount path SYSTEM hive..." )
274292 If RegistryHelper.LoadRegistryHive(Path.Combine(MountPath, "Windows" , "system32" , "config" , "SYSTEM" ), "HKLM\zSYS" ) = 0 Then
293+ DynaLog.LogMessage( "Load operation succeeded. Continuing..." )
275294 Try
276295 ' First we need to grab the default control set of the target image
296+ DynaLog.LogMessage( "Determining default control set..." )
277297 Dim DefaultControlSet As Integer = RegistryHelper.GetDefaultControlSet( "zSYS" )
298+ DynaLog.LogMessage( "Determined control set: " & DefaultControlSet)
278299 If DefaultControlSet = - 1 Then
300+ DynaLog.LogMessage( "Control set is wrong." )
279301 Throw New Exception( "Registry control set could not be obtained" )
280302 End If
281303 ' We only document a maximum of 999 control sets. CurrentControlSet is not a thing in an offline system, as the registry
282304 ' subsystems guess the control set to use based on values in HKLM\SYSTEM\Select.
305+ DynaLog.LogMessage( "Opening mount path services key for read access..." )
283306 Dim ServiceRk As RegistryKey = Registry.LocalMachine.OpenSubKey( String .Format( "zSYS\ControlSet{0}\Services" , DefaultControlSet.ToString().PadLeft( 3 , "0" )), False )
284307 ' For some stupid reason, .NET keys are stored in HKLM\SYSTEM\ControlSet<nnn>\Services. GUID keys are also not allowed
308+ DynaLog.LogMessage( "Getting service names..." )
285309 Dim ServiceNames() As String = ServiceRk.GetSubKeyNames().Where( Function (serviceName) Not serviceName.StartsWith( ".NET" , StringComparison.OrdinalIgnoreCase) AndAlso Not serviceName.StartsWith( "{" )).ToArray()
286310 ServiceRk.Close()
287311
@@ -305,26 +329,35 @@ Module WindowsServiceHelper
305329 ' it will show that value.
306330 serviceImagePath = ServiceInfoRk.GetValue( "ImagePath" , "" , RegistryValueOptions.DoNotExpandEnvironmentNames)
307331 If serviceImagePath = "" Then
332+ DynaLog.LogMessage( "The service image path cannot be obtained." )
308333 ' This "service" is bogus
309334 Continue For
310335 End If
311336
312337 serviceEntryName = ServiceName
313338 serviceDisplayName = ServiceInfoRk.GetValue( "DisplayName" , "" )
339+ DynaLog.LogMessage( "Raw service display name: " & serviceDisplayName)
314340 If serviceDisplayName.StartsWith( "@" ) AndAlso serviceDisplayName.ToLowerInvariant().Contains( ".inf" ) Then
341+ DynaLog.LogMessage( "Raw display name points to a device driver. Parsing..." )
315342 Dim parsedInf As Tuple( Of String , String ) = ParseInfLine(serviceDisplayName)
316343
317344 If parsedInf IsNot Nothing Then
345+ DynaLog.LogMessage( "We have grabbed the path and the token. Continuing..." )
318346 Dim resolvedString As String = ResolveInfToken(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "INF" , parsedInf.Item1), parsedInf.Item2)
347+ DynaLog.LogMessage( "- Resolved string (using current system): " & resolvedString)
319348 If Not String .IsNullOrEmpty(resolvedString) Then
349+ DynaLog.LogMessage( "We grabbed the resolved string. Using that..." )
320350 serviceDisplayName = resolvedString
321351 End If
322352 End If
323353 ElseIf serviceDisplayName.StartsWith( "@" ) Then
354+ DynaLog.LogMessage( "Raw display name indicates an indirect string. Parsing..." )
324355 serviceDisplayName = ResolveIndirectString(serviceDisplayName)
325356 End If
326357 serviceDescription = ServiceInfoRk.GetValue( "Description" , "" )
358+ DynaLog.LogMessage( "Raw service description: " & serviceDescription)
327359 If serviceDescription.StartsWith( "@" ) Then
360+ DynaLog.LogMessage( "Raw description indicates an indirect string. Parsing..." )
328361 serviceDescription = ResolveIndirectString(serviceDescription)
329362 End If
330363 serviceObjectName = ServiceInfoRk.GetValue( "ObjectName" , "" )
@@ -339,8 +372,10 @@ Module WindowsServiceHelper
339372 serviceFailActionByteArr = ServiceInfoRk.GetValue( "FailureActions" , New Byte () {})
340373
341374 Dim serviceRequiredPrivilegeList As New List( Of NTSecurityPrivilegeConstant)
375+ DynaLog.LogMessage( "Privilege items defined by the service: " & serviceRequiredPrivilegesString.Count)
342376
343377 If serviceRequiredPrivilegesString.Count > 0 Then
378+ DynaLog.LogMessage( "This service defines privileges. Getting privilege constant representations..." )
344379 ' Parse the items themselves to keys that are available in the dictionary we filled
345380 ' stuff in
346381 For Each serviceRequiredPrivilegeString In serviceRequiredPrivilegesString
@@ -352,6 +387,7 @@ Module WindowsServiceHelper
352387 Next
353388 End If
354389
390+ DynaLog.LogMessage( "Adding service " & serviceEntryName & " to service list..." )
355391 serviceList.Add( New WindowsService(serviceEntryName,
356392 serviceDisplayName,
357393 serviceDescription,
@@ -386,21 +422,28 @@ Module WindowsServiceHelper
386422 secondDelay As Long = 0 ,
387423 subsequentDelay As Long = 0
388424 Dim resetDelay As Integer = 0
425+ DynaLog.LogMessage( "Parsing specified failure action byte array..." )
426+ DynaLog.LogMessage( "Byte array length: " & FailureActions.Count)
389427
390428 If FailureActions.Count >= 1 Then
429+ DynaLog.LogMessage( "Some failure actions have been defined." )
391430 Try
431+ DynaLog.LogMessage( "Getting service reset delay..." )
392432 resetDelay = GetDelay(FailureActions.Skip( 0 ).Take( 4 ).ToArray())
393433
394434 ' We have to get the number of byte elements twice because undefined failure measures
395435 ' cause our byte array to be smaller than expected, therefore causing indexes out of bounds.
436+ DynaLog.LogMessage( "Getting 1st failure action and delay (in ms)..." )
396437 firstFail = FailureActions( 20 )
397438 firstDelay = GetDelay(FailureActions.Skip( 24 ).Take( 4 ).ToArray())
398439 If FailureActions.Count > 28 Then
440+ DynaLog.LogMessage( "Byte array is long enough for second failure measures. Getting 2nd failure action and delay (in ms)..." )
399441 ' We have defined second failure measures
400442 secondFail = FailureActions( 28 )
401443 secondDelay = GetDelay(FailureActions.Skip( 32 ).Take( 4 ).ToArray())
402444 End If
403445 If FailureActions.Count > 36 Then
446+ DynaLog.LogMessage( "Byte array is long enough for subsequent failure measures. Getting subsequent failure actions and delays (in ms)..." )
404447 ' We have defined subsequent failure measures
405448 subsequentFails = FailureActions( 36 )
406449 subsequentDelay = GetDelay(FailureActions.Skip( 40 ).Take( 4 ).ToArray())
@@ -415,6 +458,7 @@ Module WindowsServiceHelper
415458 End Function
416459
417460 Private Function GetDelay(ByteArray As Byte ()) As Long
461+ DynaLog.LogMessage( "Getting numeric delay from our byte array..." )
418462 Dim binary As String = ""
419463
420464 For x = ByteArray.Length - 1 To 0 Step - 1
0 commit comments