diff --git a/BinaryObjectScanner.FileType/BinaryObjectScanner.FileType.csproj b/BinaryObjectScanner.FileType/BinaryObjectScanner.FileType.csproj
index efd0cc69..12347ebb 100644
--- a/BinaryObjectScanner.FileType/BinaryObjectScanner.FileType.csproj
+++ b/BinaryObjectScanner.FileType/BinaryObjectScanner.FileType.csproj
@@ -24,6 +24,8 @@
+
+
diff --git a/BinaryObjectScanner.FileType/Executable.cs b/BinaryObjectScanner.FileType/Executable.cs
index 9a891943..b4b52b50 100644
--- a/BinaryObjectScanner.FileType/Executable.cs
+++ b/BinaryObjectScanner.FileType/Executable.cs
@@ -1,6 +1,14 @@
using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
using BinaryObjectScanner.Interfaces;
+using BinaryObjectScanner.Utilities;
+using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.FileType
{
@@ -8,11 +16,100 @@ namespace BinaryObjectScanner.FileType
/// Executable or library
///
///
- /// Due to the complexity of executables, all actual handling is offloaded to
+ /// Due to the complexity of executables, all extraction handling
/// another class that is used by the scanner
///
public class Executable : IDetectable, IExtractable
{
+ #region Properties
+
+ ///
+ /// Determines if packers are counted as detected protections or not
+ ///
+ public bool IncludePackers { get; set; }
+
+ ///
+ /// Cache for all IContentCheck types
+ ///
+ public static IEnumerable ContentCheckClasses
+ {
+ get
+ {
+ if (contentCheckClasses == null)
+ contentCheckClasses = InitCheckClasses();
+
+ return contentCheckClasses;
+ }
+ }
+
+ ///
+ /// Cache for all ILinearExecutableCheck types
+ ///
+ public static IEnumerable LinearExecutableCheckClasses
+ {
+ get
+ {
+ if (linearExecutableCheckClasses == null)
+ linearExecutableCheckClasses = InitCheckClasses();
+
+ return linearExecutableCheckClasses;
+ }
+ }
+
+ ///
+ /// Cache for all INewExecutableCheck types
+ ///
+ public static IEnumerable NewExecutableCheckClasses
+ {
+ get
+ {
+ if (newExecutableCheckClasses == null)
+ newExecutableCheckClasses = InitCheckClasses();
+
+ return newExecutableCheckClasses;
+ }
+ }
+
+ ///
+ /// Cache for all IPortableExecutableCheck types
+ ///
+ public static IEnumerable PortableExecutableCheckClasses
+ {
+ get
+ {
+ if (portableExecutableCheckClasses == null)
+ portableExecutableCheckClasses = InitCheckClasses();
+
+ return portableExecutableCheckClasses;
+ }
+ }
+
+ #endregion
+
+ #region Internal Instances
+
+ ///
+ /// Cache for all IContentCheck types
+ ///
+ private static IEnumerable contentCheckClasses;
+
+ ///
+ /// Cache for all ILinearExecutableCheck types
+ ///
+ private static IEnumerable linearExecutableCheckClasses;
+
+ ///
+ /// Cache for all INewExecutableCheck types
+ ///
+ private static IEnumerable newExecutableCheckClasses;
+
+ ///
+ /// Cache for all IPortableExecutableCheck types
+ ///
+ private static IEnumerable portableExecutableCheckClasses;
+
+ #endregion
+
///
public string Detect(string file, bool includeDebug)
{
@@ -26,10 +123,48 @@ namespace BinaryObjectScanner.FileType
}
///
- /// This implementation should never be invoked
public string Detect(Stream stream, string file, bool includeDebug)
{
- throw new InvalidOperationException();
+ // Try to create a wrapper for the proper executable type
+ var wrapper = WrapperFactory.CreateExecutableWrapper(stream);
+ if (wrapper == null)
+ return null;
+
+ // Create the internal queue
+ var protections = new ConcurrentQueue();
+
+ // Only use generic content checks if we're in debug mode
+ if (includeDebug)
+ {
+ var subProtections = RunContentChecks(file, stream, includeDebug);
+ if (subProtections != null)
+ protections.AddRange(subProtections.Values.ToArray());
+ }
+
+ if (wrapper is MSDOS)
+ {
+ // No-op until protection classes implmented
+ }
+ else if (wrapper is LinearExecutable lex)
+ {
+ var subProtections = RunLinearExecutableChecks(file, stream, lex, includeDebug);
+ if (subProtections != null)
+ protections.AddRange(subProtections.Values.ToArray());
+ }
+ else if (wrapper is NewExecutable nex)
+ {
+ var subProtections = RunNewExecutableChecks(file, stream, nex, includeDebug);
+ if (subProtections != null)
+ protections.AddRange(subProtections.Values.ToArray());
+ }
+ else if (wrapper is PortableExecutable pex)
+ {
+ var subProtections = RunPortableExecutableChecks(file, stream, pex, includeDebug);
+ if (subProtections != null)
+ protections.AddRange(subProtections.Values.ToArray());
+ }
+
+ return string.Join(";", protections);
}
///
@@ -50,5 +185,186 @@ namespace BinaryObjectScanner.FileType
{
throw new InvalidOperationException();
}
+
+ #region Check Runners
+
+ ///
+ /// Handle a single file based on all content check implementations
+ ///
+ /// Name of the source file of the stream, for tracking
+ /// Stream to scan the contents of
+ /// True to include debug data, false otherwise
+ /// Set of protections in file, null on error
+ public ConcurrentDictionary RunContentChecks(string file, Stream stream, bool includeDebug)
+ {
+ // If we have an invalid file
+ if (string.IsNullOrWhiteSpace(file))
+ return null;
+ else if (!File.Exists(file))
+ return null;
+
+ // Read the file contents
+ byte[] fileContent = null;
+ try
+ {
+ using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
+ {
+ fileContent = br.ReadBytes((int)stream.Length);
+ if (fileContent == null)
+ return null;
+ }
+ }
+ catch (Exception ex)
+ {
+ if (includeDebug) Console.WriteLine(ex);
+ return null;
+ }
+
+ // Create the output dictionary
+ var protections = new ConcurrentDictionary();
+
+ // Iterate through all checks
+ Parallel.ForEach(ContentCheckClasses, checkClass =>
+ {
+ // Get the protection for the class, if possible
+ string protection = checkClass.CheckContents(file, fileContent, includeDebug);
+ if (string.IsNullOrWhiteSpace(protection))
+ return;
+
+ // If we are filtering the output of the check
+ if (!CheckIfPacker(checkClass) || !IncludePackers)
+ return;
+
+ protections.TryAdd(checkClass, protection);
+ });
+
+ return protections;
+ }
+
+ ///
+ /// Handle a single file based on all linear executable check implementations
+ ///
+ /// Name of the source file of the executable, for tracking
+ /// Executable to scan
+ /// True to include debug data, false otherwise
+ /// Set of protections in file, null on error
+ public ConcurrentDictionary RunLinearExecutableChecks(string file, Stream stream, LinearExecutable lex, bool includeDebug)
+ {
+ // Create the output dictionary
+ var protections = new ConcurrentDictionary();
+
+ // Iterate through all checks
+ Parallel.ForEach(LinearExecutableCheckClasses, checkClass =>
+ {
+ // Get the protection for the class, if possible
+ string protection = checkClass.CheckLinearExecutable(file, lex, includeDebug);
+ if (string.IsNullOrWhiteSpace(protection))
+ return;
+
+ // If we are filtering the output of the check
+ if (!CheckIfPacker(checkClass) || !IncludePackers)
+ return;
+
+ protections.TryAdd(checkClass, protection);
+ });
+
+ return protections;
+ }
+
+ ///
+ /// Handle a single file based on all new executable check implementations
+ ///
+ /// Name of the source file of the executable, for tracking
+ /// Executable to scan
+ /// True to include debug data, false otherwise
+ /// Set of protections in file, null on error
+ public ConcurrentDictionary RunNewExecutableChecks(string file, Stream stream, NewExecutable nex, bool includeDebug)
+ {
+ // Create the output dictionary
+ var protections = new ConcurrentDictionary();
+
+ // Iterate through all checks
+ Parallel.ForEach(NewExecutableCheckClasses, checkClass =>
+ {
+ // Get the protection for the class, if possible
+ string protection = checkClass.CheckNewExecutable(file, nex, includeDebug);
+ if (string.IsNullOrWhiteSpace(protection))
+ return;
+
+ // If we are filtering the output of the check
+ if (!CheckIfPacker(checkClass) || !IncludePackers)
+ return;
+
+ protections.TryAdd(checkClass, protection);
+ });
+
+ return protections;
+ }
+
+ ///
+ /// Handle a single file based on all portable executable check implementations
+ ///
+ /// Name of the source file of the executable, for tracking
+ /// Executable to scan
+ /// True to include debug data, false otherwise
+ /// Set of protections in file, null on error
+ public ConcurrentDictionary RunPortableExecutableChecks(string file, Stream stream, PortableExecutable pex, bool includeDebug)
+ {
+ // Create the output dictionary
+ var protections = new ConcurrentDictionary();
+
+ // Iterate through all checks
+ Parallel.ForEach(PortableExecutableCheckClasses, checkClass =>
+ {
+ // Get the protection for the class, if possible
+ string protection = checkClass.CheckPortableExecutable(file, pex, includeDebug);
+ if (string.IsNullOrWhiteSpace(protection))
+ return;
+
+ // If we are filtering the output of the check
+ if (!CheckIfPacker(checkClass) || !IncludePackers)
+ return;
+
+ protections.TryAdd(checkClass, protection);
+ });
+
+ return protections;
+ }
+
+ #endregion
+
+ #region Initializers
+
+ ///
+ /// Initialize all implementations of a type
+ ///
+ private static IEnumerable InitCheckClasses()
+ => InitCheckClasses(typeof(BinaryObjectScanner.Packer._DUMMY).Assembly)
+ .Concat(InitCheckClasses(typeof(BinaryObjectScanner.Protection._DUMMY).Assembly));
+
+ ///
+ /// Initialize all implementations of a type
+ ///
+ private static IEnumerable InitCheckClasses(Assembly assembly)
+ {
+ return assembly.GetTypes()
+ .Where(t => t.IsClass && t.GetInterface(typeof(T).Name) != null)
+ .Select(t => (T)Activator.CreateInstance(t));
+ }
+
+ #endregion
+
+ #region Helpers
+
+ ///
+ /// Check to see if an implementation is a packer using reflection
+ ///
+ /// Implementation that was last used to check
+ private static bool CheckIfPacker(object impl)
+ {
+ return impl.GetType().Namespace.ToLowerInvariant().Contains("packer");
+ }
+
+ #endregion
}
}
diff --git a/BurnOutSharp/Handler.cs b/BurnOutSharp/Handler.cs
index 2eaf22fb..4e9eae91 100644
--- a/BurnOutSharp/Handler.cs
+++ b/BurnOutSharp/Handler.cs
@@ -3,150 +3,45 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using System.Text;
+using System.Reflection;
using System.Threading.Tasks;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Utilities;
-using BinaryObjectScanner.Wrappers;
using static BinaryObjectScanner.Utilities.Dictionary;
namespace BurnOutSharp
{
internal static class Handler
{
+ #region Public Collections
+
+ ///
+ /// Cache for all IPathCheck types
+ ///
+ public static IEnumerable PathCheckClasses
+ {
+ get
+ {
+ if (pathCheckClasses == null)
+ pathCheckClasses = InitCheckClasses();
+
+ return pathCheckClasses;
+ }
+ }
+
+ #endregion
+
+ #region Internal Instances
+
+ ///
+ /// Cache for all IPathCheck types
+ ///
+ private static IEnumerable pathCheckClasses;
+
+ #endregion
+
#region Multiple Implementation Wrappers
- ///
- /// Handle a single file based on all content check implementations
- ///
- /// Name of the source file of the stream, for tracking
- /// Stream to scan the contents of
- /// Scanner object to use for options and scanning
- /// Set of protections in file, null on error
- public static ConcurrentQueue HandleContentChecks(string fileName, Stream stream, Scanner scanner)
- {
- // If we have an invalid file
- if (string.IsNullOrWhiteSpace(fileName))
- return null;
- else if (!File.Exists(fileName))
- return null;
-
- // Read the file contents
- byte[] fileContent = null;
- try
- {
- using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
- {
- fileContent = br.ReadBytes((int)stream.Length);
- if (fileContent == null)
- return null;
- }
- }
- catch (Exception ex)
- {
- if (scanner.IncludeDebug) Console.WriteLine(ex);
- return null;
- }
-
- // Create the output queue
- var protections = new ConcurrentQueue();
-
- // Iterate through all checks
- Parallel.ForEach(ScanningClasses.ContentCheckClasses, checkClass =>
- {
- // Get the protection for the class, if possible
- var subProtections = checkClass.PerformCheck(fileName, fileContent, scanner.IncludeDebug);
- if (subProtections != null)
- {
- // If we are filtering the output of the check
- if (!CheckIfPacker(checkClass) || !scanner.ScanPackers)
- return;
-
- protections.AddRange(subProtections);
- }
- });
-
- return protections;
- }
-
- ///
- /// Handle a single file based on all linear executable check implementations
- ///
- /// Name of the source file of the executable, for tracking
- /// Executable to scan
- /// Scanner object to use for options and scanning
- /// Set of protections in file, null on error
- public static ConcurrentDictionary> HandleLinearExecutableChecks(string fileName, Stream stream, LinearExecutable lex, Scanner scanner)
- {
- // Create the output dictionary
- var protections = new ConcurrentDictionary>();
-
- // Iterate through all checks
- Parallel.ForEach(ScanningClasses.LinearExecutableCheckClasses, checkClass =>
- {
- // Get the protection for the class, if possible
- var subProtections = checkClass.PerformCheck(fileName, lex, scanner.IncludeDebug);
- if (subProtections == null)
- return;
-
- // If we are filtering the output of the check
- if (!CheckIfPacker(checkClass) || !scanner.ScanPackers)
- return;
-
- // Add all found protections to the output
- AppendToDictionary(protections, fileName, subProtections);
-
- // If we have an extractable implementation
- if (checkClass is IExtractable extractable)
- {
- var extractedProtections = HandleExtractable(extractable, fileName, stream, scanner);
- if (extractedProtections != null)
- AppendToDictionary(protections, extractedProtections);
- }
- });
-
- return protections;
- }
-
- ///
- /// Handle a single file based on all new executable check implementations
- ///
- /// Name of the source file of the executable, for tracking
- /// Executable to scan
- /// Scanner object to use for options and scanning
- /// Set of protections in file, null on error
- public static ConcurrentDictionary> HandleNewExecutableChecks(string fileName, Stream stream, NewExecutable nex, Scanner scanner)
- {
- // Create the output dictionary
- var protections = new ConcurrentDictionary>();
-
- // Iterate through all checks
- Parallel.ForEach(ScanningClasses.NewExecutableCheckClasses, checkClass =>
- {
- // Get the protection for the class, if possible
- var subProtections = checkClass.PerformCheck(fileName, nex, scanner.IncludeDebug);
- if (subProtections == null)
- return;
-
- // If we are filtering the output of the check
- if (!CheckIfPacker(checkClass) || !scanner.ScanPackers)
- return;
-
- // Add all found protections to the output
- AppendToDictionary(protections, fileName, subProtections);
-
- // If we have an extractable implementation
- if (checkClass is IExtractable extractable)
- {
- var extractedProtections = HandleExtractable(extractable, fileName, stream, scanner);
- if (extractedProtections != null)
- AppendToDictionary(protections, extractedProtections);
- }
- });
-
- return protections;
- }
-
///
/// Handle a single path based on all path check implementations
///
@@ -162,7 +57,7 @@ namespace BurnOutSharp
files = files?.Select(f => f.Replace('\\', '/'))?.ToList();
// Iterate through all checks
- Parallel.ForEach(ScanningClasses.PathCheckClasses, checkClass =>
+ Parallel.ForEach(PathCheckClasses, checkClass =>
{
var subProtections = checkClass.PerformCheck(path, files);
if (subProtections != null)
@@ -172,45 +67,6 @@ namespace BurnOutSharp
return protections;
}
- ///
- /// Handle a single file based on all portable executable check implementations
- ///
- /// Name of the source file of the executable, for tracking
- /// Executable to scan
- /// Scanner object to use for options and scanning
- /// Set of protections in file, null on error
- public static ConcurrentDictionary> HandlePortableExecutableChecks(string fileName, Stream stream, PortableExecutable pex, Scanner scanner)
- {
- // Create the output dictionary
- var protections = new ConcurrentDictionary>();
-
- // Iterate through all checks
- Parallel.ForEach(ScanningClasses.PortableExecutableCheckClasses, checkClass =>
- {
- // Get the protection for the class, if possible
- var subProtections = checkClass.PerformCheck(fileName, pex, scanner.IncludeDebug);
- if (subProtections == null)
- return;
-
- // If we are filtering the output of the check
- if (!CheckIfPacker(checkClass) || !scanner.ScanPackers)
- return;
-
- // Add all found protections to the output
- AppendToDictionary(protections, fileName, subProtections);
-
- // If we have an extractable implementation
- if (checkClass is IExtractable extractable)
- {
- var extractedProtections = HandleExtractable(extractable, fileName, stream, scanner);
- if (extractedProtections != null)
- AppendToDictionary(protections, extractedProtections);
- }
- });
-
- return protections;
- }
-
#endregion
#region Single Implementation Handlers
@@ -273,48 +129,6 @@ namespace BurnOutSharp
return null;
}
- ///
- /// Handle files based on an IContentCheck implementation
- ///
- /// IDetectable class representing the check
- /// Name of the source file of the byte array, for tracking
- /// Contents of the source file
- /// True to include debug data, false otherwise
- /// Set of protections in file, null on error
- private static ConcurrentQueue PerformCheck(this IContentCheck impl, string fileName, byte[] fileContent, bool includeDebug)
- {
- string protection = impl.CheckContents(fileName, fileContent, includeDebug);
- return ProcessProtectionString(protection);
- }
-
- ///
- /// Handle files based on an ILinearExecutableCheck implementation
- ///
- /// ILinearExecutableCheck class representing the check
- /// Name of the source file of the executable, for tracking
- /// LinearExecutable to check
- /// True to include debug data, false otherwise
- /// Set of protections in file, null on error
- private static ConcurrentQueue PerformCheck(this ILinearExecutableCheck impl, string fileName, LinearExecutable lex, bool includeDebug)
- {
- string protection = impl.CheckLinearExecutable(fileName, lex, includeDebug);
- return ProcessProtectionString(protection);
- }
-
- ///
- /// Handle files based on an INewExecutableCheck implementation
- ///
- /// INewExecutableCheck class representing the check
- /// Name of the source file of the executable, for tracking
- /// NewExecutable to check
- /// True to include debug data, false otherwise
- /// Set of protections in file, null on error
- private static ConcurrentQueue PerformCheck(this INewExecutableCheck impl, string fileName, NewExecutable nex, bool includeDebug)
- {
- string protection = impl.CheckNewExecutable(fileName, nex, includeDebug);
- return ProcessProtectionString(protection);
- }
-
///
/// Handle files based on an IPathCheck implementation
///
@@ -350,33 +164,31 @@ namespace BurnOutSharp
return protections;
}
+ #endregion
+
+ #region Initializers
+
///
- /// Handle files based on an IPortableExecutableCheck implementation
+ /// Initialize all implementations of a type
///
- /// IPortableExecutableCheck class representing the check
- /// Name of the source file of the executable, for tracking
- /// NewExecutable to check
- /// True to include debug data, false otherwise
- /// Set of protections in file, null on error
- private static ConcurrentQueue PerformCheck(this IPortableExecutableCheck impl, string fileName, PortableExecutable pex, bool includeDebug)
+ private static IEnumerable InitCheckClasses()
+ => InitCheckClasses(typeof(BinaryObjectScanner.Packer._DUMMY).Assembly)
+ .Concat(InitCheckClasses(typeof(BinaryObjectScanner.Protection._DUMMY).Assembly));
+
+ ///
+ /// Initialize all implementations of a type
+ ///
+ private static IEnumerable InitCheckClasses(Assembly assembly)
{
- string protection = impl.CheckPortableExecutable(fileName, pex, includeDebug);
- return ProcessProtectionString(protection);
+ return assembly.GetTypes()
+ .Where(t => t.IsClass && t.GetInterface(typeof(T).Name) != null)
+ .Select(t => (T)Activator.CreateInstance(t));
}
#endregion
#region Helpers
- ///
- /// Check to see if an implementation is a packer using reflection
- ///
- /// Implementation that was last used to check
- private static bool CheckIfPacker(object impl)
- {
- return impl.GetType().Namespace.ToLowerInvariant().Contains("packer");
- }
-
///
/// Process a protection string if it includes multiple protections
///
diff --git a/BurnOutSharp/Scanner.cs b/BurnOutSharp/Scanner.cs
index 54f37c6b..08c2e137 100644
--- a/BurnOutSharp/Scanner.cs
+++ b/BurnOutSharp/Scanner.cs
@@ -4,7 +4,9 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
+using System.Threading.Tasks;
using BinaryObjectScanner.FileType;
+using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Utilities;
using BinaryObjectScanner.Wrappers;
using static BinaryObjectScanner.Utilities.Dictionary;
@@ -297,9 +299,18 @@ namespace BurnOutSharp
{
// If we have an executable, it needs to bypass normal handling
// TODO: Write custom executable handling
- if (detectable is Executable)
+ if (detectable is Executable executable)
{
- ProcessExecutable(fileName, stream, protections);
+ executable.IncludePackers = ScanPackers;
+
+ // TODO: Enable this after IExtractable is properly implemented for Executable
+ //var subProtections = Handler.HandleDetectable(executable, fileName, stream, IncludeDebug);
+ //if (subProtections != null)
+ // AppendToDictionary(protections, fileName, subProtections);
+
+ var subProtections = ProcessExecutable(executable, fileName, stream);
+ if (subProtections != null)
+ AppendToDictionary(protections, subProtections);
}
// Otherwise, use the default implementation
@@ -366,26 +377,29 @@ namespace BurnOutSharp
///
/// Process scanning for an Executable type
///
+ /// Executable instance for processing
/// Name of the source file of the stream, for tracking
/// Stream to scan the contents of
- /// Current set of protections to append to
///
/// Ideally, we wouldn't need to circumvent the proper handling of file types just for Executable,
/// but due to the complexity of scanning, this is not currently possible.
///
- private void ProcessExecutable(string fileName, Stream stream, ConcurrentDictionary> protections)
+ private ConcurrentDictionary> ProcessExecutable(Executable executable, string fileName, Stream stream)
{
// Try to create a wrapper for the proper executable type
var wrapper = WrapperFactory.CreateExecutableWrapper(stream);
if (wrapper == null)
- return;
+ return null;
+
+ // Create the output dictionary
+ var protections = new ConcurrentDictionary>();
// Only use generic content checks if we're in debug mode
if (IncludeDebug)
{
- var subProtections = Handler.HandleContentChecks(fileName, stream, this);
+ var subProtections = executable.RunContentChecks(fileName, stream, IncludeDebug);
if (subProtections != null)
- AppendToDictionary(protections, fileName, subProtections);
+ AppendToDictionary(protections, fileName, subProtections.Values.ToArray());
}
if (wrapper is MSDOS)
@@ -394,22 +408,63 @@ namespace BurnOutSharp
}
else if (wrapper is LinearExecutable lex)
{
- var subProtections = Handler.HandleLinearExecutableChecks(fileName, stream, lex, this);
- if (subProtections != null)
- AppendToDictionary(protections, subProtections);
+ var subProtections = executable.RunLinearExecutableChecks(fileName, stream, lex, IncludeDebug);
+ if (subProtections == null)
+ return protections;
+
+ // Append the returned values
+ AppendToDictionary(protections, fileName, subProtections.Values.ToArray());
+
+ // If we have any extractable packers
+ var extractables = subProtections.Keys.Where(c => c is IExtractable).Select(c => c as IExtractable);
+ Parallel.ForEach(extractables, extractable =>
+ {
+ // Get the protection for the class, if possible
+ var extractedProtections = Handler.HandleExtractable(extractable, fileName, stream, this);
+ if (extractedProtections != null)
+ AppendToDictionary(protections, extractedProtections);
+ });
}
else if (wrapper is NewExecutable nex)
{
- var subProtections = Handler.HandleNewExecutableChecks(fileName, stream, nex, this);
- if (subProtections != null)
- AppendToDictionary(protections, subProtections);
+ var subProtections = executable.RunNewExecutableChecks(fileName, stream, nex, IncludeDebug);
+ if (subProtections == null)
+ return protections;
+
+ // Append the returned values
+ AppendToDictionary(protections, fileName, subProtections.Values.ToArray());
+
+ // If we have any extractable packers
+ var extractables = subProtections.Keys.Where(c => c is IExtractable).Select(c => c as IExtractable);
+ Parallel.ForEach(extractables, extractable =>
+ {
+ // Get the protection for the class, if possible
+ var extractedProtections = Handler.HandleExtractable(extractable, fileName, stream, this);
+ if (extractedProtections != null)
+ AppendToDictionary(protections, extractedProtections);
+ });
}
else if (wrapper is PortableExecutable pex)
{
- var subProtections = Handler.HandlePortableExecutableChecks(fileName, stream, pex, this);
- if (subProtections != null)
- AppendToDictionary(protections, subProtections);
+ var subProtections = executable.RunPortableExecutableChecks(fileName, stream, pex, IncludeDebug);
+ if (subProtections == null)
+ return protections;
+
+ // Append the returned values
+ AppendToDictionary(protections, fileName, subProtections.Values.ToArray());
+
+ // If we have any extractable packers
+ var extractables = subProtections.Keys.Where(c => c is IExtractable).Select(c => c as IExtractable);
+ Parallel.ForEach(extractables, extractable =>
+ {
+ // Get the protection for the class, if possible
+ var extractedProtections = Handler.HandleExtractable(extractable, fileName, stream, this);
+ if (extractedProtections != null)
+ AppendToDictionary(protections, extractedProtections);
+ });
}
+
+ return protections;
}
#endregion
diff --git a/BurnOutSharp/ScanningClasses.cs b/BurnOutSharp/ScanningClasses.cs
deleted file mode 100644
index 7c689e69..00000000
--- a/BurnOutSharp/ScanningClasses.cs
+++ /dev/null
@@ -1,157 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using BinaryObjectScanner.Interfaces;
-
-namespace BurnOutSharp
-{
- ///
- /// Statically-generated lists of scanning classes
- ///
- internal static class ScanningClasses
- {
- #region Public Collections
-
- ///
- /// Cache for all IContentCheck types
- ///
- public static IEnumerable ContentCheckClasses
- {
- get
- {
- if (contentCheckClasses == null)
- contentCheckClasses = InitCheckClasses();
-
- return contentCheckClasses;
- }
- }
-
- ///
- /// Cache for all IExtractable types
- ///
- public static IEnumerable ExtractableClasses
- {
- get
- {
- if (extractableClasses == null)
- extractableClasses = InitCheckClasses();
-
- return extractableClasses;
- }
- }
-
- ///
- /// Cache for all ILinearExecutableCheck types
- ///
- public static IEnumerable LinearExecutableCheckClasses
- {
- get
- {
- if (linearExecutableCheckClasses == null)
- linearExecutableCheckClasses = InitCheckClasses();
-
- return linearExecutableCheckClasses;
- }
- }
-
- ///
- /// Cache for all INewExecutableCheck types
- ///
- public static IEnumerable NewExecutableCheckClasses
- {
- get
- {
- if (newExecutableCheckClasses == null)
- newExecutableCheckClasses = InitCheckClasses();
-
- return newExecutableCheckClasses;
- }
- }
-
- ///
- /// Cache for all IPathCheck types
- ///
- public static IEnumerable PathCheckClasses
- {
- get
- {
- if (pathCheckClasses == null)
- pathCheckClasses = InitCheckClasses();
-
- return pathCheckClasses;
- }
- }
-
- ///
- /// Cache for all IPortableExecutableCheck types
- ///
- public static IEnumerable PortableExecutableCheckClasses
- {
- get
- {
- if (portableExecutableCheckClasses == null)
- portableExecutableCheckClasses = InitCheckClasses();
-
- return portableExecutableCheckClasses;
- }
- }
-
- #endregion
-
- #region Internal Instances
-
- ///
- /// Cache for all IContentCheck types
- ///
- private static IEnumerable contentCheckClasses;
-
- ///
- /// Cache for all IExtractable types
- ///
- private static IEnumerable extractableClasses;
-
- ///
- /// Cache for all ILinearExecutableCheck types
- ///
- private static IEnumerable linearExecutableCheckClasses;
-
- ///
- /// Cache for all INewExecutableCheck types
- ///
- private static IEnumerable newExecutableCheckClasses;
-
- ///
- /// Cache for all IPathCheck types
- ///
- private static IEnumerable pathCheckClasses;
-
- ///
- /// Cache for all IPortableExecutableCheck types
- ///
- private static IEnumerable portableExecutableCheckClasses;
-
- #endregion
-
- #region Initializers
-
- ///
- /// Initialize all implementations of a type
- ///
- private static IEnumerable InitCheckClasses()
- => InitCheckClasses(typeof(BinaryObjectScanner.Packer._DUMMY).Assembly)
- .Concat(InitCheckClasses(typeof(BinaryObjectScanner.Protection._DUMMY).Assembly));
-
- ///
- /// Initialize all implementations of a type
- ///
- private static IEnumerable InitCheckClasses(Assembly assembly)
- {
- return assembly.GetTypes()
- .Where(t => t.IsClass && t.GetInterface(typeof(T).Name) != null)
- .Select(t => (T)Activator.CreateInstance(t));
- }
-
- #endregion
- }
-}