diff --git a/BurnOutSharp/FileType/Executable.cs b/BurnOutSharp/FileType/Executable.cs index 510a044a..856ac493 100644 --- a/BurnOutSharp/FileType/Executable.cs +++ b/BurnOutSharp/FileType/Executable.cs @@ -4,6 +4,8 @@ using System.IO; using System.Text; using System.Threading.Tasks; using BurnOutSharp.Interfaces; +using BurnOutSharp.Matching; +using BurnOutSharp.Utilities; using BurnOutSharp.Wrappers; using static BurnOutSharp.Utilities.Dictionary; @@ -53,14 +55,10 @@ namespace BurnOutSharp.FileType } } - // Create Executable objects for use in the checks - stream.Seek(0, SeekOrigin.Begin); - LinearExecutable lex = LinearExecutable.Create(stream); - stream.Seek(0, SeekOrigin.Begin); - NewExecutable nex = NewExecutable.Create(stream); - stream.Seek(0, SeekOrigin.Begin); - PortableExecutable pex = PortableExecutable.Create(stream); - stream.Seek(0, SeekOrigin.Begin); + // Get the wrapper for the appropriate executable type + WrapperBase wrapper = DetermineExecutableType(stream); + if (wrapper == null) + return protections; // Iterate through all generic content checks if (fileContent != null) @@ -84,8 +82,14 @@ namespace BurnOutSharp.FileType }); } - // If we have a NE executable, iterate through all NE content checks - if (nex != null) + // If we have an MS-DOS executable + if (wrapper is MSDOS mz) + { + // No-op + } + + // If we have a New Executable + if (wrapper is NewExecutable nex) { Parallel.ForEach(ScanningClasses.NewExecutableCheckClasses, contentCheckClass => { @@ -107,8 +111,14 @@ namespace BurnOutSharp.FileType }); } - // If we have a PE executable, iterate through all PE content checks - if (pex != null) + // If we have a Linear Executable + else if (wrapper is LinearExecutable lex) + { + // No-op + } + + // If we have a Portable Executable + else if (wrapper is PortableExecutable pex) { Parallel.ForEach(ScanningClasses.PortableExecutableCheckClasses, contentCheckClass => { @@ -135,6 +145,52 @@ namespace BurnOutSharp.FileType #region Helpers + /// + /// Determine the executable type from the stream + /// + /// Stream data to parse + /// WrapperBase representing the executable, null on error + private WrapperBase DetermineExecutableType(Stream stream) + { + // Try to get an MS-DOS wrapper first + WrapperBase wrapper = MSDOS.Create(stream); + if (wrapper == null) + return null; + + // Check for a valid new executable address + if ((wrapper as MSDOS).NewExeHeaderAddr >= stream.Length) + return wrapper; + + // Try to read the executable info + stream.Seek((wrapper as MSDOS).NewExeHeaderAddr, SeekOrigin.Begin); + byte[] magic = stream.ReadBytes(4); + + // New Executable + if (magic.StartsWith(Models.NewExecutable.Constants.SignatureBytes)) + { + stream.Seek(0, SeekOrigin.Begin); + return NewExecutable.Create(stream); + } + + // Linear Executable + else if (magic.StartsWith(Models.LinearExecutable.Constants.LESignatureBytes) + || magic.StartsWith(Models.LinearExecutable.Constants.LXSignatureBytes)) + { + stream.Seek(0, SeekOrigin.Begin); + return LinearExecutable.Create(stream); + } + + // Portable Executable + else if (magic.StartsWith(Models.PortableExecutable.Constants.SignatureBytes)) + { + stream.Seek(0, SeekOrigin.Begin); + return PortableExecutable.Create(stream); + } + + // Everything else fails + return null; + } + /// /// Check to see if a protection should be added or not ///