From 237c93d66fafd021053a25095df8652cacea7505 Mon Sep 17 00:00:00 2001
From: Gabe Stocco <98900+gfs@users.noreply.github.com>
Date: Wed, 25 Jan 2023 20:18:13 -0800
Subject: [PATCH] Fixes gathering DLLCharacteristics and Signature information
for Read-Only files. (#685)
---
Lib/Collectors/FileSystemCollector.cs | 4 --
Lib/Collectors/WindowsFileSystemUtils.cs | 88 +++++++++++++++++++-----
2 files changed, 70 insertions(+), 22 deletions(-)
diff --git a/Lib/Collectors/FileSystemCollector.cs b/Lib/Collectors/FileSystemCollector.cs
index f4f7d851..5928de2a 100644
--- a/Lib/Collectors/FileSystemCollector.cs
+++ b/Lib/Collectors/FileSystemCollector.cs
@@ -242,10 +242,6 @@ e is ArgumentNullException
obj.SignatureStatus = WindowsFileSystemUtils.GetSignatureStatus(path);
obj.Characteristics = WindowsFileSystemUtils.GetDllCharacteristics(path);
}
- else if (obj.ExecutableType == EXECUTABLE_TYPE.MACOS)
- {
- obj.MacSignatureStatus = FileSystemUtils.GetMacSignature(path);
- }
}
}
}
diff --git a/Lib/Collectors/WindowsFileSystemUtils.cs b/Lib/Collectors/WindowsFileSystemUtils.cs
index 1a712b1e..05c20408 100644
--- a/Lib/Collectors/WindowsFileSystemUtils.cs
+++ b/Lib/Collectors/WindowsFileSystemUtils.cs
@@ -59,10 +59,13 @@ e is IndexOutOfRangeException
return output;
}
+ ///
+ /// Gets the of a File on disk.
+ ///
+ ///
+ /// List of DLL Characteristics
public static List GetDllCharacteristics(string Path)
{
- List output = new();
-
if (NeedsSignature(Path))
{
try
@@ -72,41 +75,75 @@ public static List GetDllCharacteristics(string Path)
using var mmf = new PeNet.FileParser.MMFile(Path);
var peHeader = new PeFile(mmf);
var dllCharacteristics = peHeader.ImageNtHeaders?.OptionalHeader.DllCharacteristics;
- if (dllCharacteristics is DllCharacteristicsType chars)
+ if (dllCharacteristics is { } chars)
{
- ushort characteristics = (ushort)chars;
- foreach (DLLCHARACTERISTICS? characteristic in Enum.GetValues(typeof(DLLCHARACTERISTICS)))
- {
- if (characteristic is DLLCHARACTERISTICS c)
- {
- if (((ushort)c & characteristics) == (ushort)c)
- {
- output.Add(c);
- }
- }
- }
+ return CharacteristicsTypeToListOfCharacteristics(chars);
}
}
}
+ // This can happen if the file is readable but not writable as MMFile tries to open the file with write privileges.
+ // When we fail we can retry by reading the file to a Stream first, which cen be less performant but works with just Read access
+ // See #684
+ catch (UnauthorizedAccessException)
+ {
+ try
+ {
+ using var stream = File.OpenRead(Path);
+ return GetDllCharacteristics(Path, stream);
+ }
+ catch (Exception e)
+ {
+ Log.Debug(e, "Failed to get DLL Characteristics for {0} ({1}:{2})", Path, e.GetType(), e.Message);
+ }
+ }
catch (Exception e) when (
e is IndexOutOfRangeException
|| e is ArgumentNullException
|| e is System.IO.IOException
|| e is ArgumentException
- || e is UnauthorizedAccessException
|| e is NullReferenceException)
{
- Log.Verbose("Failed to get PE Headers for {0} ({1}:{2})", Path, e.GetType(), e.Message);
+ Log.Debug("Failed to get DLL Characteristics for {0} ({1}:{2})", Path, e.GetType(), e.Message);
}
catch (Exception e)
{
- Log.Debug(e, "Failed to get PE Headers for {0} ({1}:{2})", Path, e.GetType(), e.Message);
+ Log.Debug(e, "Failed to get DLL Characteristics for {0} ({1}:{2})", Path, e.GetType(), e.Message);
}
}
- return output;
+ return new();
}
+ ///
+ /// Turn a enum flag value into a list of enum values
+ ///
+ ///
+ ///
+ private static List CharacteristicsTypeToListOfCharacteristics(
+ DllCharacteristicsType dllcharacteristics)
+ {
+ List output = new();
+ ushort characteristics = (ushort)dllcharacteristics;
+ foreach (DLLCHARACTERISTICS? characteristic in Enum.GetValues(typeof(DLLCHARACTERISTICS)))
+ {
+ if (characteristic is { } c)
+ {
+ if (((ushort)c & characteristics) == (ushort)c)
+ {
+ output.Add(c);
+ }
+ }
+ }
+
+ return output;
+ }
+
+ ///
+ /// Get the Signature
+ ///
+ ///
+ ///
+ ///
public static Signature? GetSignatureStatus(string Path, Stream stream)
{
if (stream is null)
@@ -151,6 +188,21 @@ e is IndexOutOfRangeException
}
}
}
+ // This can happen if the file is readable but not writable as MMFile tries to open the file with write privileges.
+ // When we fail we can retry by reading the file to a Stream first, which cen be less performant but works with just Read access
+ // See #684
+ catch (UnauthorizedAccessException)
+ {
+ try
+ {
+ using var stream = File.OpenRead(Path);
+ return GetSignatureStatus(Path, stream);
+ }
+ catch (Exception e)
+ {
+ Log.Debug(e, "Failed to get signature for {0} ({1}:{2})", Path, e.GetType(), e.Message);
+ }
+ }
catch (Exception e)
{
Log.Verbose("Failed to get signature for {0} ({1}:{2})", Path, e.GetType(), e.Message);