diff --git a/BinaryObjectScanner.FileType/Executable.cs b/BinaryObjectScanner.FileType/Executable.cs index 133ea9c0..5d57262f 100644 --- a/BinaryObjectScanner.FileType/Executable.cs +++ b/BinaryObjectScanner.FileType/Executable.cs @@ -56,6 +56,20 @@ namespace BinaryObjectScanner.FileType } } + /// + /// Cache for all IMSDOSExecutableCheck types + /// + public static IEnumerable MSDOSExecutableCheckClasses + { + get + { + if (msdosExecutableCheckClasses == null) + msdosExecutableCheckClasses = InitCheckClasses(); + + return msdosExecutableCheckClasses; + } + } + /// /// Cache for all INewExecutableCheck types /// @@ -98,6 +112,11 @@ namespace BinaryObjectScanner.FileType /// private static IEnumerable linearExecutableCheckClasses; + /// + /// Cache for all IMSDOSExecutableCheck types + /// + private static IEnumerable msdosExecutableCheckClasses; + /// /// Cache for all INewExecutableCheck types /// @@ -141,9 +160,11 @@ namespace BinaryObjectScanner.FileType protections.AddRange(subProtections.Values.ToArray()); } - if (wrapper is MSDOS) + if (wrapper is MSDOS mz) { - // No-op until protection classes implmented + var subProtections = RunMSDOSExecutableChecks(file, stream, mz, includeDebug); + if (subProtections != null) + protections.AddRange(subProtections.Values.ToArray()); } else if (wrapper is LinearExecutable lex) { @@ -252,6 +273,36 @@ namespace BinaryObjectScanner.FileType return protections; } + /// + /// Handle a single file based on all MS-DOS 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 RunMSDOSExecutableChecks(string file, Stream stream, MSDOS mz, bool includeDebug) + { + // Create the output dictionary + var protections = new ConcurrentDictionary(); + + // Iterate through all checks + Parallel.ForEach(MSDOSExecutableCheckClasses, checkClass => + { + // Get the protection for the class, if possible + string protection = checkClass.CheckMSDOSExecutable(file, mz, 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 /// diff --git a/BinaryObjectScanner.Interfaces/IMSDOSExecutableCheck.cs b/BinaryObjectScanner.Interfaces/IMSDOSExecutableCheck.cs new file mode 100644 index 00000000..19d8f3b9 --- /dev/null +++ b/BinaryObjectScanner.Interfaces/IMSDOSExecutableCheck.cs @@ -0,0 +1,19 @@ +using BinaryObjectScanner.Wrappers; + +namespace BinaryObjectScanner.Interfaces +{ + /// + /// Check a MS-DOS Executable (MZ) for protection + /// + public interface IMSDOSExecutableCheck + { + /// + /// Check a path for protections based on file contents + /// + /// File to check for protection indicators + /// MSDOS representing the read-in file + /// True to include debug data, false otherwise + /// String containing any protections found in the file + string CheckMSDOSExecutable(string file, MSDOS mz, bool includeDebug); + } +} diff --git a/BurnOutSharp/Scanner.cs b/BurnOutSharp/Scanner.cs index 11766d4f..cf3a663a 100644 --- a/BurnOutSharp/Scanner.cs +++ b/BurnOutSharp/Scanner.cs @@ -391,9 +391,19 @@ namespace BurnOutSharp AppendToDictionary(protections, fileName, subProtections.Values.ToArray()); } - if (wrapper is MSDOS) + if (wrapper is MSDOS mz) { - // No-op until protection classes implmented + var subProtections = executable.RunMSDOSExecutableChecks(fileName, stream, mz, IncludeDebug); + if (subProtections == null) + return protections; + + // Append the returned values + AppendToDictionary(protections, fileName, subProtections.Values.ToArray()); + + // If we have any extractable packers + var extractedProtections = HandleExtractableProtections(subProtections.Keys, fileName, stream); + if (extractedProtections != null) + AppendToDictionary(protections, extractedProtections); } else if (wrapper is LinearExecutable lex) {