diff --git a/BinaryObjectScanner.FileType/Executable.cs b/BinaryObjectScanner.FileType/Executable.cs new file mode 100644 index 00000000..9a891943 --- /dev/null +++ b/BinaryObjectScanner.FileType/Executable.cs @@ -0,0 +1,54 @@ +using System; +using System.IO; +using BinaryObjectScanner.Interfaces; + +namespace BinaryObjectScanner.FileType +{ + /// + /// Executable or library + /// + /// + /// Due to the complexity of executables, all actual handling is offloaded to + /// another class that is used by the scanner + /// + public class Executable : IDetectable, IExtractable + { + /// + public string Detect(string file, bool includeDebug) + { + if (!File.Exists(file)) + return null; + + using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + return Detect(fs, file, includeDebug); + } + } + + /// + /// This implementation should never be invoked + public string Detect(Stream stream, string file, bool includeDebug) + { + throw new InvalidOperationException(); + } + + /// + public string Extract(string file, bool includeDebug) + { + if (!File.Exists(file)) + return null; + + using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + return Extract(fs, file, includeDebug); + } + } + + /// + /// This implementation should never be invoked + public string Extract(Stream stream, string file, bool includeDebug) + { + throw new InvalidOperationException(); + } + } +} diff --git a/BurnOutSharp/Factory.cs b/BurnOutSharp/Factory.cs index 6a8997ba..964d1704 100644 --- a/BurnOutSharp/Factory.cs +++ b/BurnOutSharp/Factory.cs @@ -67,17 +67,5 @@ namespace BurnOutSharp default: return null; } } - - /// - /// Create an instance of a scannable based on file type - /// - public static IScannable CreateScannable(SupportedFileType fileType) - { - switch (fileType) - { - case SupportedFileType.Executable: return new BinaryObjectScanner.FileType.Executable(); - default: return null; - } - } } } diff --git a/BurnOutSharp/FileType/Executable.cs b/BurnOutSharp/FileType/Executable.cs deleted file mode 100644 index 1a8d4940..00000000 --- a/BurnOutSharp/FileType/Executable.cs +++ /dev/null @@ -1,339 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.IO; -using System.Text; -using System.Threading.Tasks; -using BurnOutSharp; -using BinaryObjectScanner.Interfaces; -using BinaryObjectScanner.Wrappers; -using static BinaryObjectScanner.Utilities.Dictionary; - -namespace BinaryObjectScanner.FileType -{ - /// - /// Executable or library - /// - public class Executable : IDetectable, IExtractable, IScannable - { - /// - public string Detect(string file, bool includeDebug) - { - if (!File.Exists(file)) - return null; - - using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read)) - { - return Detect(fs, file, includeDebug); - } - } - - /// - public string Detect(Stream stream, string file, bool includeDebug) - { - // Implementation notes: - // - Executables may house more than one sort of packer/protection (see Textfile for details) - // - The output of Detect directly influences which types of packers should be attempted for extraction - // - There are no other file types that require this input, so is it worth changing the interface? - // - Can this somehow delegate to the proper extractable type? - - return null; - - // The below code is a copy of what is currently in Scan, but without any of the - // extraction code or packer filtering code. It is not currently enabled since it - // is not as complete as the IScannable implementation and therefore cannot be reasonably - // used as a replacement yet. - - // Files can be protected in multiple ways - var protections = new ConcurrentQueue(); - - // Load the current file content for debug only - byte[] fileContent = null; - if (includeDebug) - { - try - { - using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true)) - { - fileContent = br.ReadBytes((int)stream.Length); - } - } - catch (Exception ex) - { - if (includeDebug) Console.WriteLine(ex); - } - } - - // Get the wrapper for the appropriate executable type - WrapperBase wrapper = WrapperFactory.CreateExecutableWrapper(stream); - if (wrapper == null) - return null; - - // Iterate through all generic content checks - if (fileContent != null) - { - Parallel.ForEach(ScanningClasses.ContentCheckClasses, checkClass => - { - string protection = checkClass.CheckContents(file, fileContent, includeDebug); - protections.Enqueue(protection); - }); - } - - // If we have an MS-DOS executable - if (wrapper is MSDOS mz) - { - // No-op - } - - // If we have a New Executable - else if (wrapper is NewExecutable nex) - { - Parallel.ForEach(ScanningClasses.NewExecutableCheckClasses, checkClass => - { - string protection = checkClass.CheckNewExecutable(file, nex, includeDebug); - protections.Enqueue(protection); - }); - } - - // If we have a Linear Executable - else if (wrapper is LinearExecutable lex) - { - Parallel.ForEach(ScanningClasses.LinearExecutableCheckClasses, checkClass => - { - string protection = checkClass.CheckLinearExecutable(file, lex, includeDebug); - protections.Enqueue(protection); - }); - } - - // If we have a Portable Executable - else if (wrapper is PortableExecutable pex) - { - Parallel.ForEach(ScanningClasses.PortableExecutableCheckClasses, checkClass => - { - string protection = checkClass.CheckPortableExecutable(file, pex, includeDebug); - protections.Enqueue(protection); - }); - } - - return string.Join(";", protections.ToArray()); - } - - /// - public string Extract(string file, bool includeDebug) - { - if (!File.Exists(file)) - return null; - - using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read)) - { - return Extract(fs, file, includeDebug); - } - } - - /// - public string Extract(Stream stream, string file, bool includeDebug) - { - // Implementation notes: - // - Executables may house more than one sort of extractable packer/protection - // - We currently have no way of defining what folder is output for a given extractable - // - Everything else should be basically the same for other extractable types - // - Which extractions to run is directly influenced by the detected protections - // - Can this somehow delegate to the proper extractable type? - // - Can we have a check in Scanner that then runs all extractable implementations if the class is Executable? - - // The following packers fully implement IExtractable (extract and doesn't return null) - // - - // - - // - - // - - // - - - return null; - } - - /// - public ConcurrentDictionary> Scan(Scanner scanner, string file) - { - if (!File.Exists(file)) - return null; - - using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read)) - { - return Scan(scanner, fs, file); - } - } - - /// - public ConcurrentDictionary> Scan(Scanner scanner, Stream stream, string file) - { - // Files can be protected in multiple ways - var protections = new ConcurrentDictionary>(); - - // Load the current file content for debug only - byte[] fileContent = null; - if (scanner.IncludeDebug) - { - try - { - using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true)) - { - fileContent = br.ReadBytes((int)stream.Length); - } - } - catch (Exception ex) - { - if (scanner.IncludeDebug) Console.WriteLine(ex); - - // Enable for odd files, keep disabled otherwise - // AppendToDictionary(protections, file, "[Out of memory attempting to open]"); - // return protections; - } - } - - // Get the wrapper for the appropriate executable type - WrapperBase wrapper = WrapperFactory.CreateExecutableWrapper(stream); - if (wrapper == null) - return protections; - - // Iterate through all generic content checks - if (fileContent != null) - { - Parallel.ForEach(ScanningClasses.ContentCheckClasses, checkClass => - { - // Get the protection for the class, if possible - string protection = checkClass.CheckContents(file, fileContent, scanner.IncludeDebug); - AppendToDictionary(protections, file, protection); - }); - } - - // If we have an MS-DOS executable - if (wrapper is MSDOS mz) - { - // No-op - } - - // If we have a New Executable - else if (wrapper is NewExecutable nex) - { - Parallel.ForEach(ScanningClasses.NewExecutableCheckClasses, checkClass => - { - // Get the protection for the class, if possible - string protection = checkClass.CheckNewExecutable(file, nex, scanner.IncludeDebug); - if (ShouldAddProtection(checkClass, scanner.ScanPackers, protection)) - AppendToDictionary(protections, file, protection); - - // If we had a protection, check if it is extractable - if (!string.IsNullOrWhiteSpace(protection)) - HandleExtractable(scanner, stream, file, checkClass, protections); - }); - } - - // If we have a Linear Executable - else if (wrapper is LinearExecutable lex) - { - Parallel.ForEach(ScanningClasses.LinearExecutableCheckClasses, checkClass => - { - // Get the protection for the class, if possible - string protection = checkClass.CheckLinearExecutable(file, lex, scanner.IncludeDebug); - if (ShouldAddProtection(checkClass, scanner.ScanPackers, protection)) - AppendToDictionary(protections, file, protection); - - // If we had a protection, check if it is extractable - if (!string.IsNullOrWhiteSpace(protection)) - HandleExtractable(scanner, stream, file, checkClass, protections); - }); - } - - // If we have a Portable Executable - else if (wrapper is PortableExecutable pex) - { - Parallel.ForEach(ScanningClasses.PortableExecutableCheckClasses, checkClass => - { - // Get the protection for the class, if possible - string protection = checkClass.CheckPortableExecutable(file, pex, scanner.IncludeDebug); - if (ShouldAddProtection(checkClass, scanner.ScanPackers, protection)) - AppendToDictionary(protections, file, protection); - - // If we had a protection, check if it is extractable - if (!string.IsNullOrWhiteSpace(protection)) - HandleExtractable(scanner, stream, file, checkClass, protections); - }); - } - - return protections; - } - - #region Helpers - - /// - /// Check to see if a protection should be added or not - /// - /// Class that was last used to check - /// Determines if packers should be included in the output - /// The protection result to be checked - private bool ShouldAddProtection(object checkClass, bool scanPackers, string protection) - { - // If we have an invalid protection - if (string.IsNullOrWhiteSpace(protection)) - return false; - - // If we have a valid content check based on settings - if (scanPackers || !checkClass.GetType().Namespace.ToLowerInvariant().Contains("packer")) - return true; - - // Everything else fails - return false; - } - - /// - /// Handle extractable protections and packers - /// - /// Scanner object for state tracking - /// Stream representing the input file - /// Path to the input file - /// Class representing the current packer or protection - /// Set of existing protections to append to - private static void HandleExtractable(Scanner scanner, Stream stream, string file, object checkingClass, ConcurrentDictionary> protections) - { - // If we don't have an IExtractable implementation - if (!(checkingClass is IExtractable extractable)) - return; - - // If we have an invalid file - if (file == null) - return; - - // If the extractable file itself fails - try - { - // Extract and get the output path - string tempPath = extractable.Extract(stream, file, scanner.IncludeDebug); - if (tempPath != null) - return; - - // Collect and format all found protections - var subProtections = scanner.GetProtections(tempPath); - - // If temp directory cleanup fails - try - { - Directory.Delete(tempPath, true); - } - catch (Exception ex) - { - if (scanner.IncludeDebug) Console.WriteLine(ex); - } - - // Prepare the returned protections - StripFromKeys(protections, tempPath); - PrependToKeys(subProtections, file); - AppendToDictionary(protections, subProtections); - } - catch (Exception ex) - { - if (scanner.IncludeDebug) Console.WriteLine(ex); - } - } - - #endregion - } -} diff --git a/BurnOutSharp/Handler.cs b/BurnOutSharp/Handler.cs index 8ece76c3..34293b25 100644 --- a/BurnOutSharp/Handler.cs +++ b/BurnOutSharp/Handler.cs @@ -10,7 +10,6 @@ using static BinaryObjectScanner.Utilities.Dictionary; namespace BurnOutSharp { - // TODO: Implement IExtractable handler // TODO: Implement IPathCheck handler internal static class Handler { @@ -21,10 +20,9 @@ namespace BurnOutSharp /// /// Name of the source file of the stream, for tracking /// Stream to scan the contents of - /// True to include packers in the output, false otherwise - /// True to include debug data, false otherwise + /// Scanner object to use for options and scanning /// Set of protections in file, null on error - public static ConcurrentQueue HandleContentChecks(string fileName, Stream stream, bool scanPackers, bool includeDebug) + public static ConcurrentQueue HandleContentChecks(string fileName, Stream stream, Scanner scanner) { // If we have an invalid file if (string.IsNullOrWhiteSpace(fileName)) @@ -45,7 +43,7 @@ namespace BurnOutSharp } catch (Exception ex) { - if (includeDebug) Console.WriteLine(ex); + if (scanner.IncludeDebug) Console.WriteLine(ex); return null; } @@ -56,11 +54,11 @@ namespace BurnOutSharp Parallel.ForEach(ScanningClasses.ContentCheckClasses, checkClass => { // Get the protection for the class, if possible - var subProtections = HandleContentCheck(checkClass, fileName, fileContent, includeDebug); + var subProtections = HandleContentCheck(checkClass, fileName, fileContent, scanner.IncludeDebug); if (subProtections != null) { // If we are filtering the output of the check - if (!CheckIfPacker(checkClass) || !scanPackers) + if (!CheckIfPacker(checkClass) || !scanner.ScanPackers) return; protections.AddRange(subProtections); @@ -75,11 +73,9 @@ namespace BurnOutSharp /// /// Name of the source file of the executable, for tracking /// Executable to scan - /// True to include extractable contents in the output, false otherwise - /// True to include packers in the output, false otherwise - /// True to include debug data, false otherwise + /// Scanner object to use for options and scanning /// Set of protections in file, null on error - public static ConcurrentDictionary> HandleNewExecutableChecks(string fileName, LinearExecutable lex, bool scanArchives, bool scanPackers, bool includeDebug) + public static ConcurrentDictionary> HandleLinearExecutableChecks(string fileName, Stream stream, LinearExecutable lex, Scanner scanner) { // Create the output dictionary var protections = new ConcurrentDictionary>(); @@ -88,17 +84,24 @@ namespace BurnOutSharp Parallel.ForEach(ScanningClasses.LinearExecutableCheckClasses, checkClass => { // Get the protection for the class, if possible - var subProtections = HandleLinearExecutableCheck(checkClass, fileName, lex, includeDebug); - if (subProtections != null) + var subProtections = HandleLinearExecutableCheck(checkClass, 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) { - // If we are filtering the output of the check - if (!CheckIfPacker(checkClass) || !scanPackers) - return; - - AppendToDictionary(protections, fileName, subProtections); + var extractedProtections = HandleExtractable(extractable, fileName, stream, scanner); + if (extractedProtections != null) + AppendToDictionary(protections, extractedProtections); } - - // TODO: Handle extractable implementations }); return protections; @@ -109,11 +112,9 @@ namespace BurnOutSharp /// /// Name of the source file of the executable, for tracking /// Executable to scan - /// True to include extractable contents in the output, false otherwise - /// True to include packers in the output, false otherwise - /// True to include debug data, false otherwise + /// Scanner object to use for options and scanning /// Set of protections in file, null on error - public static ConcurrentDictionary> HandleNewExecutableChecks(string fileName, NewExecutable nex, bool scanArchives, bool scanPackers, bool includeDebug) + public static ConcurrentDictionary> HandleNewExecutableChecks(string fileName, Stream stream, NewExecutable nex, Scanner scanner) { // Create the output dictionary var protections = new ConcurrentDictionary>(); @@ -122,17 +123,24 @@ namespace BurnOutSharp Parallel.ForEach(ScanningClasses.NewExecutableCheckClasses, checkClass => { // Get the protection for the class, if possible - var subProtections = HandleNewExecutableCheck(checkClass, fileName, nex, includeDebug); - if (subProtections != null) + var subProtections = HandleNewExecutableCheck(checkClass, 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) { - // If we are filtering the output of the check - if (!CheckIfPacker(checkClass) || !scanPackers) - return; - - AppendToDictionary(protections, fileName, subProtections); + var extractedProtections = HandleExtractable(extractable, fileName, stream, scanner); + if (extractedProtections != null) + AppendToDictionary(protections, extractedProtections); } - - // TODO: Handle extractable implementations }); return protections; @@ -143,11 +151,9 @@ namespace BurnOutSharp /// /// Name of the source file of the executable, for tracking /// Executable to scan - /// True to include extractable contents in the output, false otherwise - /// True to include packers in the output, false otherwise - /// True to include debug data, false otherwise + /// Scanner object to use for options and scanning /// Set of protections in file, null on error - public static ConcurrentDictionary> HandlePortableExecutableChecks(string fileName, PortableExecutable pex, bool scanArchives, bool scanPackers, bool includeDebug) + public static ConcurrentDictionary> HandlePortableExecutableChecks(string fileName, Stream stream, PortableExecutable pex, Scanner scanner) { // Create the output dictionary var protections = new ConcurrentDictionary>(); @@ -156,17 +162,24 @@ namespace BurnOutSharp Parallel.ForEach(ScanningClasses.PortableExecutableCheckClasses, checkClass => { // Get the protection for the class, if possible - var subProtections = HandlePortableExecutableCheck(checkClass, fileName, pex, includeDebug); - if (subProtections != null) + var subProtections = HandlePortableExecutableCheck(checkClass, 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) { - // If we are filtering the output of the check - if (!CheckIfPacker(checkClass) || !scanPackers) - return; - - AppendToDictionary(protections, fileName, subProtections); + var extractedProtections = HandleExtractable(extractable, fileName, stream, scanner); + if (extractedProtections != null) + AppendToDictionary(protections, extractedProtections); } - - // TODO: Handle extractable implementations }); return protections; @@ -204,6 +217,50 @@ namespace BurnOutSharp return ProcessProtectionString(protection); } + /// + /// Handle files based on an IExtractable implementation + /// + /// IDetectable class representing the file type + /// Name of the source file of the stream, for tracking + /// Stream to scan the contents of + /// Scanner object to use on extractable contents + /// Set of protections in file, null on error + public static ConcurrentDictionary> HandleExtractable(IExtractable impl, string fileName, Stream stream, Scanner scanner) + { + // If the extractable file itself fails + try + { + // Extract and get the output path + string tempPath = impl.Extract(stream, fileName, scanner.IncludeDebug); + if (tempPath == null) + return null; + + // Collect and format all found protections + var subProtections = scanner.GetProtections(tempPath); + + // If temp directory cleanup fails + try + { + Directory.Delete(tempPath, true); + } + catch (Exception ex) + { + if (scanner.IncludeDebug) Console.WriteLine(ex); + } + + // Prepare the returned protections + StripFromKeys(subProtections, tempPath); + PrependToKeys(subProtections, fileName); + return subProtections; + } + catch (Exception ex) + { + if (scanner.IncludeDebug) Console.WriteLine(ex); + } + + return null; + } + /// /// Handle files based on an ILinearExecutableCheck implementation /// diff --git a/BurnOutSharp/Interfaces/IScannable.cs b/BurnOutSharp/Interfaces/IScannable.cs deleted file mode 100644 index e0d5670e..00000000 --- a/BurnOutSharp/Interfaces/IScannable.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Collections.Concurrent; -using System.IO; -using BurnOutSharp; - -namespace BinaryObjectScanner.Interfaces -{ - /// - /// Mark a file type as being able to be scanned - /// - /// - /// This is also used for packers, embedded archives, and other - /// installer formats that may need to be "extracted" before they - /// can be fully scanned. - /// - public interface IScannable - { - /// - /// Scan a file for all internal protections - /// - /// Scanner object for state tracking - /// Path to the input file - /// Dictionary mapping paths to protection lists - /// Ideally, this should just point to the other scan implementation - ConcurrentDictionary> Scan(Scanner scanner, string file); - - /// - /// Scan a stream for all internal protections - /// - /// Scanner object for state tracking - /// Stream representing the input file - /// Path to the input file - /// Dictionary mapping paths to protection lists - ConcurrentDictionary> Scan(Scanner scanner, Stream stream, string file); - } -} diff --git a/BurnOutSharp/Scanner.cs b/BurnOutSharp/Scanner.cs index 30762d80..38925ad2 100644 --- a/BurnOutSharp/Scanner.cs +++ b/BurnOutSharp/Scanner.cs @@ -6,8 +6,8 @@ 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; namespace BurnOutSharp @@ -351,9 +351,7 @@ namespace BurnOutSharp // TODO: Write custom executable handling if (detectable is Executable) { - var subProtections = Handler.HandleDetectable(detectable, fileName, stream, IncludeDebug); - if (subProtections != null) - AppendToDictionary(protections, fileName, subProtections); + ProcessExecutable(fileName, stream, protections); } // Otherwise, use the default implementation @@ -380,16 +378,6 @@ namespace BurnOutSharp } } - // Create a scannable for the given file type - var scannable = Factory.CreateScannable(fileType); - - // If we're scanning file contents - if (scannable != null && ScanContents) - { - var subProtections = scannable.Scan(this, stream, fileName); - AppendToDictionary(protections, subProtections); - } - #endregion #region Archive File Types @@ -400,19 +388,10 @@ namespace BurnOutSharp // If we're scanning archives if (extractable != null && ScanArchives) { - // If we have an executable, it needs to bypass normal handling - // TODO: Write custom executable handling - if (extractable is Executable) + // We only want to process non-executables + if (!(extractable is Executable)) { - var subProtections = HandleExtractable(extractable, fileName, stream); - if (subProtections != null) - AppendToDictionary(protections, subProtections); - } - - // Otherwise, use the default implementation - else - { - var subProtections = HandleExtractable(extractable, fileName, stream); + var subProtections = Handler.HandleExtractable(extractable, fileName, stream, this); if (subProtections != null) AppendToDictionary(protections, subProtections); } @@ -423,7 +402,6 @@ namespace BurnOutSharp catch (Exception ex) { if (IncludeDebug) Console.WriteLine(ex); - AppendToDictionary(protections, fileName, IncludeDebug ? ex.ToString() : "[Exception opening file, please try again]"); } @@ -435,49 +413,55 @@ namespace BurnOutSharp #endregion - #region Interface Handlers + #region Executable Handling /// - /// Handle files based on an IExtractable implementation + /// Process scanning for an Executable type /// - /// IExtractable class representing the file type /// Name of the source file of the stream, for tracking /// Stream to scan the contents of - /// Set of protections in internal files, null on error - private ConcurrentDictionary> HandleExtractable(IExtractable extractable, string fileName, Stream stream) + /// 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) { - // If the extractable file itself fails - try + // Try to create a wrapper for the proper executable type + var wrapper = WrapperFactory.CreateExecutableWrapper(stream); + if (wrapper == null) + return; + + // Only use generic content checks if we're in debug mode + if (IncludeDebug) { - // Extract and get the output path - string tempPath = extractable.Extract(stream, fileName, IncludeDebug); - if (tempPath == null) - return null; - - // Collect and format all found protections - var subProtections = GetProtections(tempPath); - - // If temp directory cleanup fails - try - { - Directory.Delete(tempPath, true); - } - catch (Exception ex) - { - if (IncludeDebug) Console.WriteLine(ex); - } - - // Prepare the returned protections - StripFromKeys(subProtections, tempPath); - PrependToKeys(subProtections, fileName); - return subProtections; - } - catch (Exception ex) - { - if (IncludeDebug) Console.WriteLine(ex); + var subProtections = Handler.HandleContentChecks(fileName, stream, this); + if (subProtections != null) + AppendToDictionary(protections, fileName, subProtections); } - return null; + if (wrapper is MSDOS) + { + // No-op until protection classes implmented + } + else if (wrapper is LinearExecutable lex) + { + var subProtections = Handler.HandleLinearExecutableChecks(fileName, stream, lex, this); + if (subProtections != null) + AppendToDictionary(protections, subProtections); + } + else if (wrapper is NewExecutable nex) + { + var subProtections = Handler.HandleNewExecutableChecks(fileName, stream, nex, this); + if (subProtections != null) + AppendToDictionary(protections, subProtections); + } + else if (wrapper is PortableExecutable pex) + { + var subProtections = Handler.HandlePortableExecutableChecks(fileName, stream, pex, this); + if (subProtections != null) + AppendToDictionary(protections, subProtections); + } } #endregion