Skip to content

Commit

Permalink
Fixes gathering DLLCharacteristics and Signature information for Read…
Browse files Browse the repository at this point in the history
…-Only files. (#685)
  • Loading branch information
gfs authored Jan 26, 2023
1 parent f1fa334 commit 237c93d
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 22 deletions.
4 changes: 0 additions & 4 deletions Lib/Collectors/FileSystemCollector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
}
Expand Down
88 changes: 70 additions & 18 deletions Lib/Collectors/WindowsFileSystemUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,13 @@ e is IndexOutOfRangeException
return output;
}

/// <summary>
/// Gets the <see cref="DLLCHARACTERISTICS"/> of a File on disk.
/// </summary>
/// <param name="Path"></param>
/// <returns>List of DLL Characteristics</returns>
public static List<DLLCHARACTERISTICS> GetDllCharacteristics(string Path)
{
List<DLLCHARACTERISTICS> output = new();

if (NeedsSignature(Path))
{
try
Expand All @@ -72,41 +75,75 @@ public static List<DLLCHARACTERISTICS> 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();
}

/// <summary>
/// Turn a <see cref="DllCharacteristicsType"/> enum flag value into a list of <see cref="DLLCHARACTERISTICS"/> enum values
/// </summary>
/// <param name="dllcharacteristics"></param>
/// <returns></returns>
private static List<DLLCHARACTERISTICS> CharacteristicsTypeToListOfCharacteristics(
DllCharacteristicsType dllcharacteristics)
{
List<DLLCHARACTERISTICS> 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;
}

/// <summary>
/// Get the Signature
/// </summary>
/// <param name="Path"></param>
/// <param name="stream"></param>
/// <returns></returns>
public static Signature? GetSignatureStatus(string Path, Stream stream)
{
if (stream is null)
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 237c93d

Please sign in to comment.