diff --git a/BinaryObjectScanner.FileType/Executable.cs b/BinaryObjectScanner.FileType/Executable.cs index 732e7db6..0154ef32 100644 --- a/BinaryObjectScanner.FileType/Executable.cs +++ b/BinaryObjectScanner.FileType/Executable.cs @@ -270,7 +270,11 @@ namespace BinaryObjectScanner.FileType Parallel.ForEach(ContentCheckClasses, checkClass => { // Get the protection for the class, if possible +#if NET48 string protection = checkClass.CheckContents(file, fileContent, includeDebug); +#else + string? protection = checkClass.CheckContents(file, fileContent, includeDebug); +#endif if (string.IsNullOrWhiteSpace(protection)) return; @@ -304,7 +308,11 @@ namespace BinaryObjectScanner.FileType Parallel.ForEach(LinearExecutableCheckClasses, checkClass => { // Get the protection for the class, if possible +#if NET48 string protection = checkClass.CheckLinearExecutable(file, lex, includeDebug); +#else + string? protection = checkClass.CheckLinearExecutable(file, lex, includeDebug); +#endif if (string.IsNullOrWhiteSpace(protection)) return; @@ -338,7 +346,11 @@ namespace BinaryObjectScanner.FileType Parallel.ForEach(MSDOSExecutableCheckClasses, checkClass => { // Get the protection for the class, if possible +#if NET48 string protection = checkClass.CheckMSDOSExecutable(file, mz, includeDebug); +#else + string? protection = checkClass.CheckMSDOSExecutable(file, mz, includeDebug); +#endif if (string.IsNullOrWhiteSpace(protection)) return; @@ -372,7 +384,11 @@ namespace BinaryObjectScanner.FileType Parallel.ForEach(NewExecutableCheckClasses, checkClass => { // Get the protection for the class, if possible +#if NET48 string protection = checkClass.CheckNewExecutable(file, nex, includeDebug); +#else + string? protection = checkClass.CheckNewExecutable(file, nex, includeDebug); +#endif if (string.IsNullOrWhiteSpace(protection)) return; @@ -406,7 +422,11 @@ namespace BinaryObjectScanner.FileType Parallel.ForEach(PortableExecutableCheckClasses, checkClass => { // Get the protection for the class, if possible +#if NET48 string protection = checkClass.CheckPortableExecutable(file, pex, includeDebug); +#else + string? protection = checkClass.CheckPortableExecutable(file, pex, includeDebug); +#endif if (string.IsNullOrWhiteSpace(protection)) return; @@ -449,9 +469,10 @@ namespace BinaryObjectScanner.FileType private static IEnumerable? InitCheckClasses(Assembly assembly) #endif { - return assembly.GetTypes() - .Where(t => t.IsClass && t.GetInterface(typeof(T).Name) != null) - .Select(t => (T)Activator.CreateInstance(t)); + return assembly.GetTypes()? + .Where(t => t.IsClass && t.GetInterface(typeof(T).Name) != null)? + .Select(t => (T)Activator.CreateInstance(t)) + .Cast() ?? Array.Empty(); } #endregion @@ -464,7 +485,7 @@ namespace BinaryObjectScanner.FileType /// Implementation that was last used to check private static bool CheckIfGameEngine(object impl) { - return impl.GetType().Namespace.ToLowerInvariant().Contains("gameengine"); + return impl?.GetType()?.Namespace?.ToLowerInvariant()?.Contains("gameengine") ?? false; } /// @@ -473,7 +494,7 @@ namespace BinaryObjectScanner.FileType /// Implementation that was last used to check private static bool CheckIfPacker(object impl) { - return impl.GetType().Namespace.ToLowerInvariant().Contains("packer"); + return impl.GetType()?.Namespace?.ToLowerInvariant()?.Contains("packer") ?? false; } #endregion diff --git a/BinaryObjectScanner.GameEngine/RenderWare.cs b/BinaryObjectScanner.GameEngine/RenderWare.cs index ebef7268..3f20617a 100644 --- a/BinaryObjectScanner.GameEngine/RenderWare.cs +++ b/BinaryObjectScanner.GameEngine/RenderWare.cs @@ -18,10 +18,14 @@ namespace BinaryObjectScanner.GameEngine public class RenderWare : IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; diff --git a/BinaryObjectScanner.Interfaces/IContentCheck.cs b/BinaryObjectScanner.Interfaces/IContentCheck.cs index 7fda9ac4..492f544c 100644 --- a/BinaryObjectScanner.Interfaces/IContentCheck.cs +++ b/BinaryObjectScanner.Interfaces/IContentCheck.cs @@ -12,6 +12,10 @@ /// Byte array representing the file contents /// True to include debug data, false otherwise /// String containing any protections found in the file +#if NET48 string CheckContents(string file, byte[] fileContent, bool includeDebug); +#else + string? CheckContents(string file, byte[] fileContent, bool includeDebug); +#endif } } diff --git a/BinaryObjectScanner.Interfaces/ILinearExecutableCheck.cs b/BinaryObjectScanner.Interfaces/ILinearExecutableCheck.cs index 287c860a..c9a13d35 100644 --- a/BinaryObjectScanner.Interfaces/ILinearExecutableCheck.cs +++ b/BinaryObjectScanner.Interfaces/ILinearExecutableCheck.cs @@ -14,6 +14,10 @@ namespace BinaryObjectScanner.Interfaces /// LinearExecutable representing the read-in file /// True to include debug data, false otherwise /// String containing any protections found in the file +#if NET48 string CheckLinearExecutable(string file, LinearExecutable lex, bool includeDebug); +#else + string? CheckLinearExecutable(string file, LinearExecutable lex, bool includeDebug); +#endif } } diff --git a/BinaryObjectScanner.Interfaces/IMSDOSExecutableCheck.cs b/BinaryObjectScanner.Interfaces/IMSDOSExecutableCheck.cs index c43bb9bb..35165f4d 100644 --- a/BinaryObjectScanner.Interfaces/IMSDOSExecutableCheck.cs +++ b/BinaryObjectScanner.Interfaces/IMSDOSExecutableCheck.cs @@ -14,6 +14,10 @@ namespace BinaryObjectScanner.Interfaces /// MSDOS representing the read-in file /// True to include debug data, false otherwise /// String containing any protections found in the file +#if NET48 string CheckMSDOSExecutable(string file, MSDOS mz, bool includeDebug); +#else + string? CheckMSDOSExecutable(string file, MSDOS mz, bool includeDebug); +#endif } } diff --git a/BinaryObjectScanner.Interfaces/INewExecutableCheck.cs b/BinaryObjectScanner.Interfaces/INewExecutableCheck.cs index b0684b65..38aa6f66 100644 --- a/BinaryObjectScanner.Interfaces/INewExecutableCheck.cs +++ b/BinaryObjectScanner.Interfaces/INewExecutableCheck.cs @@ -14,6 +14,10 @@ namespace BinaryObjectScanner.Interfaces /// NewExecutable representing the read-in file /// True to include debug data, false otherwise /// String containing any protections found in the file +#if NET48 string CheckNewExecutable(string file, NewExecutable nex, bool includeDebug); +#else + string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug); +#endif } } diff --git a/BinaryObjectScanner.Interfaces/IPathCheck.cs b/BinaryObjectScanner.Interfaces/IPathCheck.cs index 29067cc6..6ea51191 100644 --- a/BinaryObjectScanner.Interfaces/IPathCheck.cs +++ b/BinaryObjectScanner.Interfaces/IPathCheck.cs @@ -24,6 +24,10 @@ namespace BinaryObjectScanner.Interfaces /// /// Path to check for protection indicators /// This can do some limited content checking as well, but it's suggested to use a content check instead, if possible +#if NET48 string CheckFilePath(string path); +#else + string? CheckFilePath(string path); +#endif } } diff --git a/BinaryObjectScanner.Interfaces/IPortableExecutableCheck.cs b/BinaryObjectScanner.Interfaces/IPortableExecutableCheck.cs index 098c9ab2..c507511f 100644 --- a/BinaryObjectScanner.Interfaces/IPortableExecutableCheck.cs +++ b/BinaryObjectScanner.Interfaces/IPortableExecutableCheck.cs @@ -14,6 +14,10 @@ namespace BinaryObjectScanner.Interfaces /// PortableExecutable representing the read-in file /// True to include debug data, false otherwise /// String containing any protections found in the file +#if NET48 string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug); +#else + string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug); +#endif } } diff --git a/BinaryObjectScanner.Packer/ASPack.cs b/BinaryObjectScanner.Packer/ASPack.cs index b54c0621..c8bcd67f 100644 --- a/BinaryObjectScanner.Packer/ASPack.cs +++ b/BinaryObjectScanner.Packer/ASPack.cs @@ -11,10 +11,14 @@ namespace BinaryObjectScanner.Packer public class ASPack : IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -28,7 +32,7 @@ namespace BinaryObjectScanner.Packer // if (pex.EntryPointRaw != null) // { // var matchers = GenerateMatchers(); - // string match = MatchUtil.GetFirstMatch(file, pex.EntryPointRaw, matchers, includeDebug); + // var match = MatchUtil.GetFirstMatch(file, pex.EntryPointRaw, matchers, includeDebug); // if (!string.IsNullOrWhiteSpace(match)) // return match; // } @@ -37,11 +41,15 @@ namespace BinaryObjectScanner.Packer var adataSection = pex.GetFirstSection(".adata", exact: false); if (adataSection != null) { +#if NET48 var adataSectionRaw = pex.GetFirstSectionData(Encoding.UTF8.GetString(adataSection.Name)); +#else + var adataSectionRaw = pex.GetFirstSectionData(Encoding.UTF8.GetString(adataSection.Name!)); +#endif if (adataSectionRaw != null) { var matchers = GenerateMatchers(); - string match = MatchUtil.GetFirstMatch(file, adataSectionRaw, matchers, includeDebug); + var match = MatchUtil.GetFirstMatch(file, adataSectionRaw, matchers, includeDebug); if (!string.IsNullOrWhiteSpace(match)) return match; } diff --git a/BinaryObjectScanner.Packer/AdvancedInstaller.cs b/BinaryObjectScanner.Packer/AdvancedInstaller.cs index 1bbbfbc3..eb55b0b2 100644 --- a/BinaryObjectScanner.Packer/AdvancedInstaller.cs +++ b/BinaryObjectScanner.Packer/AdvancedInstaller.cs @@ -11,15 +11,19 @@ namespace BinaryObjectScanner.Packer public class AdvancedInstaller : IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Get the .rdata section strings, if they exist - List strs = pex.GetFirstSectionStrings(".rdata"); + var strs = pex.GetFirstSectionStrings(".rdata"); if (strs != null) { if (strs.Any(s => s.Contains("Software\\Caphyon\\Advanced Installer"))) diff --git a/BinaryObjectScanner.Packer/Armadillo.cs b/BinaryObjectScanner.Packer/Armadillo.cs index f92edc22..e41ce70d 100644 --- a/BinaryObjectScanner.Packer/Armadillo.cs +++ b/BinaryObjectScanner.Packer/Armadillo.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using System.IO; +using System.IO; using System.Linq; using BinaryObjectScanner.Interfaces; using SabreTools.Serialization.Wrappers; @@ -12,10 +11,14 @@ namespace BinaryObjectScanner.Packer public class Armadillo : IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -25,14 +28,17 @@ namespace BinaryObjectScanner.Packer return "Armadillo"; // Loop through all "extension" sections -- usually .data1 or .text1 - foreach (var sectionName in pex.SectionNames.Where(s => s != null && s.EndsWith("1"))) + if (pex.SectionNames != null) { - // Get the section strings, if they exist - List strs = pex.GetFirstSectionStrings(sectionName); - if (strs != null) + foreach (var sectionName in pex.SectionNames.Where(s => s != null && s.EndsWith("1"))) { - if (strs.Any(s => s.Contains("ARMDEBUG"))) - return "Armadillo"; + // Get the section strings, if they exist + var strs = pex.GetFirstSectionStrings(sectionName); + if (strs != null) + { + if (strs.Any(s => s.Contains("ARMDEBUG"))) + return "Armadillo"; + } } } diff --git a/BinaryObjectScanner.Packer/AutoPlayMediaStudio.cs b/BinaryObjectScanner.Packer/AutoPlayMediaStudio.cs index e690e08f..100d9e8f 100644 --- a/BinaryObjectScanner.Packer/AutoPlayMediaStudio.cs +++ b/BinaryObjectScanner.Packer/AutoPlayMediaStudio.cs @@ -11,15 +11,19 @@ namespace BinaryObjectScanner.Packer public class AutoPlayMediaStudio : IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Known to detect versions 5.0.0.3 - 8.1.0.0 - string name = pex.ProductName; + var name = pex.ProductName; if (name?.StartsWith("AutoPlay Media Studio", StringComparison.OrdinalIgnoreCase) == true) return $"AutoPlay Media Studio {GetVersion(pex)}"; @@ -58,11 +62,15 @@ namespace BinaryObjectScanner.Packer { return null; } - + private string GetVersion(PortableExecutable pex) { // Check the product version explicitly +#if NET48 string version = pex.ProductVersion; +#else + string? version = pex.ProductVersion; +#endif if (!string.IsNullOrEmpty(version)) return version; diff --git a/BinaryObjectScanner.Packer/CExe.cs b/BinaryObjectScanner.Packer/CExe.cs index 7bfe83b3..8a093f4f 100644 --- a/BinaryObjectScanner.Packer/CExe.cs +++ b/BinaryObjectScanner.Packer/CExe.cs @@ -16,10 +16,14 @@ namespace BinaryObjectScanner.Packer public class CExe : IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -27,7 +31,9 @@ namespace BinaryObjectScanner.Packer if (pex.FindResourceByNamedType("99, ").Count() == 2) return "CExe"; - var matchers = new List + if (pex.StubExecutableData != null) + { + var matchers = new List { new ContentMatchSet(new byte?[] { @@ -40,9 +46,10 @@ namespace BinaryObjectScanner.Packer }, "CExe") }; - string match = MatchUtil.GetFirstMatch(file, pex.StubExecutableData, matchers, includeDebug); - if (!string.IsNullOrWhiteSpace(match)) - return match; + var match = MatchUtil.GetFirstMatch(file, pex.StubExecutableData, matchers, includeDebug); + if (!string.IsNullOrWhiteSpace(match)) + return match; + } return null; } @@ -73,12 +80,12 @@ namespace BinaryObjectScanner.Packer try { // Parse into an executable again for easier extraction - PortableExecutable pex = PortableExecutable.Create(stream); + var pex = PortableExecutable.Create(stream); if (pex == null) return null; // Get the first resource of type 99 with index 2 - byte[] payload = pex.FindResourceByNamedType("99, 2").FirstOrDefault(); + var payload = pex.FindResourceByNamedType("99, 2").FirstOrDefault(); if (payload == null || payload.Length == 0) return null; @@ -86,7 +93,7 @@ namespace BinaryObjectScanner.Packer bool zlib = pex.FindResourceByNamedType("99, 1").Any(); // Create the output data buffer - byte[] data; + var data = new byte[0]; // If we had the decompression DLL included, it's zlib if (zlib) diff --git a/BinaryObjectScanner.Packer/EXEStealth.cs b/BinaryObjectScanner.Packer/EXEStealth.cs index c1f6867d..e18b2f9e 100644 --- a/BinaryObjectScanner.Packer/EXEStealth.cs +++ b/BinaryObjectScanner.Packer/EXEStealth.cs @@ -13,7 +13,11 @@ namespace BinaryObjectScanner.Packer public class EXEStealth : IContentCheck, IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckContents(string file, byte[] fileContent, bool includeDebug) +#else + public string? CheckContents(string file, byte[] fileContent, bool includeDebug) +#endif { // TODO: Obtain a sample to find where this string is in a typical executable if (includeDebug) @@ -38,10 +42,14 @@ namespace BinaryObjectScanner.Packer } /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; diff --git a/BinaryObjectScanner.Packer/EmbeddedExecutable.cs b/BinaryObjectScanner.Packer/EmbeddedExecutable.cs index f96ea6a2..9d02e2ba 100644 --- a/BinaryObjectScanner.Packer/EmbeddedExecutable.cs +++ b/BinaryObjectScanner.Packer/EmbeddedExecutable.cs @@ -14,10 +14,14 @@ namespace BinaryObjectScanner.Packer public class EmbeddedExecutable : IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -54,14 +58,15 @@ namespace BinaryObjectScanner.Packer try { // Parse into an executable again for easier extraction - PortableExecutable pex = PortableExecutable.Create(stream); + var pex = PortableExecutable.Create(stream); if (pex?.ResourceData == null) return null; // Get the resources that have an executable signature var resources = pex.ResourceData .Where(kvp => kvp.Value != null && kvp.Value is byte[]) - .Where(kvp => (kvp.Value as byte[]).StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes)) + .Select(kvp => kvp.Value as byte[]) + .Where(b => b != null && b.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes)) .ToList(); string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); @@ -72,17 +77,19 @@ namespace BinaryObjectScanner.Packer try { // Get the resource data - var resource = resources[i]; - byte[] data = resource.Value as byte[]; + var data = resources[i]; + if (data == null) + continue; // Create the temp filename string tempFile = $"embedded_resource_{i}.bin"; tempFile = Path.Combine(tempPath, tempFile); // Write the resource data to a temp file - using (Stream tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) + using (var tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) { - tempStream.Write(data, 0, data.Length); + if (tempStream != null) + tempStream.Write(data, 0, data.Length); } } catch (Exception ex) diff --git a/BinaryObjectScanner.Packer/GenteeInstaller.cs b/BinaryObjectScanner.Packer/GenteeInstaller.cs index 142df93e..98cca5dc 100644 --- a/BinaryObjectScanner.Packer/GenteeInstaller.cs +++ b/BinaryObjectScanner.Packer/GenteeInstaller.cs @@ -11,15 +11,19 @@ namespace BinaryObjectScanner.Packer public class GenteeInstaller : IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Get the .data/DATA section strings, if they exist - List strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); + var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); if (strs != null) { if (strs.Any(s => s.Contains("Gentee installer"))) diff --git a/BinaryObjectScanner.Packer/HyperTechCrackProof.cs b/BinaryObjectScanner.Packer/HyperTechCrackProof.cs index 562b2a34..df90aa4c 100644 --- a/BinaryObjectScanner.Packer/HyperTechCrackProof.cs +++ b/BinaryObjectScanner.Packer/HyperTechCrackProof.cs @@ -13,17 +13,21 @@ namespace BinaryObjectScanner.Packer public class HyperTechCrackProof : IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // This check may be overly limiting, as it excludes the sample provided to DiE (https://github.com/horsicq/Detect-It-Easy/issues/102). // TODO: Find further samples and invesitgate if the "peC" section is only present on specific versions. bool peCSection = pex.ContainsSection("peC", exact: true); - bool importTableMatch = (pex.Model.ImportTable?.ImportDirectoryTable?.Any(idte => idte.Name == "KeRnEl32.dLl") ?? false); + bool importTableMatch = (pex.Model.ImportTable?.ImportDirectoryTable?.Any(idte => idte?.Name == "KeRnEl32.dLl") ?? false); if (peCSection && importTableMatch) return "HyperTech CrackProof"; diff --git a/BinaryObjectScanner.Packer/InnoSetup.cs b/BinaryObjectScanner.Packer/InnoSetup.cs index 6371d392..66039bf6 100644 --- a/BinaryObjectScanner.Packer/InnoSetup.cs +++ b/BinaryObjectScanner.Packer/InnoSetup.cs @@ -12,14 +12,14 @@ namespace BinaryObjectScanner.Packer public class InnoSetup : IExtractable, INewExecutableCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckNewExecutable(string file, NewExecutable nex, bool includeDebug) +#else + public string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug) +#endif { - // Check we have a valid executable - if (nex == null) - return null; - // Check for "Inno" in the reserved words - if (nex.Model.Stub?.Header?.Reserved2[4] == 0x6E49 && nex.Model.Stub?.Header?.Reserved2[5] == 0x6F6E) + if (nex.Model.Stub?.Header?.Reserved2?[4] == 0x6E49 && nex.Model.Stub?.Header?.Reserved2?[5] == 0x6F6E) { string version = GetOldVersion(file, nex); if (!string.IsNullOrWhiteSpace(version)) @@ -32,18 +32,22 @@ namespace BinaryObjectScanner.Packer } /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Get the .data/DATA section strings, if they exist - List strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); + var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); if (strs != null) { - string str = strs.FirstOrDefault(s => s.StartsWith("Inno Setup Setup Data")); + var str = strs.FirstOrDefault(s => s.StartsWith("Inno Setup Setup Data")); if (str != null) { return str.Replace("Inno Setup Setup Data", "Inno Setup") diff --git a/BinaryObjectScanner.Packer/InstallAnywhere.cs b/BinaryObjectScanner.Packer/InstallAnywhere.cs index 5ce4d5c0..8be6e7ab 100644 --- a/BinaryObjectScanner.Packer/InstallAnywhere.cs +++ b/BinaryObjectScanner.Packer/InstallAnywhere.cs @@ -10,14 +10,18 @@ namespace BinaryObjectScanner.Packer public class InstallAnywhere : IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string name = pex.FileDescription; + var name= pex.FileDescription; if (name?.StartsWith("InstallAnywhere Self Extractor", StringComparison.OrdinalIgnoreCase) == true) return $"InstallAnywhere {GetVersion(pex)}"; @@ -57,7 +61,7 @@ namespace BinaryObjectScanner.Packer private string GetVersion(PortableExecutable pex) { // Check the internal versions - string version = pex.GetInternalVersion(); + var version = pex.GetInternalVersion(); if (!string.IsNullOrEmpty(version)) return version; diff --git a/BinaryObjectScanner.Packer/InstallerVISE.cs b/BinaryObjectScanner.Packer/InstallerVISE.cs index 2c2d9d5c..0bc6dfe3 100644 --- a/BinaryObjectScanner.Packer/InstallerVISE.cs +++ b/BinaryObjectScanner.Packer/InstallerVISE.cs @@ -12,15 +12,19 @@ namespace BinaryObjectScanner.Packer { //TODO: Add exact version detection for Windows builds, make sure versions before 3.X are detected as well, and detect the Mac builds. /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Get the .data/DATA section strings, if they exist - List strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); + var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); if (strs != null) { if (strs.Any(s => s.Contains("ViseMain"))) diff --git a/BinaryObjectScanner.Packer/IntelInstallationFramework.cs b/BinaryObjectScanner.Packer/IntelInstallationFramework.cs index 82ad2a2c..b20986ff 100644 --- a/BinaryObjectScanner.Packer/IntelInstallationFramework.cs +++ b/BinaryObjectScanner.Packer/IntelInstallationFramework.cs @@ -9,14 +9,18 @@ namespace BinaryObjectScanner.Packer public class IntelInstallationFramework : IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string name = pex.FileDescription; + var name= pex.FileDescription; if (name?.Equals("Intel(R) Installation Framework", StringComparison.OrdinalIgnoreCase) == true || name?.Equals("Intel Installation Framework", StringComparison.OrdinalIgnoreCase) == true) { diff --git a/BinaryObjectScanner.Packer/MicrosoftCABSFX.cs b/BinaryObjectScanner.Packer/MicrosoftCABSFX.cs index 7619e0ba..79fcb0e7 100644 --- a/BinaryObjectScanner.Packer/MicrosoftCABSFX.cs +++ b/BinaryObjectScanner.Packer/MicrosoftCABSFX.cs @@ -12,14 +12,18 @@ namespace BinaryObjectScanner.Packer public class MicrosoftCABSFX : IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string name = pex.InternalName; + var name= pex.InternalName; if (name?.Equals("Wextract", StringComparison.OrdinalIgnoreCase) == true) return $"Microsoft CAB SFX {GetVersion(pex)}"; @@ -28,7 +32,7 @@ namespace BinaryObjectScanner.Packer return $"Microsoft CAB SFX {GetVersion(pex)}"; // Get the .data/DATA section strings, if they exist - List strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); + var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); if (strs != null) { if (strs.Any(s => s.Contains("wextract_cleanup"))) @@ -77,7 +81,7 @@ namespace BinaryObjectScanner.Packer private string GetVersion(PortableExecutable pex) { // Check the internal versions - string version = pex.GetInternalVersion(); + var version = pex.GetInternalVersion(); if (!string.IsNullOrWhiteSpace(version)) return $"v{version}"; diff --git a/BinaryObjectScanner.Packer/NSIS.cs b/BinaryObjectScanner.Packer/NSIS.cs index 898f4c1b..380980a6 100644 --- a/BinaryObjectScanner.Packer/NSIS.cs +++ b/BinaryObjectScanner.Packer/NSIS.cs @@ -10,19 +10,23 @@ namespace BinaryObjectScanner.Packer public class NSIS : IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string description = pex.AssemblyDescription; + var description = pex.AssemblyDescription; if (!string.IsNullOrWhiteSpace(description) && description.StartsWith("Nullsoft Install System")) return $"NSIS {description.Substring("Nullsoft Install System".Length).Trim()}"; // Get the .data/DATA section strings, if they exist - List strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); + var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); if (strs != null) { if (strs.Any(s => s.Contains("NullsoftInst"))) diff --git a/BinaryObjectScanner.Packer/NeoLite.cs b/BinaryObjectScanner.Packer/NeoLite.cs index fb53f033..0ece86af 100644 --- a/BinaryObjectScanner.Packer/NeoLite.cs +++ b/BinaryObjectScanner.Packer/NeoLite.cs @@ -18,10 +18,14 @@ namespace BinaryObjectScanner.Packer { // TODO: Find samples of NeoLite 1.X. /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; diff --git a/BinaryObjectScanner.Packer/PECompact.cs b/BinaryObjectScanner.Packer/PECompact.cs index 0e6e2f36..38bf0666 100644 --- a/BinaryObjectScanner.Packer/PECompact.cs +++ b/BinaryObjectScanner.Packer/PECompact.cs @@ -9,10 +9,14 @@ namespace BinaryObjectScanner.Packer public class PECompact : IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; diff --git a/BinaryObjectScanner.Packer/Petite.cs b/BinaryObjectScanner.Packer/Petite.cs index e990f8e7..e68836a5 100644 --- a/BinaryObjectScanner.Packer/Petite.cs +++ b/BinaryObjectScanner.Packer/Petite.cs @@ -9,10 +9,14 @@ namespace BinaryObjectScanner.Packer public class PEtite : IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; diff --git a/BinaryObjectScanner.Packer/SetupFactory.cs b/BinaryObjectScanner.Packer/SetupFactory.cs index 90d41cb4..77328272 100644 --- a/BinaryObjectScanner.Packer/SetupFactory.cs +++ b/BinaryObjectScanner.Packer/SetupFactory.cs @@ -11,15 +11,19 @@ namespace BinaryObjectScanner.Packer public class SetupFactory : IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Known to detect versions 7.0.5.1 - 9.1.0.0 - string name = pex.LegalCopyright; + var name = pex.LegalCopyright; if (name?.StartsWith("Setup Engine", StringComparison.OrdinalIgnoreCase) == true) return $"Setup Factory {GetVersion(pex)}"; @@ -67,7 +71,7 @@ namespace BinaryObjectScanner.Packer private string GetVersion(PortableExecutable pex) { // Check the product version explicitly - string version = pex.ProductVersion; + var version = pex.ProductVersion; if (!string.IsNullOrEmpty(version)) return version; diff --git a/BinaryObjectScanner.Packer/SevenZipSFX.cs b/BinaryObjectScanner.Packer/SevenZipSFX.cs index 5a4ca313..ef0c9c27 100644 --- a/BinaryObjectScanner.Packer/SevenZipSFX.cs +++ b/BinaryObjectScanner.Packer/SevenZipSFX.cs @@ -9,10 +9,14 @@ namespace BinaryObjectScanner.Packer public class SevenZipSFX : IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; diff --git a/BinaryObjectScanner.Packer/Shrinker.cs b/BinaryObjectScanner.Packer/Shrinker.cs index 9ab2ecd5..b69907f0 100644 --- a/BinaryObjectScanner.Packer/Shrinker.cs +++ b/BinaryObjectScanner.Packer/Shrinker.cs @@ -9,10 +9,14 @@ namespace BinaryObjectScanner.Packer public class Shrinker : IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; diff --git a/BinaryObjectScanner.Packer/UPX.cs b/BinaryObjectScanner.Packer/UPX.cs index 7f0764b2..eeb3fc0f 100644 --- a/BinaryObjectScanner.Packer/UPX.cs +++ b/BinaryObjectScanner.Packer/UPX.cs @@ -17,17 +17,21 @@ namespace BinaryObjectScanner.Packer private static readonly Regex _upxVersionMatch = new Regex(@"^([0-9]\.[0-9]{2})$", RegexOptions.Compiled); /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Check header padding strings if (pex.HeaderPaddingStrings?.Any() == true) { - string match = pex.HeaderPaddingStrings.FirstOrDefault(s => s.Contains("UPX!")); + var match = pex.HeaderPaddingStrings.FirstOrDefault(s => s.Contains("UPX!")); //if (match != null) // return "UPX"; @@ -42,7 +46,7 @@ namespace BinaryObjectScanner.Packer } match = pex.HeaderPaddingStrings.FirstOrDefault(s => _upxVersionMatch.IsMatch(s)); - if (pex.HeaderPaddingStrings.Any(s => s == "UPX!" && match != null)) + if (match != null && pex.HeaderPaddingStrings.Any(s => s == "UPX!")) { var regexMatch = _upxVersionMatch.Match(match); if (regexMatch.Success) @@ -50,7 +54,7 @@ namespace BinaryObjectScanner.Packer else return "UPX (Unknown Version)"; } - else if (pex.HeaderPaddingStrings.Any(s => s == "NOS " && match != null)) + else if (match != null && pex.HeaderPaddingStrings.Any(s => s == "NOS ")) { var regexMatch = _upxVersionMatch.Match(match); if (regexMatch.Success) diff --git a/BinaryObjectScanner.Packer/WinRARSFX.cs b/BinaryObjectScanner.Packer/WinRARSFX.cs index 5c30bd08..d843a896 100644 --- a/BinaryObjectScanner.Packer/WinRARSFX.cs +++ b/BinaryObjectScanner.Packer/WinRARSFX.cs @@ -12,14 +12,18 @@ namespace BinaryObjectScanner.Packer public class WinRARSFX : IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string name = pex.AssemblyDescription; + var name = pex.AssemblyDescription; if (name?.Contains("WinRAR archiver") == true) return "WinRAR SFX"; diff --git a/BinaryObjectScanner.Packer/WinZipSFX.cs b/BinaryObjectScanner.Packer/WinZipSFX.cs index c45e2670..77b009a6 100644 --- a/BinaryObjectScanner.Packer/WinZipSFX.cs +++ b/BinaryObjectScanner.Packer/WinZipSFX.cs @@ -12,19 +12,19 @@ namespace BinaryObjectScanner.Packer public class WinZipSFX : IExtractable, INewExecutableCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckNewExecutable(string file, NewExecutable nex, bool includeDebug) +#else + public string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug) +#endif { - // Check we have a valid executable - if (nex == null) - return null; - // If the resident-name table doesnt exist if (nex.Model.ResidentNameTable == null) return null; // Check for the WinZip name string - bool winZipNameFound = nex.Model.ResidentNameTable.Where(rnte => rnte?.NameString != null) - .Select(rnte => Encoding.ASCII.GetString(rnte.NameString)) + bool winZipNameFound = nex.Model.ResidentNameTable + .Select(rnte => rnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(rnte.NameString)) .Any(s => s.Contains("WZ-SE-01")); // If we didn't find it @@ -32,7 +32,7 @@ namespace BinaryObjectScanner.Packer return null; // Try to get a known version - string version = GetNEHeaderVersion(nex); + var version = GetNEHeaderVersion(nex); if (!string.IsNullOrWhiteSpace(version)) return $"WinZip SFX {version}"; @@ -40,17 +40,21 @@ namespace BinaryObjectScanner.Packer } /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Check the export directory table, if it exists if (pex.Model.ExportTable?.ExportDirectoryTable != null) { - string version = GetPEExportDirectoryVersion(pex); + var version = GetPEExportDirectoryVersion(pex); if (!string.IsNullOrWhiteSpace(version)) return $"WinZip SFX {version}"; } @@ -130,7 +134,11 @@ namespace BinaryObjectScanner.Packer /// /// TODO: Reduce the checks to only the ones that differ between versions /// TODO: Research to see if the versions are embedded elsewhere in these files +#if NET48 private string GetNEHeaderVersion(NewExecutable nex) +#else + private string? GetNEHeaderVersion(NewExecutable nex) +#endif { #region 2.0 Variants @@ -688,10 +696,14 @@ namespace BinaryObjectScanner.Packer /// Get the version from the PE export directory table value combinations /// /// TODO: Research to see if the versions are embedded elsewhere in these files +#if NET48 private string GetPEExportDirectoryVersion(PortableExecutable pex) +#else + private string? GetPEExportDirectoryVersion(PortableExecutable pex) +#endif { - string sfxFileName = pex.Model.ExportTable.ExportDirectoryTable.Name; - uint sfxTimeDateStamp = pex.Model.ExportTable.ExportDirectoryTable.TimeDateStamp; + string sfxFileName = pex.Model.ExportTable?.ExportDirectoryTable?.Name ?? string.Empty; + uint sfxTimeDateStamp = pex.Model.ExportTable?.ExportDirectoryTable?.TimeDateStamp ?? uint.MaxValue; string assemblyVersion = pex.AssemblyVersion ?? "Unknown Version"; // Standard diff --git a/BinaryObjectScanner.Packer/WiseInstaller.cs b/BinaryObjectScanner.Packer/WiseInstaller.cs index 57337227..d31f207a 100644 --- a/BinaryObjectScanner.Packer/WiseInstaller.cs +++ b/BinaryObjectScanner.Packer/WiseInstaller.cs @@ -14,12 +14,12 @@ namespace BinaryObjectScanner.Packer public class WiseInstaller : IExtractable, INewExecutableCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckNewExecutable(string file, NewExecutable nex, bool includeDebug) +#else + public string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug) +#endif { - /// Check we have a valid executable - if (nex == null) - return null; - // If we match a known header if (MatchesNEVersion(nex) != null) return "Wise Installation Wizard Module"; @@ -44,10 +44,14 @@ namespace BinaryObjectScanner.Packer } /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -58,7 +62,7 @@ namespace BinaryObjectScanner.Packer // TODO: Investigate STUB32.EXE in export directory table // Get the .data/DATA section strings, if they exist - List strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); + var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); if (strs != null) { if (strs.Any(s => s.Contains("WiseMain"))) @@ -102,12 +106,12 @@ namespace BinaryObjectScanner.Packer try { // Try to parse as a New Executable - NewExecutable nex = NewExecutable.Create(stream); + var nex = NewExecutable.Create(stream); if (nex != null) return ExtractNewExecutable(nex, file, includeDebug); // Try to parse as a Portable Executable - PortableExecutable pex = PortableExecutable.Create(stream); + var pex = PortableExecutable.Create(stream); if (pex != null) return ExtractPortableExecutable(pex, file, includeDebug); @@ -125,7 +129,11 @@ namespace BinaryObjectScanner.Packer /// /// New executable to check /// True if it matches a known version, false otherwise +#if NET48 private FormatProperty MatchesNEVersion(NewExecutable nex) +#else + private FormatProperty? MatchesNEVersion(NewExecutable nex) +#endif { // TODO: Offset is _not_ the EXE header address, rather where the data starts. Fix this. switch (nex.Model.Stub?.Header?.NewExeHeaderAddr) @@ -182,7 +190,11 @@ namespace BinaryObjectScanner.Packer /// /// Portable executable to check /// True if it matches a known version, false otherwise +#if NET48 private FormatProperty GetPEFormat(PortableExecutable pex) +#else + private FormatProperty? GetPEFormat(PortableExecutable pex) +#endif { if (pex.OverlayAddress == 0x6e00 && pex.GetFirstSection(".text")?.VirtualSize == 0x3cf4 @@ -229,7 +241,11 @@ namespace BinaryObjectScanner.Packer /// Path to the input file /// True to include debug data, false otherwise /// True if it matches a known version, false otherwise +#if NET48 private string ExtractNewExecutable(NewExecutable nex, string file, bool includeDebug) +#else + private string? ExtractNewExecutable(NewExecutable nex, string file, bool includeDebug) +#endif { string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempPath); @@ -268,7 +284,11 @@ namespace BinaryObjectScanner.Packer /// Path to the input file /// True to include debug data, false otherwise /// True if it matches a known version, false otherwise +#if NET48 private string ExtractPortableExecutable(PortableExecutable pex, string file, bool includeDebug) +#else + private string? ExtractPortableExecutable(PortableExecutable pex, string file, bool includeDebug) +#endif { try { @@ -279,7 +299,7 @@ namespace BinaryObjectScanner.Packer // Get the overlay data for easier reading int overlayOffset = 0, dataStart = 0; - byte[] overlayData = pex.OverlayData; + var overlayData = pex.OverlayData; if (overlayData == null) return null; @@ -333,8 +353,8 @@ namespace BinaryObjectScanner.Packer int offsetReal = overlayOffset; // If the first entry is PKZIP, we assume it's an embedded zipfile - byte[] magic = overlayData.ReadBytes(ref overlayOffset, 4); overlayOffset -= 4; - bool pkzip = magic.StartsWith(new byte?[] { (byte)'P', (byte)'K' }); + var magic = overlayData.ReadBytes(ref overlayOffset, 4); overlayOffset -= 4; + bool pkzip = magic?.StartsWith(new byte?[] { (byte)'P', (byte)'K' }) ?? false; string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempPath); diff --git a/BinaryObjectScanner.Packer/dotFuscator.cs b/BinaryObjectScanner.Packer/dotFuscator.cs index ef553045..ba29acab 100644 --- a/BinaryObjectScanner.Packer/dotFuscator.cs +++ b/BinaryObjectScanner.Packer/dotFuscator.cs @@ -10,15 +10,19 @@ namespace BinaryObjectScanner.Packer public class dotFuscator : IExtractable, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Get the .text section strings, if they exist - List strs = pex.GetFirstSectionStrings(".text"); + var strs = pex.GetFirstSectionStrings(".text"); if (strs != null) { if (strs.Any(s => s.Contains("DotfuscatorAttribute"))) diff --git a/BinaryObjectScanner.Protection/ActiveMARK.cs b/BinaryObjectScanner.Protection/ActiveMARK.cs index 4b7bce65..82044201 100644 --- a/BinaryObjectScanner.Protection/ActiveMARK.cs +++ b/BinaryObjectScanner.Protection/ActiveMARK.cs @@ -11,7 +11,11 @@ namespace BinaryObjectScanner.Protection public class ActiveMARK : IContentCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckContents(string file, byte[] fileContent, bool includeDebug) +#else + public string? CheckContents(string file, byte[] fileContent, bool includeDebug) +#endif { // TODO: Obtain a sample to find where this string is in a typical executable if (includeDebug) @@ -34,10 +38,14 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -78,7 +86,7 @@ namespace BinaryObjectScanner.Protection } // Get the .data section strings, if they exist - List strs = pex.GetLastSectionStrings(".data"); + var strs = pex.GetLastSectionStrings(".data"); if (strs != null) { if (strs.Any(s => s.Contains("MPRMMGVA")) @@ -92,8 +100,8 @@ namespace BinaryObjectScanner.Protection var resources = pex.FindResourceByNamedType("REGISTRY, AMINTERNETPROTOCOL"); if (resources.Any()) { - bool match = resources.Where(r => r != null) - .Select(r => Encoding.ASCII.GetString(r)) + bool match = resources + .Select(r => r == null ? string.Empty : Encoding.ASCII.GetString(r)) .Any(r => r.Contains("ActiveMARK")); if (match) return "ActiveMARK"; diff --git a/BinaryObjectScanner.Protection/AegiSoft.cs b/BinaryObjectScanner.Protection/AegiSoft.cs index e0bbbcab..8942826a 100644 --- a/BinaryObjectScanner.Protection/AegiSoft.cs +++ b/BinaryObjectScanner.Protection/AegiSoft.cs @@ -20,10 +20,14 @@ namespace BinaryObjectScanner.Protection public class AegiSoft : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -58,7 +62,7 @@ namespace BinaryObjectScanner.Protection }, "AegiSoft License Manager"), }; - string match = MatchUtil.GetFirstMatch(file, dataSectionRaw, matchers, includeDebug); + var match = MatchUtil.GetFirstMatch(file, dataSectionRaw, matchers, includeDebug); if (!string.IsNullOrWhiteSpace(match)) return match; } @@ -84,7 +88,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/AlphaDVD.cs b/BinaryObjectScanner.Protection/AlphaDVD.cs index 667c1aa0..87f013fe 100644 --- a/BinaryObjectScanner.Protection/AlphaDVD.cs +++ b/BinaryObjectScanner.Protection/AlphaDVD.cs @@ -27,7 +27,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/AlphaROM.cs b/BinaryObjectScanner.Protection/AlphaROM.cs index bba17db5..9a06a1da 100644 --- a/BinaryObjectScanner.Protection/AlphaROM.cs +++ b/BinaryObjectScanner.Protection/AlphaROM.cs @@ -44,18 +44,22 @@ namespace BinaryObjectScanner.Protection public class AlphaROM : IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // TODO: Add support for detecting Alpha-ROM found in older games made with the RealLive engine. // TODO: Add version detection for Alpha-ROM. // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Get the .data/DATA section strings, if they exist - List strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); + var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); if (strs != null) { if (strs.Any(s => s.Contains("\\SETTEC"))) diff --git a/BinaryObjectScanner.Protection/Bitpool.cs b/BinaryObjectScanner.Protection/Bitpool.cs index 62380bc4..e39838b0 100644 --- a/BinaryObjectScanner.Protection/Bitpool.cs +++ b/BinaryObjectScanner.Protection/Bitpool.cs @@ -38,7 +38,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/ByteShield.cs b/BinaryObjectScanner.Protection/ByteShield.cs index 265b1d86..f5156c91 100644 --- a/BinaryObjectScanner.Protection/ByteShield.cs +++ b/BinaryObjectScanner.Protection/ByteShield.cs @@ -41,15 +41,19 @@ namespace BinaryObjectScanner.Protection public class ByteShield : IPortableExecutableCheck, IPathCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Found in "LineRider2.exe" in Redump entry 6236 - string name = pex.FileDescription; + var name = pex.FileDescription; if (name?.Equals("ByteShield Client") == true) return $"ByteShield Activation Client {pex.GetInternalVersion()}"; @@ -91,7 +95,7 @@ namespace BinaryObjectScanner.Protection return "ByteShield"; // Get the .data/DATA section strings, if they exist - List strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); + var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); if (strs != null) { // Found in "LineRider2.exe" in Redump entry 6236 @@ -128,7 +132,7 @@ namespace BinaryObjectScanner.Protection return null; } - + /// public ConcurrentQueue CheckDirectoryPath(string path, IEnumerable files) { @@ -144,7 +148,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { // TODO: Investigate reference to "bbz650.tmp" in "Byteshield.dll" (Redump entry 6236) // Files with the ".bbz" extension are associated with ByteShield, but the extenstion is known to be used in other places as well. diff --git a/BinaryObjectScanner.Protection/CDCheck.cs b/BinaryObjectScanner.Protection/CDCheck.cs index 8b9eaa31..c8068b8d 100644 --- a/BinaryObjectScanner.Protection/CDCheck.cs +++ b/BinaryObjectScanner.Protection/CDCheck.cs @@ -6,14 +6,18 @@ namespace BinaryObjectScanner.Protection public class CDCheck : IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string name = pex.Comments; + var name = pex.Comments; if (name?.Contains("CDCheck utlity for Microsoft Game Studios") == true) return "Microsoft Game Studios CD Check"; diff --git a/BinaryObjectScanner.Protection/CDDVDCops.cs b/BinaryObjectScanner.Protection/CDDVDCops.cs index a3ca3049..1dd2f09d 100644 --- a/BinaryObjectScanner.Protection/CDDVDCops.cs +++ b/BinaryObjectScanner.Protection/CDDVDCops.cs @@ -43,7 +43,11 @@ namespace BinaryObjectScanner.Protection { // TODO: Investigate reference to "CD32COPS.DLL" in "WETFLIPP.QZ_" in IA item "Triada_Russian_DVD_Complete_Collection_of_Erotic_Games". /// +#if NET48 public string CheckContents(string file, byte[] fileContent, bool includeDebug) +#else + public string? CheckContents(string file, byte[] fileContent, bool includeDebug) +#endif { // TODO: Obtain a sample to find where this string is in a typical executable if (includeDebug) @@ -73,12 +77,12 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckNewExecutable(string file, NewExecutable nex, bool includeDebug) +#else + public string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug) +#endif { - // Check we have a valid executable - if (nex == null) - return null; - // TODO: Don't read entire file var data = nex.ReadArbitraryRange(); if (data == null) @@ -96,7 +100,7 @@ namespace BinaryObjectScanner.Protection }, GetVersion, "CD-Cops"), }; - string match = MatchUtil.GetFirstMatch(file, data, neMatchSets, includeDebug); + var match = MatchUtil.GetFirstMatch(file, data, neMatchSets, includeDebug); if (!string.IsNullOrEmpty(match)) return match; @@ -104,8 +108,7 @@ namespace BinaryObjectScanner.Protection // Found in "h3blade.exe" in Redump entry 85077. bool importedNameTableEntries = nex.Model.ImportedNameTable? .Select(kvp => kvp.Value) - .Where(inte => inte.NameString != null) - .Select(inte => Encoding.ASCII.GetString(inte.NameString)) + .Select(inte => inte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(inte.NameString)) .Any(s => s.Contains("CDCOPS")) ?? false; if (importedNameTableEntries) return "CD-Cops"; @@ -113,8 +116,7 @@ namespace BinaryObjectScanner.Protection // Check the nonresident-name table // Found in "CDCOPS.DLL" in Redump entry 85077. bool nonresidentNameTableEntries = nex.Model.NonResidentNameTable? - .Where(nrnte => nrnte.NameString != null) - .Select(nrnte => Encoding.ASCII.GetString(nrnte.NameString)) + .Select(nrnte => nrnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(nrnte.NameString)) .Any(s => s.Contains("CDcops assembly-language DLL")) ?? false; if (nonresidentNameTableEntries) return "CD-Cops"; @@ -123,10 +125,14 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -161,7 +167,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/CDGuard.cs b/BinaryObjectScanner.Protection/CDGuard.cs index 548f99d1..e98fc96f 100644 --- a/BinaryObjectScanner.Protection/CDGuard.cs +++ b/BinaryObjectScanner.Protection/CDGuard.cs @@ -24,10 +24,14 @@ namespace BinaryObjectScanner.Protection public class CDGuard : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -46,7 +50,7 @@ namespace BinaryObjectScanner.Protection if (pex.Model.ImportTable?.ImportDirectoryTable != null) { // Found in "Randevu.exe" in Redump entry 97142. - bool match = pex.Model.ImportTable.ImportDirectoryTable.Any(idte => idte.Name?.Equals("cdguard.dll", StringComparison.OrdinalIgnoreCase) == true); + bool match = pex.Model.ImportTable.ImportDirectoryTable.Any(idte => idte?.Name != null && idte.Name.Equals("cdguard.dll", StringComparison.OrdinalIgnoreCase)); if (match) return "CD-Guard Copy Protection System"; } @@ -67,7 +71,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/CDKey.cs b/BinaryObjectScanner.Protection/CDKey.cs index c6dcedfa..a1ed161b 100644 --- a/BinaryObjectScanner.Protection/CDKey.cs +++ b/BinaryObjectScanner.Protection/CDKey.cs @@ -7,14 +7,18 @@ namespace BinaryObjectScanner.Protection public class CDKey : IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string name = pex.InternalName; + var name = pex.InternalName; if (name?.Equals("CDKey", StringComparison.OrdinalIgnoreCase) == true) return "CD-Key / Serial"; diff --git a/BinaryObjectScanner.Protection/CDLock.cs b/BinaryObjectScanner.Protection/CDLock.cs index 2a5cb2b9..6f7c8271 100644 --- a/BinaryObjectScanner.Protection/CDLock.cs +++ b/BinaryObjectScanner.Protection/CDLock.cs @@ -27,10 +27,14 @@ namespace BinaryObjectScanner.Protection public class CDLock : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -52,7 +56,7 @@ namespace BinaryObjectScanner.Protection }, "CD-Lock"), }; - string match = MatchUtil.GetFirstMatch(file, dataSectionRaw, matchers, includeDebug); + var match = MatchUtil.GetFirstMatch(file, dataSectionRaw, matchers, includeDebug); if (!string.IsNullOrWhiteSpace(match)) return match; } @@ -77,7 +81,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/CDProtector.cs b/BinaryObjectScanner.Protection/CDProtector.cs index d934f9fb..a22c2843 100644 --- a/BinaryObjectScanner.Protection/CDProtector.cs +++ b/BinaryObjectScanner.Protection/CDProtector.cs @@ -39,7 +39,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/CDSHiELDSE.cs b/BinaryObjectScanner.Protection/CDSHiELDSE.cs index 87ed7ffa..b659fa1f 100644 --- a/BinaryObjectScanner.Protection/CDSHiELDSE.cs +++ b/BinaryObjectScanner.Protection/CDSHiELDSE.cs @@ -8,10 +8,14 @@ namespace BinaryObjectScanner.Protection public class CDSHiELDSE : IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -25,7 +29,7 @@ namespace BinaryObjectScanner.Protection //} // Get the code/CODE section strings, if they exist - List strs = pex.GetFirstSectionStrings("code") ?? pex.GetFirstSectionStrings("CODE"); + var strs = pex.GetFirstSectionStrings("code") ?? pex.GetFirstSectionStrings("CODE"); if (strs != null) { if (strs.Any(s => s.Contains("~0017.tmp"))) diff --git a/BinaryObjectScanner.Protection/CDX.cs b/BinaryObjectScanner.Protection/CDX.cs index e3bd9c74..35bc2cf5 100644 --- a/BinaryObjectScanner.Protection/CDX.cs +++ b/BinaryObjectScanner.Protection/CDX.cs @@ -22,7 +22,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/CactusDataShield.cs b/BinaryObjectScanner.Protection/CactusDataShield.cs index 8d04a3a2..6b949f6a 100644 --- a/BinaryObjectScanner.Protection/CactusDataShield.cs +++ b/BinaryObjectScanner.Protection/CactusDataShield.cs @@ -8,7 +8,11 @@ namespace BinaryObjectScanner.Protection public class CactusDataShield : IContentCheck { /// +#if NET48 public string CheckContents(string file, byte[] fileContent, bool includeDebug) +#else + public string? CheckContents(string file, byte[] fileContent, bool includeDebug) +#endif { // TODO: Limit these checks to Mac binaries // TODO: Obtain a sample to find where this string is in a typical executable diff --git a/BinaryObjectScanner.Protection/CenegaProtectDVD.cs b/BinaryObjectScanner.Protection/CenegaProtectDVD.cs index 835801a4..4aba15da 100644 --- a/BinaryObjectScanner.Protection/CenegaProtectDVD.cs +++ b/BinaryObjectScanner.Protection/CenegaProtectDVD.cs @@ -15,10 +15,14 @@ namespace BinaryObjectScanner.Protection public class CengaProtectDVD : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -66,7 +70,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/ChosenBytesCodeLock.cs b/BinaryObjectScanner.Protection/ChosenBytesCodeLock.cs index b28d7012..290a9efc 100644 --- a/BinaryObjectScanner.Protection/ChosenBytesCodeLock.cs +++ b/BinaryObjectScanner.Protection/ChosenBytesCodeLock.cs @@ -23,21 +23,25 @@ namespace BinaryObjectScanner.Protection public class ChosenBytesCodeLock : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Found in "Code-Lock.ocx" in Code-Lock version 2.35. // Also worth noting is the File Description for this file, which is "A future for you, a challenge for the rest.". - string name = pex.ProductName; + var name = pex.ProductName; if (name?.StartsWith("Code-Lock", StringComparison.OrdinalIgnoreCase) == true) return $"ChosenBytes Code-Lock {pex.ProductVersion}"; // Get the .text section strings, if they exist - List strs = pex.GetFirstSectionStrings(".text"); + var strs = pex.GetFirstSectionStrings(".text"); if (strs != null) { if (strs.Any(s => s.Contains("CODE-LOCK.OCX"))) @@ -69,7 +73,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/CopyKiller.cs b/BinaryObjectScanner.Protection/CopyKiller.cs index bbb2a155..24312c80 100644 --- a/BinaryObjectScanner.Protection/CopyKiller.cs +++ b/BinaryObjectScanner.Protection/CopyKiller.cs @@ -8,7 +8,11 @@ namespace BinaryObjectScanner.Protection public class CopyKiller : IContentCheck, IPathCheck { /// +#if NET48 public string CheckContents(string file, byte[] fileContent, bool includeDebug) +#else + public string? CheckContents(string file, byte[] fileContent, bool includeDebug) +#endif { // TODO: Obtain a sample to find where this string is in a typical executable if (includeDebug) @@ -43,7 +47,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { // TODO: The following checks are overly broad and should be refined // TODO: Look into .PFF files as an indicator. At least one disc has those oversized files diff --git a/BinaryObjectScanner.Protection/CopyLok.cs b/BinaryObjectScanner.Protection/CopyLok.cs index 99a11fce..c7567355 100644 --- a/BinaryObjectScanner.Protection/CopyLok.cs +++ b/BinaryObjectScanner.Protection/CopyLok.cs @@ -23,17 +23,21 @@ namespace BinaryObjectScanner.Protection public class CopyLok : IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // If there are more than 2 icd-prefixed sections, then we have a match // Though this is the same name that SafeDisc uses for protected executables, this seems to be a coincidence. // Found in Redump entries 31557, 31674, 31675, 31708, 38239, 44210, and 53929. - int icdSectionCount = pex.SectionNames.Count(s => s.StartsWith("icd")); + int icdSectionCount = pex.SectionNames?.Count(s => s.StartsWith("icd")) ?? 0; if (icdSectionCount >= 2) return "CopyLok / CodeLok"; diff --git a/BinaryObjectScanner.Protection/CrypKey.cs b/BinaryObjectScanner.Protection/CrypKey.cs index 8d17a82a..770e73e8 100644 --- a/BinaryObjectScanner.Protection/CrypKey.cs +++ b/BinaryObjectScanner.Protection/CrypKey.cs @@ -10,10 +10,14 @@ namespace BinaryObjectScanner.Protection public class CrypKey : IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -21,7 +25,7 @@ namespace BinaryObjectScanner.Protection string version = pex.GetVersionInfoString("CrypKey Version") ?? string.Empty; // Found in 'cki32k.dll' - string name = pex.CompanyName; + var name = pex.CompanyName; if (name?.StartsWith("CrypKey") == true) return $"CrypKey {version}".TrimEnd(); diff --git a/BinaryObjectScanner.Protection/Cucko.cs b/BinaryObjectScanner.Protection/Cucko.cs index 25932254..4795756d 100644 --- a/BinaryObjectScanner.Protection/Cucko.cs +++ b/BinaryObjectScanner.Protection/Cucko.cs @@ -12,30 +12,40 @@ namespace BinaryObjectScanner.Protection public class Cucko : IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Get the .text section, if it exists - if (!pex.ContainsSection(".text")) - return null; - - var matchers = new List + if (pex.ContainsSection(".text")) { - // Confirmed to detect most examples known of Cucko. The only known exception is the version of "TSLHost.dll" included on Redump entry 36119. - // ŠU‰8...…™...ŠUŠ8T... - new ContentMatchSet(new byte?[] + var textData = pex.GetFirstSectionData(".text"); + if (textData != null) { - 0x8A, 0x55, 0x89, 0x38, 0x14, 0x1E, 0x0F, 0x85, - 0x99, 0x00, 0x00, 0x00, 0x8A, 0x55, 0x8A, 0x38, - 0x54, 0x1E, 0x01, 0x0F - }, "Cucko (EA Custom)") - }; + var matchers = new List + { + // Confirmed to detect most examples known of Cucko. The only known exception is the version of "TSLHost.dll" included on Redump entry 36119. + // ŠU‰8...…™...ŠUŠ8T... + new ContentMatchSet(new byte?[] + { + 0x8A, 0x55, 0x89, 0x38, 0x14, 0x1E, 0x0F, 0x85, + 0x99, 0x00, 0x00, 0x00, 0x8A, 0x55, 0x8A, 0x38, + 0x54, 0x1E, 0x01, 0x0F + }, "Cucko (EA Custom)") + }; - return MatchUtil.GetFirstMatch(file, pex.GetFirstSectionData(".text"), matchers, includeDebug); + return MatchUtil.GetFirstMatch(file, textData, matchers, includeDebug); + } + } + + return null; } } } diff --git a/BinaryObjectScanner.Protection/DVDCrypt.cs b/BinaryObjectScanner.Protection/DVDCrypt.cs index 40c5d28e..763a1b26 100644 --- a/BinaryObjectScanner.Protection/DVDCrypt.cs +++ b/BinaryObjectScanner.Protection/DVDCrypt.cs @@ -19,7 +19,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/DVDMoviePROTECT.cs b/BinaryObjectScanner.Protection/DVDMoviePROTECT.cs index aaec3eb0..84286cf8 100644 --- a/BinaryObjectScanner.Protection/DVDMoviePROTECT.cs +++ b/BinaryObjectScanner.Protection/DVDMoviePROTECT.cs @@ -20,6 +20,9 @@ namespace BinaryObjectScanner.Protection for (int i = 0; i < bupfiles.Length; i++) { FileInfo bupfile = new FileInfo(bupfiles[i]); + if (bupfile.DirectoryName == null) + continue; + FileInfo ifofile = new FileInfo(Path.Combine(bupfile.DirectoryName, bupfile.Name.Substring(0, bupfile.Name.Length - bupfile.Extension.Length) + ".ifo")); if (bupfile.Length != ifofile.Length) { @@ -33,7 +36,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { return null; } diff --git a/BinaryObjectScanner.Protection/Denuvo.cs b/BinaryObjectScanner.Protection/Denuvo.cs index 69ae58ef..4d2badb1 100644 --- a/BinaryObjectScanner.Protection/Denuvo.cs +++ b/BinaryObjectScanner.Protection/Denuvo.cs @@ -31,17 +31,21 @@ namespace BinaryObjectScanner.Protection // https://www.pcgamingwiki.com/wiki/Denuvo#Redeem.exe /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // All current checks for Denuvo Anti-Cheat come from Doom Eternal Update 1 (Steam Depot 782332, Manifest 7064393210727378308). // Found in "denuvo-anti-cheat.sys". - string name = pex.FileDescription; + var name = pex.FileDescription; if (name?.Equals("Denuvo Anti-Cheat Driver", StringComparison.OrdinalIgnoreCase) == true) return $"Denuvo Anti-Cheat"; @@ -157,7 +161,7 @@ namespace BinaryObjectScanner.Protection // "Denuvo v3.0b (x64)"), // }; - // string match = MatchUtil.GetFirstMatch(file, pex.EntryPointRaw, matchers, includeDebug); + // var match = MatchUtil.GetFirstMatch(file, pex.EntryPointRaw, matchers, includeDebug); // if (!string.IsNullOrWhiteSpace(match)) // return match; @@ -223,7 +227,7 @@ namespace BinaryObjectScanner.Protection // "Denuvo v2.0 (x86)"), // }; - // string match = MatchUtil.GetFirstMatch(file, pex.EntryPointRaw, matchers, includeDebug); + // var match = MatchUtil.GetFirstMatch(file, pex.EntryPointRaw, matchers, includeDebug); // if (!string.IsNullOrWhiteSpace(match)) // return match; @@ -253,7 +257,7 @@ namespace BinaryObjectScanner.Protection return null; } - + /// public ConcurrentQueue CheckDirectoryPath(string path, IEnumerable files) { @@ -274,7 +278,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/DinamicMultimedia.cs b/BinaryObjectScanner.Protection/DinamicMultimedia.cs index 6f359936..25f000a8 100644 --- a/BinaryObjectScanner.Protection/DinamicMultimedia.cs +++ b/BinaryObjectScanner.Protection/DinamicMultimedia.cs @@ -42,7 +42,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/DiscGuard.cs b/BinaryObjectScanner.Protection/DiscGuard.cs index 9e2e5759..bd51d538 100644 --- a/BinaryObjectScanner.Protection/DiscGuard.cs +++ b/BinaryObjectScanner.Protection/DiscGuard.cs @@ -38,15 +38,19 @@ namespace BinaryObjectScanner.Protection { // TODO: Add checks for the game executables, which seem likely to contain some kind of indicators that can be checked for. The game executables all seem to import "Ord(1)" from one of the varying DLLs present. /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Found in "IOSLinksys.dll" (Redump entries 31914, 46743, 46961, 79284, and 79374). - string name = pex.FileDescription; + var name = pex.FileDescription; if (name?.StartsWith("IOSLinkNT", StringComparison.OrdinalIgnoreCase) == true) return "DiscGuard"; @@ -75,58 +79,62 @@ namespace BinaryObjectScanner.Protection // Get the .vbn section, if it exists if (pex.ContainsSection(".vbn")) { - var matchers = new List + var vbnData = pex.GetFirstSectionData(".vbn"); + if (vbnData != null) { - // Found in "T29.dll" (Redump entry 31914). - // This check should be as long as the following check, as this data is nearly identical (including length) in the original files, but for some reason the section ends early, causing part of the remaining data to not be part of a section. - new ContentMatchSet(new byte?[] + var matchers = new List { - 0x7B, 0x39, 0x8F, 0x07, 0x47, 0xE9, 0x96, 0x8C, 0xCA, 0xB2, 0x5C, 0x50, - 0xC7, 0x5A, 0x18, 0xBD, 0x75, 0xB5, 0x68, 0x6A, 0x78, 0xB5, 0xCF, 0xF2, - 0xBE, 0xB3, 0xDB, 0xE9, 0x4E, 0x87, 0x8D, 0x46, 0x63, 0x0A, 0x54, 0xB8, - 0x4F, 0x85, 0x60, 0x2C, 0x06, 0xEC, 0xBD, 0x75, 0xF5, 0x6A, 0x6E, 0x35, - 0x4D, 0x5A, 0x8B, 0xF4, 0x12, 0x15, 0x23, 0xC8, 0xE9, 0x80, 0x01, 0x10, - 0xFE, 0xDB, 0xC6, 0x70, 0x1D, 0xC1, 0x4D, 0xAE, 0x9E, 0xE1, 0x01, 0xAA, - 0x9E, 0x50, 0x50, 0xC5, 0x66, 0x80, 0xC0, 0xA2, 0x2F, 0xA9, 0x7A, 0x3B, - 0x48, 0x74, 0x9D, 0x17, 0x33, 0x5D, 0x4C, 0x84, 0xD9, 0x54, 0xC4, 0x08, - 0xCC, 0x10, 0x2A, 0xF6, 0x91, 0x40, 0x51, 0xD3, 0xF5, 0x9A, 0x07, 0xE7, - 0xAB, 0xE9, 0x0B, 0xAD, 0xD4, 0x3A, 0xEC, 0xBA, 0x4B, 0x6C, 0xD2, 0x82, - 0x0D, 0xF5, 0x49, 0x83, 0x8E, 0xAB, 0x85, 0x92, 0x78, 0x1D, 0x69, 0x1E, - 0x44, 0xC6, 0xF6, 0xB4, 0x5F, 0x5F, 0xC2, 0x48, 0x5A, 0xED, 0x43, 0xD3, - 0xA4, 0x41, 0x81 - }, GetVersion, "DiscGuard"), + // Found in "T29.dll" (Redump entry 31914). + // This check should be as long as the following check, as this data is nearly identical (including length) in the original files, but for some reason the section ends early, causing part of the remaining data to not be part of a section. + new ContentMatchSet(new byte?[] + { + 0x7B, 0x39, 0x8F, 0x07, 0x47, 0xE9, 0x96, 0x8C, 0xCA, 0xB2, 0x5C, 0x50, + 0xC7, 0x5A, 0x18, 0xBD, 0x75, 0xB5, 0x68, 0x6A, 0x78, 0xB5, 0xCF, 0xF2, + 0xBE, 0xB3, 0xDB, 0xE9, 0x4E, 0x87, 0x8D, 0x46, 0x63, 0x0A, 0x54, 0xB8, + 0x4F, 0x85, 0x60, 0x2C, 0x06, 0xEC, 0xBD, 0x75, 0xF5, 0x6A, 0x6E, 0x35, + 0x4D, 0x5A, 0x8B, 0xF4, 0x12, 0x15, 0x23, 0xC8, 0xE9, 0x80, 0x01, 0x10, + 0xFE, 0xDB, 0xC6, 0x70, 0x1D, 0xC1, 0x4D, 0xAE, 0x9E, 0xE1, 0x01, 0xAA, + 0x9E, 0x50, 0x50, 0xC5, 0x66, 0x80, 0xC0, 0xA2, 0x2F, 0xA9, 0x7A, 0x3B, + 0x48, 0x74, 0x9D, 0x17, 0x33, 0x5D, 0x4C, 0x84, 0xD9, 0x54, 0xC4, 0x08, + 0xCC, 0x10, 0x2A, 0xF6, 0x91, 0x40, 0x51, 0xD3, 0xF5, 0x9A, 0x07, 0xE7, + 0xAB, 0xE9, 0x0B, 0xAD, 0xD4, 0x3A, 0xEC, 0xBA, 0x4B, 0x6C, 0xD2, 0x82, + 0x0D, 0xF5, 0x49, 0x83, 0x8E, 0xAB, 0x85, 0x92, 0x78, 0x1D, 0x69, 0x1E, + 0x44, 0xC6, 0xF6, 0xB4, 0x5F, 0x5F, 0xC2, 0x48, 0x5A, 0xED, 0x43, 0xD3, + 0xA4, 0x41, 0x81 + }, GetVersion, "DiscGuard"), - // Found in "T5375.dll" (Redump entry 79284), "TD352.dll" and "TE091.dll" (Redump entry 46743), "T71E1.dll" and "T7181.dll" (Redump entry 46961), and "TA0E4.DLL" (Redump entry 79374). - new ContentMatchSet(new byte?[] - { - 0x7B, 0x39, 0x8F, 0x07, 0x45, 0xE9, 0x96, 0x8C, 0xCA, 0xB2, 0x5C, 0x50, - 0xC7, 0x5A, 0x18, 0xBD, 0x75, 0xB5, 0x68, 0x6A, 0x78, 0xB5, 0xCF, 0xF2, - 0xBE, 0xB3, 0xDB, 0xE9, 0x4E, 0x87, 0x8D, 0x46, 0x63, 0x0A, 0x54, 0xB8, - 0x4F, 0x85, 0x60, 0x2C, 0x06, 0xEC, 0xBD, 0x75, 0xC6, 0xEB, 0x6E, 0x35, - 0xED, 0xD0, 0x8B, 0xF4, 0x15, 0x12, 0x3D, 0xF3, 0x65, 0xF7, 0x01, 0x10, - 0xF8, 0xFA, 0xC6, 0x70, 0x1D, 0xC1, 0x4D, 0xAE, 0x9E, 0xE1, 0x01, 0xAA, - 0x9E, 0x50, 0x50, 0xC5, 0x66, 0x80, 0xC0, 0xA2, 0x2F, 0xA9, 0x7A, 0x3B, - 0x48, 0x74, 0x9D, 0x17, 0x33, 0x5D, 0x4C, 0x84, 0xD9, 0x54, 0xC4, 0x08, - 0xCC, 0x10, 0x2A, 0xF6, 0x91, 0x40, 0x51, 0xD3, 0x41, 0x9A, 0x07, 0xE7, - 0xAB, 0xE9, 0x0B, 0xAD, 0xD4, 0x3A, 0xEC, 0xBA, 0xAF, 0x69, 0xD2, 0x82, - 0x67, 0xF5, 0x49, 0x83, 0x8E, 0xAB, 0x85, 0x92, 0x04, 0x19, 0x69, 0x1E, - 0x44, 0xC6, 0xF6, 0xB4, 0x5F, 0x5F, 0xC2, 0x48, 0x5A, 0xED, 0x43, 0xD3, - 0xA4, 0x41, 0x81, 0xAF, 0xB8, 0xCB, 0x46, 0xE3, 0xDA, 0x05, 0x36, 0xEA, - 0x05, 0xF5, 0xB9, 0xCE, 0x5F, 0x9A, 0xF5, 0x7D, 0x9E, 0x64, 0x66, 0xF9, - 0xA5, 0x7C, 0x4D, 0x1D, 0x1D, 0x95, 0x02, 0x52, 0x66, 0x23, 0xEF, 0xFF, - 0xEC, 0x63, 0x11, 0xEB, 0xF6, 0x66, 0x8F, 0x2B, 0xCF, 0x07, 0x50, 0x18, - 0xBE, 0x58, 0xCA, 0x08, 0x24, 0xAD, 0x81, 0x1A, 0xAB, 0x0E, 0x2D, 0x16, - 0x38, 0xAB, 0x22, 0xB5, 0xA8, 0xF0, 0x7D, 0x2E, 0xAF, 0x5E, 0xEA, 0x02, - 0x72, 0x20, 0x14, 0x19, 0x0E, 0x31, 0xF3, 0xD0, 0x40, 0xAE, 0xA2, 0xD5, - 0x0A, 0xA7, 0xB7, 0xAE, 0x02, 0xCF, 0xAC, 0x5F, 0xB8, 0x03, 0x15, 0x80, - 0x9A, 0x58, 0x5C, 0x03, 0x28, 0x31, 0x9E, 0xB8, 0x21, 0x5D, 0x07, 0xB3, - 0xB9, 0xEC, 0x75, 0xBA, 0xC2, 0xC8, 0x9D, 0x6F, 0x7A, 0xA1, 0x00, 0x8A - }, GetVersion, "DiscGuard"), - }; + // Found in "T5375.dll" (Redump entry 79284), "TD352.dll" and "TE091.dll" (Redump entry 46743), "T71E1.dll" and "T7181.dll" (Redump entry 46961), and "TA0E4.DLL" (Redump entry 79374). + new ContentMatchSet(new byte?[] + { + 0x7B, 0x39, 0x8F, 0x07, 0x45, 0xE9, 0x96, 0x8C, 0xCA, 0xB2, 0x5C, 0x50, + 0xC7, 0x5A, 0x18, 0xBD, 0x75, 0xB5, 0x68, 0x6A, 0x78, 0xB5, 0xCF, 0xF2, + 0xBE, 0xB3, 0xDB, 0xE9, 0x4E, 0x87, 0x8D, 0x46, 0x63, 0x0A, 0x54, 0xB8, + 0x4F, 0x85, 0x60, 0x2C, 0x06, 0xEC, 0xBD, 0x75, 0xC6, 0xEB, 0x6E, 0x35, + 0xED, 0xD0, 0x8B, 0xF4, 0x15, 0x12, 0x3D, 0xF3, 0x65, 0xF7, 0x01, 0x10, + 0xF8, 0xFA, 0xC6, 0x70, 0x1D, 0xC1, 0x4D, 0xAE, 0x9E, 0xE1, 0x01, 0xAA, + 0x9E, 0x50, 0x50, 0xC5, 0x66, 0x80, 0xC0, 0xA2, 0x2F, 0xA9, 0x7A, 0x3B, + 0x48, 0x74, 0x9D, 0x17, 0x33, 0x5D, 0x4C, 0x84, 0xD9, 0x54, 0xC4, 0x08, + 0xCC, 0x10, 0x2A, 0xF6, 0x91, 0x40, 0x51, 0xD3, 0x41, 0x9A, 0x07, 0xE7, + 0xAB, 0xE9, 0x0B, 0xAD, 0xD4, 0x3A, 0xEC, 0xBA, 0xAF, 0x69, 0xD2, 0x82, + 0x67, 0xF5, 0x49, 0x83, 0x8E, 0xAB, 0x85, 0x92, 0x04, 0x19, 0x69, 0x1E, + 0x44, 0xC6, 0xF6, 0xB4, 0x5F, 0x5F, 0xC2, 0x48, 0x5A, 0xED, 0x43, 0xD3, + 0xA4, 0x41, 0x81, 0xAF, 0xB8, 0xCB, 0x46, 0xE3, 0xDA, 0x05, 0x36, 0xEA, + 0x05, 0xF5, 0xB9, 0xCE, 0x5F, 0x9A, 0xF5, 0x7D, 0x9E, 0x64, 0x66, 0xF9, + 0xA5, 0x7C, 0x4D, 0x1D, 0x1D, 0x95, 0x02, 0x52, 0x66, 0x23, 0xEF, 0xFF, + 0xEC, 0x63, 0x11, 0xEB, 0xF6, 0x66, 0x8F, 0x2B, 0xCF, 0x07, 0x50, 0x18, + 0xBE, 0x58, 0xCA, 0x08, 0x24, 0xAD, 0x81, 0x1A, 0xAB, 0x0E, 0x2D, 0x16, + 0x38, 0xAB, 0x22, 0xB5, 0xA8, 0xF0, 0x7D, 0x2E, 0xAF, 0x5E, 0xEA, 0x02, + 0x72, 0x20, 0x14, 0x19, 0x0E, 0x31, 0xF3, 0xD0, 0x40, 0xAE, 0xA2, 0xD5, + 0x0A, 0xA7, 0xB7, 0xAE, 0x02, 0xCF, 0xAC, 0x5F, 0xB8, 0x03, 0x15, 0x80, + 0x9A, 0x58, 0x5C, 0x03, 0x28, 0x31, 0x9E, 0xB8, 0x21, 0x5D, 0x07, 0xB3, + 0xB9, 0xEC, 0x75, 0xBA, 0xC2, 0xC8, 0x9D, 0x6F, 0x7A, 0xA1, 0x00, 0x8A + }, GetVersion, "DiscGuard"), + }; - string match = MatchUtil.GetFirstMatch(file, pex.GetFirstSectionData(".vbn"), matchers, includeDebug); - if (!string.IsNullOrWhiteSpace(match)) - return match; + var match = MatchUtil.GetFirstMatch(file, vbnData, matchers, includeDebug); + if (!string.IsNullOrWhiteSpace(match)) + return match; + } } return null; @@ -163,7 +171,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { @@ -182,7 +194,11 @@ namespace BinaryObjectScanner.Protection private string GetVersion(PortableExecutable pex) { // Check the internal versions +#if NET48 string version = pex.GetInternalVersion(); +#else + string? version = pex.GetInternalVersion(); +#endif if (!string.IsNullOrEmpty(version)) return version; @@ -193,7 +209,7 @@ namespace BinaryObjectScanner.Protection private string GetVersion(string file, byte[] fileContent, List positions) { // Check the internal versions - string version = GetInternalVersion(file, null); + string version = GetInternalVersion(file, Array.Empty()); if (!string.IsNullOrEmpty(version)) return version; @@ -207,7 +223,7 @@ namespace BinaryObjectScanner.Protection using (Stream fileStream = File.Open(firstMatchedString, FileMode.Open, FileAccess.Read, FileShare.Read)) { var pex = PortableExecutable.Create(fileStream); - return pex.GetInternalVersion(); + return pex?.GetInternalVersion() ?? string.Empty; } } catch diff --git a/BinaryObjectScanner.Protection/EasyAntiCheat.cs b/BinaryObjectScanner.Protection/EasyAntiCheat.cs index 4d3f1570..e8cf916e 100644 --- a/BinaryObjectScanner.Protection/EasyAntiCheat.cs +++ b/BinaryObjectScanner.Protection/EasyAntiCheat.cs @@ -22,14 +22,18 @@ namespace BinaryObjectScanner.Protection { // TODO: Add support for detecting older versions, especially versions made before Easy Anti-Cheat was purchased by Epic Games. /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string name = pex.FileDescription; + var name = pex.FileDescription; // Found in "VideoHorrorSociety.exe" ("Video Horror Society", Patch 1.0.70309, Steam). if (!string.IsNullOrEmpty(name) && name.Contains("Easy Anti-Cheat Bootstrapper (EOS)")) return "Easy Anti-Cheat (EOS Version)"; @@ -127,7 +131,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { // TODO: Search for the presence of the folder "EasyAntiCheat" specifically, which is present in every checked version so far. var matchers = new List diff --git a/BinaryObjectScanner.Protection/ElectronicArts.cs b/BinaryObjectScanner.Protection/ElectronicArts.cs index 91d18413..95505dbb 100644 --- a/BinaryObjectScanner.Protection/ElectronicArts.cs +++ b/BinaryObjectScanner.Protection/ElectronicArts.cs @@ -9,14 +9,18 @@ namespace BinaryObjectScanner.Protection public class ElectronicArts : IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string name = pex.FileDescription; + var name = pex.FileDescription; if (name?.Contains("EReg MFC Application") == true) return $"EA CdKey Registration Module {pex.GetInternalVersion()}"; else if (name?.Contains("Registration code installer program") == true) @@ -31,10 +35,10 @@ namespace BinaryObjectScanner.Protection if (pex.FindDialogByTitle("About CDKey").Any()) return $"EA CdKey Registration Module {pex.GetInternalVersion()}"; else if (pex.FindGenericResource("About CDKey").Any()) - return $"EA CdKey Registration Module {pex.GetInternalVersion()}"; + return $"EA CdKey Registration Module {pex.GetInternalVersion()}"; // Get the .data/DATA section strings, if they exist - List strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); + var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); if (strs != null) { if (strs.Any(s => s.Contains("EReg Config Form"))) diff --git a/BinaryObjectScanner.Protection/Engine32.cs b/BinaryObjectScanner.Protection/Engine32.cs index 990a73f3..b7ade925 100644 --- a/BinaryObjectScanner.Protection/Engine32.cs +++ b/BinaryObjectScanner.Protection/Engine32.cs @@ -16,10 +16,14 @@ namespace BinaryObjectScanner.Protection public class Engine32 : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -28,8 +32,8 @@ namespace BinaryObjectScanner.Protection // Detects Engine32 within the game executables that contain it. if (pex.Model.ImportTable?.ImportDirectoryTable != null && pex.Model.ImportTable?.HintNameTable != null) { - bool importDirectoryTableMatch = pex.Model.ImportTable.ImportDirectoryTable.Any(idte => idte.Name?.Equals("ENGINE32.DLL", StringComparison.OrdinalIgnoreCase) == true); - bool hintNameTableMatch = pex.Model.ImportTable?.HintNameTable.Any(ihne => ihne.Name == "InitEngine") ?? false; + bool importDirectoryTableMatch = pex.Model.ImportTable.ImportDirectoryTable.Any(idte => idte?.Name != null && idte.Name.Equals("ENGINE32.DLL", StringComparison.OrdinalIgnoreCase)); + bool hintNameTableMatch = pex.Model.ImportTable?.HintNameTable.Any(ihne => ihne?.Name == "InitEngine") ?? false; // The Hint/Name Table Entry "DeinitEngine" is present in every tested sample, aside from TOCA Race Driver 2 (Redump entries 104593-104596). @@ -62,7 +66,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/FreeLock.cs b/BinaryObjectScanner.Protection/FreeLock.cs index 3d6e6091..ec8dbb68 100644 --- a/BinaryObjectScanner.Protection/FreeLock.cs +++ b/BinaryObjectScanner.Protection/FreeLock.cs @@ -52,7 +52,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/GFWL.cs b/BinaryObjectScanner.Protection/GFWL.cs index 1be88ee3..abdcef75 100644 --- a/BinaryObjectScanner.Protection/GFWL.cs +++ b/BinaryObjectScanner.Protection/GFWL.cs @@ -11,14 +11,18 @@ namespace BurnOutSharp.ProtectionType public class GFWL : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string name = pex.FileDescription; + var name = pex.FileDescription; if (name?.StartsWith("Games for Windows - LIVE Zero Day Piracy Protection", StringComparison.OrdinalIgnoreCase) == true) return $"Games for Windows LIVE - Zero Day Piracy Protection Module {pex.GetInternalVersion()}"; else if (name?.StartsWith("Games for Windows", StringComparison.OrdinalIgnoreCase) == true) @@ -27,7 +31,7 @@ namespace BurnOutSharp.ProtectionType // Get the import directory table if (pex.Model.ImportTable?.ImportDirectoryTable != null) { - bool match = pex.Model.ImportTable.ImportDirectoryTable.Any(idte => idte.Name == "xlive.dll"); + bool match = pex.Model.ImportTable.ImportDirectoryTable.Any(idte => idte?.Name == "xlive.dll"); if (match) return "Games for Windows LIVE"; } @@ -50,7 +54,11 @@ namespace BurnOutSharp.ProtectionType } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/Gefest.cs b/BinaryObjectScanner.Protection/Gefest.cs index cc3c9ddf..320a5a5d 100644 --- a/BinaryObjectScanner.Protection/Gefest.cs +++ b/BinaryObjectScanner.Protection/Gefest.cs @@ -20,17 +20,25 @@ namespace BinaryObjectScanner.Protection public class Gefest : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Get the header padding strings, if it exists if (pex.HeaderPaddingStrings != null) { +#if NET48 string match = pex.HeaderPaddingStrings.FirstOrDefault(s => s.Contains("Gefest Protection System")); +#else + string? match = pex.HeaderPaddingStrings.FirstOrDefault(s => s.Contains("Gefest Protection System")); +#endif if (match != null) return $"Gefest Protection System {GetVersion(match)}"; } @@ -50,7 +58,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/HexaLock.cs b/BinaryObjectScanner.Protection/HexaLock.cs index 67826044..cd7620b0 100644 --- a/BinaryObjectScanner.Protection/HexaLock.cs +++ b/BinaryObjectScanner.Protection/HexaLock.cs @@ -33,16 +33,20 @@ namespace BinaryObjectScanner.Protection public class HexalockAutoLock : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // TODO: Fix the following checks, as this information is visible via Windows Explorer but isn't currently being seen by BOS. // Found in "HCPSMng.exe". - string name = pex.FileDescription; + var name = pex.FileDescription; if (name?.StartsWith("HCPS Manager", StringComparison.OrdinalIgnoreCase) == true) return $"Hexalock AutoLock 4.5"; @@ -56,7 +60,7 @@ namespace BinaryObjectScanner.Protection return $"Hexalock AutoLock 4.5"; // Get the .text section strings, if they exist - List strs = pex.GetFirstSectionStrings(".text"); + var strs = pex.GetFirstSectionStrings(".text"); if (strs != null) { // Found in "The Sudoku Challenge Collection.exe" in "The Sudoku Challenge! Collection" by Play at Joe's. @@ -103,7 +107,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/ImpulseReactor.cs b/BinaryObjectScanner.Protection/ImpulseReactor.cs index f24b533f..2e4b5b4a 100644 --- a/BinaryObjectScanner.Protection/ImpulseReactor.cs +++ b/BinaryObjectScanner.Protection/ImpulseReactor.cs @@ -13,14 +13,18 @@ namespace BinaryObjectScanner.Protection public class ImpulseReactor : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string name = pex.FileDescription; + var name = pex.FileDescription; if (name?.Contains("ImpulseReactor Dynamic Link Library") == true) return $"Impulse Reactor Core Module {pex.GetInternalVersion()}"; @@ -37,7 +41,7 @@ namespace BinaryObjectScanner.Protection bool containsCheck2 = false; // Get the .rdata section strings, if they exist - List strs = pex.GetFirstSectionStrings(".rdata"); + var strs = pex.GetFirstSectionStrings(".rdata"); if (strs != null) { containsCheck2 = strs.Any(s => s.EndsWith("ATTLIST")) @@ -66,7 +70,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { @@ -84,7 +92,7 @@ namespace BinaryObjectScanner.Protection using (Stream fileStream = File.Open(firstMatchedString, FileMode.Open, FileAccess.Read, FileShare.Read)) { var pex = PortableExecutable.Create(fileStream); - return pex.GetInternalVersion(); + return pex?.GetInternalVersion() ?? string.Empty; } } catch diff --git a/BinaryObjectScanner.Protection/IndyVCD.cs b/BinaryObjectScanner.Protection/IndyVCD.cs index f8512f84..b660a349 100644 --- a/BinaryObjectScanner.Protection/IndyVCD.cs +++ b/BinaryObjectScanner.Protection/IndyVCD.cs @@ -25,7 +25,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/Intenium.cs b/BinaryObjectScanner.Protection/Intenium.cs index 97e187f0..4b56e45d 100644 --- a/BinaryObjectScanner.Protection/Intenium.cs +++ b/BinaryObjectScanner.Protection/Intenium.cs @@ -23,10 +23,14 @@ namespace BinaryObjectScanner.Protection */ /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; diff --git a/BinaryObjectScanner.Protection/JoWood.cs b/BinaryObjectScanner.Protection/JoWood.cs index c69cb06a..c4932e98 100644 --- a/BinaryObjectScanner.Protection/JoWood.cs +++ b/BinaryObjectScanner.Protection/JoWood.cs @@ -13,23 +13,30 @@ namespace BinaryObjectScanner.Protection public class JoWood : IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Get the .ext section, if it exists if (pex.ContainsSection(".ext ", exact: true)) { - bool importTableMatches = (pex.Model.ImportTable?.ImportDirectoryTable?.Any(idte => idte.Name == "kernel32.dll") ?? false) - && (pex.Model.ImportTable?.HintNameTable?.Any(s => s.Name == "VirtualProtect") ?? false); + bool importTableMatches = (pex.Model.ImportTable?.ImportDirectoryTable?.Any(idte => idte?.Name == "kernel32.dll") ?? false) + && (pex.Model.ImportTable?.HintNameTable?.Any(s => s?.Name == "VirtualProtect") ?? false); // Get the .dcrtext section, if it exists if (pex.ContainsSection(".dcrtext") && importTableMatches) { - var matchers = new List + var dcrtextData = pex.GetFirstSectionData(".dcrtext"); + if (dcrtextData != null) + { + var matchers = new List { // kernel32.dll + (char)0x00 + (char)0x00 + (char)0x00 + VirtualProtect new ContentMatchSet(new byte?[] @@ -41,9 +48,10 @@ namespace BinaryObjectScanner.Protection }, GetVersion, "JoWood X-Prot"), }; - string match = MatchUtil.GetFirstMatch(file, pex.GetFirstSectionData(".dcrtext"), matchers, includeDebug); - if (!string.IsNullOrWhiteSpace(match)) - return match; + var match = MatchUtil.GetFirstMatch(file, dcrtextData, matchers, includeDebug); + if (!string.IsNullOrWhiteSpace(match)) + return match; + } } return "JoWood X-Prot v1.0-v1.3"; diff --git a/BinaryObjectScanner.Protection/KeyLock.cs b/BinaryObjectScanner.Protection/KeyLock.cs index f44b8976..7afd3d4d 100644 --- a/BinaryObjectScanner.Protection/KeyLock.cs +++ b/BinaryObjectScanner.Protection/KeyLock.cs @@ -7,7 +7,11 @@ namespace BinaryObjectScanner.Protection public class KeyLock : IContentCheck { /// +#if NET48 public string CheckContents(string file, byte[] fileContent, bool includeDebug) +#else + public string? CheckContents(string file, byte[] fileContent, bool includeDebug) +#endif { // TODO: Obtain a sample to find where this string is in a typical executable if (includeDebug) diff --git a/BinaryObjectScanner.Protection/LabelGate.cs b/BinaryObjectScanner.Protection/LabelGate.cs index a3fb90c8..4ac6d435 100644 --- a/BinaryObjectScanner.Protection/LabelGate.cs +++ b/BinaryObjectScanner.Protection/LabelGate.cs @@ -20,15 +20,19 @@ namespace BinaryObjectScanner.Protection public class LabelGate : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Should be present on all LabelGate CD2 discs (Redump entry 95010 and product ID SVWC-7185). - string name = pex.FileDescription; + var name = pex.FileDescription; if (name?.StartsWith("MAGIQLIP2 Installer", StringComparison.OrdinalIgnoreCase) == true) return $"LabelGate CD2 Media Player"; @@ -37,7 +41,7 @@ namespace BinaryObjectScanner.Protection return $"LabelGate CD2 Media Player"; // Get the .data/DATA section strings, if they exist - List strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); + var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); if (strs != null) { // Found in "START.EXE" (Redump entry 95010 and product ID SVWC-7185). @@ -73,7 +77,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/LaserLok.cs b/BinaryObjectScanner.Protection/LaserLok.cs index 2d96f9e8..49a9c99c 100644 --- a/BinaryObjectScanner.Protection/LaserLok.cs +++ b/BinaryObjectScanner.Protection/LaserLok.cs @@ -12,7 +12,11 @@ namespace BinaryObjectScanner.Protection public class LaserLok : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // TODO: Add entry point check // https://github.com/horsicq/Detect-It-Easy/blob/master/db/PE/Laserlok.2.sg @@ -49,7 +53,7 @@ namespace BinaryObjectScanner.Protection // }, "LaserLok 5"), // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -64,13 +68,14 @@ namespace BinaryObjectScanner.Protection 0x2E, 0x50, 0x45 }; int endDosStub = (int)(pex.Model.Stub?.Header?.NewExeHeaderAddr ?? 0); - bool containsCheck = pex.StubExecutableData.FirstPosition(check, out int position); + int position = -1; + bool containsCheck = pex.StubExecutableData?.FirstPosition(check, out position) ?? false; // Check the executable tables - bool containsCheck2 = (pex.Model.ImportTable?.HintNameTable.Any(hnte => hnte.Name == "GetModuleHandleA") ?? false) - && (pex.Model.ImportTable?.HintNameTable.Any(hnte => hnte.Name == "GetProcAddress") ?? false) - && (pex.Model.ImportTable?.HintNameTable.Any(hnte => hnte.Name == "LoadLibraryA") ?? false) - && (pex.Model.ImportTable?.ImportDirectoryTable.Any(idte => idte.Name == "KERNEL32.dll") ?? false); + bool containsCheck2 = (pex.Model.ImportTable?.HintNameTable?.Any(hnte => hnte?.Name == "GetModuleHandleA") ?? false) + && (pex.Model.ImportTable?.HintNameTable?.Any(hnte => hnte?.Name == "GetProcAddress") ?? false) + && (pex.Model.ImportTable?.HintNameTable?.Any(hnte => hnte?.Name == "LoadLibraryA") ?? false) + && (pex.Model.ImportTable?.ImportDirectoryTable?.Any(idte => idte?.Name == "KERNEL32.dll") ?? false); int position2 = -1; @@ -90,7 +95,7 @@ namespace BinaryObjectScanner.Protection 0x45, 0x4C, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0xEB, 0x79, 0x01, null, null, null, null, }; - containsCheck2 = pex.GetFirstSectionData(".text").FirstPosition(check2, out position2); + containsCheck2 = pex.GetFirstSectionData(".text")?.FirstPosition(check2, out position2) ?? false; } else { @@ -131,7 +136,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { @@ -150,7 +159,11 @@ namespace BinaryObjectScanner.Protection return MatchUtil.GetFirstMatch(path, matchers, any: true); } +#if NET48 private static string GetBuild(byte[] sectionContent, bool versionTwo) +#else + private static string GetBuild(byte[]? sectionContent, bool versionTwo) +#endif { if (sectionContent == null) return "(Build unknown)"; @@ -187,7 +200,11 @@ namespace BinaryObjectScanner.Protection return $"(Build {year}-{month}-{day})"; } +#if NET48 private static string GetVersion(byte[] sectionContent, int position) +#else + private static string? GetVersion(byte[]? sectionContent, int position) +#endif { // If we have invalid data if (sectionContent == null) diff --git a/BinaryObjectScanner.Protection/MGIRegistration.cs b/BinaryObjectScanner.Protection/MGIRegistration.cs index 2a15e453..aa6c217d 100644 --- a/BinaryObjectScanner.Protection/MGIRegistration.cs +++ b/BinaryObjectScanner.Protection/MGIRegistration.cs @@ -8,14 +8,18 @@ namespace BinaryObjectScanner.Protection public class MGIRegistration : IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string name = pex.ProductName; + var name = pex.ProductName; // Found in "Register.dll" in IA item "MGIPhotoSuite4.0AndPhotoVista2.02001". if (name?.Equals("MGI Registration Utility", StringComparison.Ordinal) == true) diff --git a/BinaryObjectScanner.Protection/Macrovision.CDilla.cs b/BinaryObjectScanner.Protection/Macrovision.CDilla.cs index 9b5f55cf..3c2db7a7 100644 --- a/BinaryObjectScanner.Protection/Macrovision.CDilla.cs +++ b/BinaryObjectScanner.Protection/Macrovision.CDilla.cs @@ -34,13 +34,13 @@ namespace BinaryObjectScanner.Protection /// public partial class Macrovision { - /// + /// +#if NET48 internal string CDillaCheckNewExecutable(string file, NewExecutable nex, bool includeDebug) +#else + internal string? CDillaCheckNewExecutable(string file, NewExecutable nex, bool includeDebug) +#endif { - // Check we have a valid executable - if (nex == null) - return null; - // TODO: Implement NE checks for "CDILLA05", "CDILLA10", "CDILLA16", and "CDILLA40". // TODO: Implement the following NE checks: @@ -64,15 +64,19 @@ namespace BinaryObjectScanner.Protection return null; } - /// + /// +#if NET48 internal string CDillaCheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) - { +#else + internal string? CDillaCheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif + { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string name = pex.FileDescription; + var name = pex.FileDescription; // Found in in "cdilla52.dll" from C-Dilla LMS version 3.24.010. if (name?.Equals("32-bit C-Dilla DLL", StringComparison.OrdinalIgnoreCase) == true) @@ -138,7 +142,7 @@ namespace BinaryObjectScanner.Protection return $"C-Dilla License Management System"; // Get the .data/DATA section strings, if they exist - List strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); + var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); if (strs != null) { // Found in "DJMixStation\DJMixStation.exe" in IA item "ejay_nestle_trial". @@ -151,7 +155,7 @@ namespace BinaryObjectScanner.Protection return null; } - /// + /// internal ConcurrentQueue CDillaCheckDirectoryPath(string path, IEnumerable files) { var matchers = new List @@ -194,8 +198,12 @@ namespace BinaryObjectScanner.Protection return MatchUtil.GetAllMatches(files, matchers, any: false); } - /// + /// +#if NET48 internal string CDillaCheckFilePath(string path) +#else + internal string? CDillaCheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/Macrovision.CactusDataShield.cs b/BinaryObjectScanner.Protection/Macrovision.CactusDataShield.cs index 973c3961..d3aa23b5 100644 --- a/BinaryObjectScanner.Protection/Macrovision.CactusDataShield.cs +++ b/BinaryObjectScanner.Protection/Macrovision.CactusDataShield.cs @@ -30,16 +30,20 @@ namespace BinaryObjectScanner.Protection /// public partial class Macrovision { - /// + /// +#if NET48 internal string CactusDataShieldCheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + internal string? CactusDataShieldCheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Get the .data/DATA section strings, if they exist - List strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); + var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); if (strs != null) { if (strs.Any(s => s.Contains("\\*.CDS"))) @@ -52,18 +56,18 @@ namespace BinaryObjectScanner.Protection // Found in "Volumia!" by Puur (Barcode 7 43218 63282 2) (Discogs Release Code [r795427]). // Modified version of the PlayJ Music Player specificaly for CDS, as indicated by the About page present when running the executable. var resources = pex.FindGenericResource("CactusPJ"); - if (resources.Any()) + if (resources != null && resources.Any()) return "PlayJ Music Player (Cactus Data Shield 200)"; // Found in various files in "Les Paul & Friends" (Barcode 4 98806 834170). - string name = pex.ProductName; + var name = pex.ProductName; if (name?.Equals("CDS300", StringComparison.OrdinalIgnoreCase) == true) return $"Cactus Data Shield 300"; return null; } - /// + /// internal ConcurrentQueue CactusDataShieldCheckDirectoryPath(string path, IEnumerable files) { // TODO: Verify if these are OR or AND @@ -90,8 +94,12 @@ namespace BinaryObjectScanner.Protection return MatchUtil.GetAllMatches(files, matchers, any: false); } - /// + /// +#if NET48 internal string CactusDataShieldCheckFilePath(string path) +#else + internal string? CactusDataShieldCheckFilePath(string path) +#endif { var matchers = new List { @@ -119,10 +127,18 @@ namespace BinaryObjectScanner.Protection public static string GetCactusDataShieldVersion(string firstMatchedString, IEnumerable files) { // Find the version.txt file first +#if NET48 string versionPath = files.FirstOrDefault(f => Path.GetFileName(f).Equals("version.txt", StringComparison.OrdinalIgnoreCase)); +#else + string? versionPath = files.FirstOrDefault(f => Path.GetFileName(f).Equals("version.txt", StringComparison.OrdinalIgnoreCase)); +#endif if (!string.IsNullOrWhiteSpace(versionPath)) { +#if NET48 string version = GetCactusDataShieldInternalVersion(versionPath); +#else + string? version = GetCactusDataShieldInternalVersion(versionPath); +#endif if (!string.IsNullOrWhiteSpace(version)) return version; } @@ -130,7 +146,11 @@ namespace BinaryObjectScanner.Protection return "200"; } +#if NET48 private static string GetCactusDataShieldInternalVersion(string path) +#else + private static string? GetCactusDataShieldInternalVersion(string path) +#endif { if (!File.Exists(path)) return null; @@ -139,7 +159,15 @@ namespace BinaryObjectScanner.Protection { using (var sr = new StreamReader(path, Encoding.Default)) { - return $"{sr.ReadLine().Substring(3)} ({sr.ReadLine()})"; +#if NET48 + string line = sr.ReadLine(); +#else + string? line = sr.ReadLine(); +#endif + if (line == null) + return null; + + return $"{line.Substring(3)} ({sr.ReadLine()})"; } } catch diff --git a/BinaryObjectScanner.Protection/Macrovision.FLEXnet.cs b/BinaryObjectScanner.Protection/Macrovision.FLEXnet.cs index 624c4cd4..43e362e9 100644 --- a/BinaryObjectScanner.Protection/Macrovision.FLEXnet.cs +++ b/BinaryObjectScanner.Protection/Macrovision.FLEXnet.cs @@ -8,16 +8,20 @@ namespace BinaryObjectScanner.Protection /// public partial class Macrovision { - /// + /// +#if NET48 internal string FLEXnetCheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + internal string? FLEXnetCheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Found in "IsSvcInstDanceEJay7.dll" in IA item "computer200709dvd" (Dance eJay 7). - string name = pex.ProductName; + var name = pex.ProductName; if (name?.Equals("FLEXnet Activation Toolkit", StringComparison.OrdinalIgnoreCase) == true) return $"FLEXnet"; diff --git a/BinaryObjectScanner.Protection/Macrovision.RipGuard.cs b/BinaryObjectScanner.Protection/Macrovision.RipGuard.cs index b7ea9634..b858a3a2 100644 --- a/BinaryObjectScanner.Protection/Macrovision.RipGuard.cs +++ b/BinaryObjectScanner.Protection/Macrovision.RipGuard.cs @@ -18,16 +18,20 @@ namespace BinaryObjectScanner.Protection /// public partial class Macrovision { - /// + /// +#if NET48 internal string RipGuardCheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + internal string? RipGuardCheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Found in "RGASDEV.SYS" in the Black Lagoon Season 1 DVD Steelbook box set (Geneon ID 12970). - string name = pex.FileDescription; + var name = pex.FileDescription; if (name?.Equals("rgasdev", StringComparison.OrdinalIgnoreCase) == true) return "RipGuard"; @@ -45,7 +49,11 @@ namespace BinaryObjectScanner.Protection // So far, every seemingly-randomly named EXE on RipGuard discs have a consistent hash. if (fi.Length == 49_152) { +#if NET48 string sha1 = GetFileSHA1(file); +#else + string? sha1 = GetFileSHA1(file); +#endif if (sha1 == "6A7B8545800E0AB252773A8CD0A2185CA2497938") return "RipGuard"; } @@ -58,7 +66,7 @@ namespace BinaryObjectScanner.Protection return null; } - /// + /// internal ConcurrentQueue RipGuardCheckDirectoryPath(string path, IEnumerable files) { var matchers = new List @@ -74,8 +82,12 @@ namespace BinaryObjectScanner.Protection return MatchUtil.GetAllMatches(files, matchers, any: false); } - /// + /// +#if NET48 internal string RipGuardCheckFilePath(string path) +#else + internal string? RipGuardCheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/Macrovision.SafeCast.cs b/BinaryObjectScanner.Protection/Macrovision.SafeCast.cs index f08e8ef0..19e36768 100644 --- a/BinaryObjectScanner.Protection/Macrovision.SafeCast.cs +++ b/BinaryObjectScanner.Protection/Macrovision.SafeCast.cs @@ -37,20 +37,23 @@ namespace BinaryObjectScanner.Protection /// public partial class Macrovision { - /// + /// +#if NET48 internal string SafeCastCheckNewExecutable(string file, NewExecutable nex, bool includeDebug) +#else + internal string? SafeCastCheckNewExecutable(string file, NewExecutable nex, bool includeDebug) +#endif { - // Check we have a valid executable. - if (nex == null) - return null; - // Check for the CDAC01AA name string. - bool cdac01aaNameFound = nex.Model.ResidentNameTable.Where(rnte => rnte?.NameString != null) - .Select(rnte => Encoding.ASCII.GetString(rnte.NameString)) + if (nex.Model.ResidentNameTable != null) + { + bool cdac01aaNameFound = nex.Model.ResidentNameTable + .Select(rnte => rnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(rnte.NameString)) .Any(s => s.Contains("CDAC01AA")); - - if (cdac01aaNameFound) - return "SafeCast"; + + if (cdac01aaNameFound) + return "SafeCast"; + } // TODO: Don't read entire file var data = nex.ReadArbitraryRange(); @@ -61,17 +64,21 @@ namespace BinaryObjectScanner.Protection { // SafeCast // Found as the Product Name in "cdac01aa.dll" from IA item "ejay_nestle_trial". Windows 10 appears to incorrectly truncate this to "SafeCas" in File Explorer. - new ContentMatchSet(new byte?[] { 0x53, 0x61, 0x66, 0x65, 0x43, 0x61, 0x73, 0x74 }, "SafeCast"), + new ContentMatchSet(new byte?[] { 0x53, 0x61, 0x66, 0x65, 0x43, 0x61, 0x73, 0x74 }, "SafeCast"), }; return MatchUtil.GetFirstMatch(file, data, neMatchSets, includeDebug); } - /// + /// +#if NET48 internal string SafeCastCheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + internal string? SafeCastCheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -81,7 +88,7 @@ namespace BinaryObjectScanner.Protection // Get the import directory table, if it exists if (pex.Model.ImportTable?.ImportDirectoryTable != null) { - if (pex.Model.ImportTable.ImportDirectoryTable.Any(idte => idte.Name?.Equals("CdaC14BA.dll", StringComparison.OrdinalIgnoreCase) == true)) + if (pex.Model.ImportTable.ImportDirectoryTable.Any(idte => idte?.Name != null && idte.Name.Equals("CdaC14BA.dll", StringComparison.OrdinalIgnoreCase))) return "SafeCast"; } @@ -92,7 +99,7 @@ namespace BinaryObjectScanner.Protection return "SafeCast"; // Get the .data/DATA section strings, if they exist - List strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); + var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); if (strs != null) { // Found in "DJMixStation\DJMixStation.exe" in IA item "ejay_nestle_trial". @@ -101,7 +108,7 @@ namespace BinaryObjectScanner.Protection } // Found in "32bit\Tax02\cdac14ba.dll" in IA item "TurboTax Deluxe Tax Year 2002 for Wndows (2.00R)(Intuit)(2002)(352282)". - string name = pex.FileDescription; + var name = pex.FileDescription; if (name?.Equals("SafeCast2", StringComparison.OrdinalIgnoreCase) == true) return "SafeCast"; @@ -144,7 +151,7 @@ namespace BinaryObjectScanner.Protection return null; } - /// + /// internal ConcurrentQueue SafeCastCheckDirectoryPath(string path, IEnumerable files) { var matchers = new List @@ -187,8 +194,12 @@ namespace BinaryObjectScanner.Protection return MatchUtil.GetAllMatches(files, matchers, any: false); } - /// + /// +#if NET48 internal string SafeCastCheckFilePath(string path) +#else + internal string? SafeCastCheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/Macrovision.SafeDisc.cs b/BinaryObjectScanner.Protection/Macrovision.SafeDisc.cs index 54562fc9..e3d9d845 100644 --- a/BinaryObjectScanner.Protection/Macrovision.SafeDisc.cs +++ b/BinaryObjectScanner.Protection/Macrovision.SafeDisc.cs @@ -41,26 +41,30 @@ namespace BinaryObjectScanner.Protection /// public partial class Macrovision { - /// + /// +#if NET48 internal string SafeDiscCheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + internal string? SafeDiscCheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Found in Redump entry 57986. - bool hintNameTableMatch = pex.Model.ImportTable?.HintNameTable?.Any(ihne => ihne.Name == "LTDLL_Authenticate") ?? false; + bool hintNameTableMatch = pex.Model.ImportTable?.HintNameTable?.Any(ihne => ihne?.Name == "LTDLL_Authenticate") ?? false; if (hintNameTableMatch) return "SafeDisc Lite"; // Found in Redump entry 57986. - bool importTableMatch = (pex.Model.ImportTable?.ImportDirectoryTable?.Any(idte => idte.Name == "ltdll.dll") ?? false); + bool importTableMatch = pex.Model.ImportTable?.ImportDirectoryTable?.Any(idte => idte?.Name == "ltdll.dll") ?? false; if (importTableMatch) return "SafeDisc Lite"; // Get the .data/DATA section strings, if they exist - List strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); + var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); if (strs != null) { // Found in Redump entries 14928, 25579, 32751. @@ -72,7 +76,7 @@ namespace BinaryObjectScanner.Protection return "SafeDisc Lite"; } - string name = pex.FileDescription; + var name = pex.FileDescription; // Present in "Diag.exe" files from SafeDisc 4.50.000+. if (name?.Equals("SafeDisc SRV Tool APP", StringComparison.OrdinalIgnoreCase) == true) return $"SafeDisc SRV Tool APP {GetSafeDiscDiagExecutableVersion(pex)}"; @@ -109,7 +113,7 @@ namespace BinaryObjectScanner.Protection return null; } - /// + /// internal ConcurrentQueue SafeDiscCheckDirectoryPath(string path, IEnumerable files) { var matchers = new List @@ -217,8 +221,12 @@ namespace BinaryObjectScanner.Protection return MatchUtil.GetAllMatches(files, matchers, any: false); } - /// + /// +#if NET48 internal string SafeDiscCheckFilePath(string path) +#else + internal string? SafeDiscCheckFilePath(string path) +#endif { var matchers = new List { @@ -300,7 +308,11 @@ namespace BinaryObjectScanner.Protection return string.Empty; // The hash of the file CLCD16.dll is able to provide a broad version range that appears to be consistent, but it seems it was rarely updated so these checks are quite broad. +#if NET48 string sha1 = GetFileSHA1(firstMatchedString); +#else + string? sha1 = GetFileSHA1(firstMatchedString); +#endif switch (sha1) { // Found in Redump entries 61731 and 66005. @@ -324,7 +336,11 @@ namespace BinaryObjectScanner.Protection return string.Empty; // The hash of the file CLCD32.dll so far appears to be a solid indicator of version for versions it was used with. It appears to have been updated with every release, unlike its counterpart, CLCD16.dll. +#if NET48 string sha1 = GetFileSHA1(firstMatchedString); +#else + string? sha1 = GetFileSHA1(firstMatchedString); +#endif switch (sha1) { // Found in Redump entry 66005. @@ -424,7 +440,11 @@ namespace BinaryObjectScanner.Protection // The hash of every "CLOKSPL.EXE" correlates directly to a specific SafeDisc version. +#if NET48 string sha1 = GetFileSHA1(firstMatchedString); +#else + string? sha1 = GetFileSHA1(firstMatchedString); +#endif switch (sha1) { // Found in Redump entry 66005. @@ -572,7 +592,11 @@ namespace BinaryObjectScanner.Protection // There are occasionaly inconsistencies, even within the well detected version range. This seems to me to mostly happen with later (3.20+) games, and seems to me to be an example of the SafeDisc distribution becoming more disorganized with time. // Particularly interesting inconsistencies will be noted below: // Redump entry 73786 has an EXE with a scrubbed version, a DIAG.exe with a version of 4.60.000, and a copy of drvmgt.dll belonging to version 3.10.020. This seems like an accidental(?) distribution of older drivers, as this game was released 3 years after the use of 3.10.020. +#if NET48 string sha1 = GetFileSHA1(firstMatchedString); +#else + string? sha1 = GetFileSHA1(firstMatchedString); +#endif switch (sha1) { // Found in Redump entry 102979. @@ -721,7 +745,11 @@ namespace BinaryObjectScanner.Protection } } +#if NET48 private string GetVersionFromSHA1Hash(string sha1Hash) +#else + private string? GetVersionFromSHA1Hash(string sha1Hash) +#endif { switch (sha1Hash.ToLowerInvariant()) { @@ -772,7 +800,11 @@ namespace BinaryObjectScanner.Protection private string GetSafeDiscDiagExecutableVersion(PortableExecutable pex) { // Different versions of this executable correspond to different SafeDisc versions. +#if NET48 string version = pex.FileVersion; +#else + string? version = pex.FileVersion; +#endif if (!string.IsNullOrEmpty(version)) { switch (version) diff --git a/BinaryObjectScanner.Protection/Macrovision.SafeWrap.cs b/BinaryObjectScanner.Protection/Macrovision.SafeWrap.cs index 632f51b9..99c91773 100644 --- a/BinaryObjectScanner.Protection/Macrovision.SafeWrap.cs +++ b/BinaryObjectScanner.Protection/Macrovision.SafeWrap.cs @@ -34,8 +34,12 @@ namespace BinaryObjectScanner.Protection /// public partial class Macrovision { - /// + /// +#if NET48 internal string SafeWrapCheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + internal string? SafeWrapCheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // TODO: Figure out what SafeWrap is exactly, and add checks. diff --git a/BinaryObjectScanner.Protection/Macrovision.cs b/BinaryObjectScanner.Protection/Macrovision.cs index 1459ae0c..cda6019c 100644 --- a/BinaryObjectScanner.Protection/Macrovision.cs +++ b/BinaryObjectScanner.Protection/Macrovision.cs @@ -21,21 +21,29 @@ namespace BinaryObjectScanner.Protection public partial class Macrovision : IPathCheck, INewExecutableCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckNewExecutable(string file, NewExecutable nex, bool includeDebug) +#else + public string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug) +#endif { - // Check we have a valid executable - if (nex == null) - return null; - - List resultsList = new List(); + var resultsList = new List(); // Run C-Dilla NE checks +#if NET48 string cDilla = CDillaCheckNewExecutable(file, nex, includeDebug); +#else + string? cDilla = CDillaCheckNewExecutable(file, nex, includeDebug); +#endif if (!string.IsNullOrWhiteSpace(cDilla)) resultsList.Add(cDilla); // Run SafeCast NE checks +#if NET48 string safeCast = SafeCastCheckNewExecutable(file, nex, includeDebug); +#else + string? safeCast = SafeCastCheckNewExecutable(file, nex, includeDebug); +#endif if (!string.IsNullOrWhiteSpace(safeCast)) resultsList.Add(safeCast); @@ -46,18 +54,22 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Check for specific indications for individual Macrovision protections. - List resultsList = new List(); + var resultsList = new List(); // Check for generic indications of Macrovision protections first. - string name = pex.FileDescription; + var name = pex.FileDescription; // Present in "secdrv.sys" files found in SafeDisc 2.80.010+. if (name?.Equals("Macrovision SECURITY Driver", StringComparison.OrdinalIgnoreCase) == true) @@ -76,7 +88,11 @@ namespace BinaryObjectScanner.Protection if (stxt371Section || stxt774Section) { // Check the header padding for protected sections. +#if NET48 string sectionMatch = CheckSectionForProtection(file, includeDebug, pex.HeaderPaddingStrings, pex.HeaderPaddingData, true); +#else + string? sectionMatch = CheckSectionForProtection(file, includeDebug, pex.HeaderPaddingStrings, pex.HeaderPaddingData, true); +#endif if (!string.IsNullOrWhiteSpace(sectionMatch)) { resultsList.Add(sectionMatch); @@ -90,7 +106,11 @@ namespace BinaryObjectScanner.Protection } int entryPointIndex = pex.FindEntryPointSectionIndex(); +#if NET48 string entryPointSectionName = pex.SectionNames[entryPointIndex]; +#else + string? entryPointSectionName = pex.SectionNames?[entryPointIndex]; +#endif switch (entryPointSectionName) { @@ -113,7 +133,11 @@ namespace BinaryObjectScanner.Protection else { // Check the header padding for protected sections. +#if NET48 string sectionMatch = CheckSectionForProtection(file, includeDebug, pex.HeaderPaddingStrings, pex.HeaderPaddingData, false); +#else + string? sectionMatch = CheckSectionForProtection(file, includeDebug, pex.HeaderPaddingStrings, pex.HeaderPaddingData, false); +#endif if (!string.IsNullOrWhiteSpace(sectionMatch)) { resultsList.Add(sectionMatch); @@ -128,7 +152,11 @@ namespace BinaryObjectScanner.Protection } // Run Cactus Data Shield PE checks +#if NET48 string match = CactusDataShieldCheckPortableExecutable(file, pex, includeDebug); +#else + string? match = CactusDataShieldCheckPortableExecutable(file, pex, includeDebug); +#endif if (!string.IsNullOrWhiteSpace(match)) resultsList.Add(match); @@ -168,7 +196,7 @@ namespace BinaryObjectScanner.Protection /// public ConcurrentQueue CheckDirectoryPath(string path, IEnumerable files) { - ConcurrentQueue results = new ConcurrentQueue(); + var results = new ConcurrentQueue(); // Run Macrovision directory checks var macrovision = MacrovisionCheckDirectoryPath(path, files); @@ -203,41 +231,69 @@ namespace BinaryObjectScanner.Protection if (results != null && results.Count > 0) return results; - return null; + return new ConcurrentQueue(); } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { List resultsList = new List(); // Run Macrovision file checks +#if NET48 string macrovision = MacrovisionCheckFilePath(path); +#else + string? macrovision = MacrovisionCheckFilePath(path); +#endif if (!string.IsNullOrWhiteSpace(macrovision)) resultsList.Add(macrovision); // Run Cactus Data Shield file checks +#if NET48 string cactusDataShield = CactusDataShieldCheckFilePath(path); +#else + string? cactusDataShield = CactusDataShieldCheckFilePath(path); +#endif if (!string.IsNullOrWhiteSpace(cactusDataShield)) resultsList.Add(cactusDataShield); // Run C-Dilla file checks +#if NET48 string cDilla = CDillaCheckFilePath(path); +#else + string? cDilla = CDillaCheckFilePath(path); +#endif if (!string.IsNullOrWhiteSpace(cDilla)) resultsList.Add(cDilla); // Run RipGuard file checks +#if NET48 string ripGuard = RipGuardCheckFilePath(path); +#else + string? ripGuard = RipGuardCheckFilePath(path); +#endif if (!string.IsNullOrWhiteSpace(ripGuard)) resultsList.Add(ripGuard); // Run SafeCast file checks +#if NET48 string safeCast = SafeCastCheckFilePath(path); +#else + string? safeCast = SafeCastCheckFilePath(path); +#endif if (!string.IsNullOrWhiteSpace(safeCast)) resultsList.Add(safeCast); // Run SafeDisc file checks +#if NET48 string safeDisc = SafeDiscCheckFilePath(path); +#else + string? safeDisc = SafeDiscCheckFilePath(path); +#endif if (!string.IsNullOrWhiteSpace(safeDisc)) resultsList.Add(safeDisc); @@ -260,7 +316,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 internal string MacrovisionCheckFilePath(string path) +#else + internal string? MacrovisionCheckFilePath(string path) +#endif { var matchers = new List { @@ -377,7 +437,11 @@ namespace BinaryObjectScanner.Protection { // Different versions of this driver correspond to different SafeDisc versions. // TODO: Check if earlier versions of this driver contain the version string in a less obvious place. +#if NET48 string version = pex.FileVersion; +#else + string? version = pex.FileVersion; +#endif if (!string.IsNullOrEmpty(version)) { switch (version) @@ -415,33 +479,43 @@ namespace BinaryObjectScanner.Protection return "Unknown Version (Report this to us on GitHub)"; } +#if NET48 private string CheckSectionForProtection(string file, bool includeDebug, List sectionStrings, byte[] sectionRaw, bool newVersion) +#else + private string? CheckSectionForProtection(string file, bool includeDebug, List? sectionStrings, byte[]? sectionRaw, bool newVersion) +#endif { // Get the section strings, if they exist - if (sectionStrings == null) - return null; - - // If we don't have the "BoG_" string, the section isn't protected. - if (!sectionStrings.Any(s => s.Contains("BoG_"))) - return null; - - // If we have the "BoG_" string but not the full "BoG_ *90.0&!! Yy>" string, the section has had the portion of the section that included the version number removed or obfuscated (Redump entry 40337). - if (!sectionStrings.Any(s => s.Contains("BoG_ *90.0&!! Yy>"))) - return newVersion ? "Macrovision Protected Application [Version Expunged]" : null; - - // TODO: Add more checks to help differentiate between SafeDisc and SafeCast. - var matchers = new List + if (sectionStrings != null) { - // BoG_ *90.0&!! Yy> - new ContentMatchSet(new byte?[] - { - 0x42, 0x6F, 0x47, 0x5F, 0x20, 0x2A, 0x39, 0x30, - 0x2E, 0x30, 0x26, 0x21, 0x21, 0x20, 0x20, 0x59, - 0x79, 0x3E - }, GetMacrovisionVersion, string.Empty), - }; + // If we don't have the "BoG_" string, the section isn't protected. + if (!sectionStrings.Any(s => s.Contains("BoG_"))) + return null; - return MatchUtil.GetFirstMatch(file, sectionRaw, matchers, includeDebug); + // If we have the "BoG_" string but not the full "BoG_ *90.0&!! Yy>" string, the section has had the portion of the section that included the version number removed or obfuscated (Redump entry 40337). + if (!sectionStrings.Any(s => s.Contains("BoG_ *90.0&!! Yy>"))) + return newVersion ? "Macrovision Protected Application [Version Expunged]" : null; + } + + // Get the section data, if it exists + if (sectionRaw != null) + { + // TODO: Add more checks to help differentiate between SafeDisc and SafeCast. + var matchers = new List + { + // BoG_ *90.0&!! Yy> + new ContentMatchSet(new byte?[] + { + 0x42, 0x6F, 0x47, 0x5F, 0x20, 0x2A, 0x39, 0x30, + 0x2E, 0x30, 0x26, 0x21, 0x21, 0x20, 0x20, 0x59, + 0x79, 0x3E + }, GetMacrovisionVersion, string.Empty), + }; + + return MatchUtil.GetFirstMatch(file, sectionRaw, matchers, includeDebug); + } + + return null; } internal static string GetMacrovisionVersion(string file, byte[] fileContent, List positions) @@ -573,7 +647,11 @@ namespace BinaryObjectScanner.Protection } } +#if NET48 private List CleanResultList(List resultsList) +#else + private List? CleanResultList(List? resultsList) +#endif { // If we have an invalid result list if (resultsList == null || resultsList.Count == 0) diff --git a/BinaryObjectScanner.Protection/MediaCloQ.cs b/BinaryObjectScanner.Protection/MediaCloQ.cs index 3279adc6..48747661 100644 --- a/BinaryObjectScanner.Protection/MediaCloQ.cs +++ b/BinaryObjectScanner.Protection/MediaCloQ.cs @@ -16,15 +16,19 @@ namespace BinaryObjectScanner.Protection // TODO: "Karaoke Spotlight Series - Pop Hits - Vol. 132" - Sound Choice (SC8732)" is currently undetected, due to there seeming to be no reference to MediaCloQ in the disc's contents. /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Found in scvfy.exe on "Charley Pride - A Tribute to Jim Reeves" (barcode "7 816190222-2 4"). - string name = pex.FileDescription; + var name = pex.FileDescription; if (name?.StartsWith("scvfy MFC Application", StringComparison.OrdinalIgnoreCase) == true) return $"MediaCloQ"; @@ -51,7 +55,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/MediaMaxCD3.cs b/BinaryObjectScanner.Protection/MediaMaxCD3.cs index 73ec7e1f..25bdf3a9 100644 --- a/BinaryObjectScanner.Protection/MediaMaxCD3.cs +++ b/BinaryObjectScanner.Protection/MediaMaxCD3.cs @@ -17,15 +17,19 @@ namespace BinaryObjectScanner.Protection public class MediaMaxCD3 : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Used to detect "LicGen.exe", found on "All That I Am" by Santana (Barcode 8 2876-59773-2 6) - string name = pex.FileDescription; + var name = pex.FileDescription; if (name?.StartsWith("LicGen Module", StringComparison.OrdinalIgnoreCase) == true) return $"MediaMax CD-3"; @@ -36,7 +40,7 @@ namespace BinaryObjectScanner.Protection var cd3CtrlResources = pex.FindGenericResource("Cd3Ctl"); if (cd3CtrlResources.Any()) return $"MediaMax CD-3"; - + var limitedProductionResources = pex.FindDialogBoxByItemTitle("This limited production advanced CD is not playable on your computer. It is solely intended for playback on standard CD players."); if (limitedProductionResources.Any()) return $"MediaMax CD-3"; @@ -45,7 +49,7 @@ namespace BinaryObjectScanner.Protection // "This limited production advanced CD is not playable on your computer. It is solely intended for playback on standard CD players." // Get the .data/DATA section strings, if they exist - List strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); + var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); if (strs != null) { if (strs.Any(s => s.Contains("CD3 Launch Error"))) @@ -90,7 +94,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/NEACProtect.cs b/BinaryObjectScanner.Protection/NEACProtect.cs index 05299f45..1a904f76 100644 --- a/BinaryObjectScanner.Protection/NEACProtect.cs +++ b/BinaryObjectScanner.Protection/NEACProtect.cs @@ -22,11 +22,15 @@ namespace BinaryObjectScanner.Protection public class NEACProtect : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Most of the relevant executables are highly obfuscated, making executable detection mostly impractical. // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -39,7 +43,7 @@ namespace BinaryObjectScanner.Protection if (neac0Section || neac1Section) return "NEAC Protect"; - string name = pex.ProductName; + var name = pex.ProductName; // Found in "NeacSafe64.sys" and "NeacSafe.sys". // TODO: Fix Product Name not being properly grabbed from the file. @@ -69,7 +73,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/OnlineRegistration.cs b/BinaryObjectScanner.Protection/OnlineRegistration.cs index 4d83b26d..6d669f8b 100644 --- a/BinaryObjectScanner.Protection/OnlineRegistration.cs +++ b/BinaryObjectScanner.Protection/OnlineRegistration.cs @@ -7,15 +7,19 @@ namespace BurnOutSharp.ProtectionType public class OnlineRegistration : IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // TODO: Is this too broad in general? - string name = pex.InternalName; + var name = pex.InternalName; if (name?.StartsWith("EReg", StringComparison.OrdinalIgnoreCase) == true) return $"Executable-Based Online Registration {pex.GetInternalVersion()}"; diff --git a/BinaryObjectScanner.Protection/OpenMG.cs b/BinaryObjectScanner.Protection/OpenMG.cs index 24d5454f..39963323 100644 --- a/BinaryObjectScanner.Protection/OpenMG.cs +++ b/BinaryObjectScanner.Protection/OpenMG.cs @@ -17,15 +17,19 @@ namespace BinaryObjectScanner.Protection public class OpenMG : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Found in many different OpenMG related files ("Touch" by Amerie). - string name = pex.LegalTrademarks; + var name = pex.LegalTrademarks; if (name?.StartsWith("OpenMG", StringComparison.OrdinalIgnoreCase) == true) return $"OpenMG"; @@ -91,7 +95,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/Origin.cs b/BinaryObjectScanner.Protection/Origin.cs index 82d716dd..48349ea8 100644 --- a/BinaryObjectScanner.Protection/Origin.cs +++ b/BinaryObjectScanner.Protection/Origin.cs @@ -10,14 +10,18 @@ namespace BinaryObjectScanner.Protection public class Origin : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string name = pex.FileDescription; + var name = pex.FileDescription; if (name?.Equals("Origin", StringComparison.OrdinalIgnoreCase) == true) return "Origin"; @@ -40,7 +44,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/PSXAntiModchip.cs b/BinaryObjectScanner.Protection/PSXAntiModchip.cs index ffac928f..0f89e661 100644 --- a/BinaryObjectScanner.Protection/PSXAntiModchip.cs +++ b/BinaryObjectScanner.Protection/PSXAntiModchip.cs @@ -10,7 +10,11 @@ namespace BinaryObjectScanner.Protection // For now, this means that the CheckContents check is redundant for external // use through other programs /// +#if NET48 public string CheckContents(string file, byte[] fileContent, bool includeDebug) +#else + public string? CheckContents(string file, byte[] fileContent, bool includeDebug) +#endif { // TODO: Detect Red Hand protection var contentMatchSets = new List diff --git a/BinaryObjectScanner.Protection/PlayJ.cs b/BinaryObjectScanner.Protection/PlayJ.cs index 33644c5a..b3b1e365 100644 --- a/BinaryObjectScanner.Protection/PlayJ.cs +++ b/BinaryObjectScanner.Protection/PlayJ.cs @@ -14,23 +14,27 @@ namespace BinaryObjectScanner.Protection public class PlayJ : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Found in "PlayJ.exe" (https://web.archive.org/web/20010417025347/http://dlp.playj.com:80/playj/PlayJIns266.exe) and "CACTUSPJ.exe" ("Volumia!" by Puur (Barcode 7 43218 63282 2) (Discogs Release Code [r795427])). - string name = pex.FileDescription; + var name = pex.FileDescription; if (name?.StartsWith("PlayJ Music Player", StringComparison.OrdinalIgnoreCase) == true) return $"PlayJ Music Player"; - + // Found in "PJSTREAM.DLL" ("Volumia!" by Puur (Barcode 7 43218 63282 2) (Discogs Release Code [r795427])). name = pex.FileDescription; if (name?.StartsWith("EVAUX32 Module", StringComparison.OrdinalIgnoreCase) == true) return $"PlayJ Music Player Component"; - + // Found in "PlayJ.exe" (https://web.archive.org/web/20010417025347/http://dlp.playj.com:80/playj/PlayJIns266.exe) and "CACTUSPJ.exe" ("Volumia!" by Puur (Barcode 7 43218 63282 2) (Discogs Release Code [r795427])). name = pex.ProductName; if (name?.StartsWith("PlayJ", StringComparison.OrdinalIgnoreCase) == true) @@ -57,7 +61,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/ProtectDVDVideo.cs b/BinaryObjectScanner.Protection/ProtectDVDVideo.cs index 7bd4209a..2dd849a1 100644 --- a/BinaryObjectScanner.Protection/ProtectDVDVideo.cs +++ b/BinaryObjectScanner.Protection/ProtectDVDVideo.cs @@ -32,7 +32,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { return null; } diff --git a/BinaryObjectScanner.Protection/ProtectDisc.cs b/BinaryObjectScanner.Protection/ProtectDisc.cs index 9549c850..4997c16d 100644 --- a/BinaryObjectScanner.Protection/ProtectDisc.cs +++ b/BinaryObjectScanner.Protection/ProtectDisc.cs @@ -11,10 +11,14 @@ namespace BinaryObjectScanner.Protection public class ProtectDISC : IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -31,7 +35,7 @@ namespace BinaryObjectScanner.Protection new ContentMatchSet(new byte?[] { 0x41, 0x43, 0x45, 0x2D, 0x50, 0x43, 0x44 }, GetVersion6till8, "ProtectDISC"), }; - string match = MatchUtil.GetFirstMatch(file, nthSectionData, matchers, includeDebug); + var match = MatchUtil.GetFirstMatch(file, nthSectionData, matchers, includeDebug); if (!string.IsNullOrWhiteSpace(match)) return match; } @@ -46,7 +50,7 @@ namespace BinaryObjectScanner.Protection new ContentMatchSet(new byte?[] { 0x44, 0x43, 0x50, 0x2D, 0x42, 0x4F, 0x56, 0x00, 0x00 }, GetVersion3till6, "VOB ProtectCD/DVD"), }; - string match = MatchUtil.GetFirstMatch(file, dataSectionRaw, matchers, includeDebug); + var match = MatchUtil.GetFirstMatch(file, dataSectionRaw, matchers, includeDebug); if (!string.IsNullOrWhiteSpace(match)) return match; } @@ -55,10 +59,14 @@ namespace BinaryObjectScanner.Protection if (sections.Length > 1) { // Get the n - 1 section strings, if they exist - List strs = pex.GetSectionStrings(sections.Length - 2); + var strs = pex.GetSectionStrings(sections.Length - 2); if (strs != null) { +#if NET48 string str = strs.FirstOrDefault(s => s.Contains("VOB ProtectCD")); +#else + string? str = strs.FirstOrDefault(s => s.Contains("VOB ProtectCD")); +#endif if (str != null) return $"VOB ProtectCD {GetOldVersion(str)}"; } @@ -67,7 +75,10 @@ namespace BinaryObjectScanner.Protection // Get the last section (example names: ACE5, akxpxgcv, and piofinqb) if (sections.Length > 0) { - var matchers = new List + var lastSectionData = pex.GetSectionData(sections.Length - 1); + if (lastSectionData != null) + { + var matchers = new List { // HúMETINF new ContentMatchSet(new byte?[] { 0x48, 0xFA, 0x4D, 0x45, 0x54, 0x49, 0x4E, 0x46 }, GetVersion76till10, "ProtectDISC"), @@ -76,9 +87,10 @@ namespace BinaryObjectScanner.Protection new ContentMatchSet(new byte?[] { 0x44, 0x43, 0x50, 0x2D, 0x42, 0x4F, 0x56, 0x00, 0x00 }, GetVersion3till6, "VOB ProtectCD/DVD"), }; - string match = MatchUtil.GetFirstMatch(file, pex.GetSectionData(sections.Length - 1), matchers, includeDebug); - if (!string.IsNullOrWhiteSpace(match)) - return match; + var match = MatchUtil.GetFirstMatch(file, lastSectionData, matchers, includeDebug); + if (!string.IsNullOrWhiteSpace(match)) + return match; + } } // Get the .vob.pcd section, if it exists diff --git a/BinaryObjectScanner.Protection/RainbowSentinel.cs b/BinaryObjectScanner.Protection/RainbowSentinel.cs index 98ea1488..8c146a88 100644 --- a/BinaryObjectScanner.Protection/RainbowSentinel.cs +++ b/BinaryObjectScanner.Protection/RainbowSentinel.cs @@ -24,15 +24,19 @@ namespace BinaryObjectScanner.Protection public class RainbowSentinel : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Get the .data/DATA section strings, if they exist - List strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); + var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); if (strs != null) { // Found in "ADESKSYS.DLL"/"WINADMIN.EXE"/"WINQUERY.EXE" in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]", folder "\netsetup\SUPPORT\IPX". @@ -57,7 +61,7 @@ namespace BinaryObjectScanner.Protection // TODO: Figure out why resources for "RNBOVTMP.DLL", "SENTTEMP.DLL", "SNTI386.DLL", and "SX32W.DL_"/"SX32W.DLL" aren't getting read properly, causing checks for these files to not work. - string name = pex.FileDescription; + var name = pex.FileDescription; // Found in "RNBOVTMP.DLL" in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]". if (name?.Equals("Rainbow Technologies Virtual Device Driver", StringComparison.OrdinalIgnoreCase) == true) @@ -130,7 +134,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/RingPROTECH.cs b/BinaryObjectScanner.Protection/RingPROTECH.cs index 73bd1ba0..03d3f2a7 100644 --- a/BinaryObjectScanner.Protection/RingPROTECH.cs +++ b/BinaryObjectScanner.Protection/RingPROTECH.cs @@ -10,7 +10,11 @@ namespace BinaryObjectScanner.Protection public class RingPROTECH : IContentCheck, IPathCheck { /// +#if NET48 public string CheckContents(string file, byte[] fileContent, bool includeDebug) +#else + public string? CheckContents(string file, byte[] fileContent, bool includeDebug) +#endif { // TODO: Obtain a sample to find where this string is in a typical executable if (includeDebug) @@ -46,7 +50,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/SVKP.cs b/BinaryObjectScanner.Protection/SVKP.cs index 9f754996..6874b36d 100644 --- a/BinaryObjectScanner.Protection/SVKP.cs +++ b/BinaryObjectScanner.Protection/SVKP.cs @@ -24,10 +24,14 @@ namespace BinaryObjectScanner.Protection // TODO: Find 1.4+ samples. /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -106,7 +110,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/SafeLock.cs b/BinaryObjectScanner.Protection/SafeLock.cs index 5ac35ce4..6933bda7 100644 --- a/BinaryObjectScanner.Protection/SafeLock.cs +++ b/BinaryObjectScanner.Protection/SafeLock.cs @@ -36,7 +36,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/SecuROM.cs b/BinaryObjectScanner.Protection/SecuROM.cs index c026c561..4b74acea 100644 --- a/BinaryObjectScanner.Protection/SecuROM.cs +++ b/BinaryObjectScanner.Protection/SecuROM.cs @@ -13,14 +13,18 @@ namespace BinaryObjectScanner.Protection public class SecuROM : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string name = pex.FileDescription; + var name = pex.FileDescription; if (name?.Contains("SecuROM PA") == true) return $"SecuROM Product Activation v{pex.GetInternalVersion()}"; @@ -62,27 +66,30 @@ namespace BinaryObjectScanner.Protection for (int i = 4; i < sections.Length; i++) { var nthSection = sections[i]; - string nthSectionName = Encoding.UTF8.GetString(nthSection.Name).TrimEnd('\0'); - if (nthSection != null && nthSectionName != ".idata" && nthSectionName != ".rsrc") + if (nthSection == null) + continue; + + string nthSectionName = Encoding.UTF8.GetString(nthSection.Name ?? Array.Empty()).TrimEnd('\0'); + if (nthSectionName != ".idata" && nthSectionName != ".rsrc") { var nthSectionData = pex.GetFirstSectionData(nthSectionName); - if (nthSectionData != null) - { - var matchers = new List - { - // (char)0xCA + (char)0xDD + (char)0xDD + (char)0xAC + (char)0x03 - new ContentMatchSet(new byte?[] { 0xCA, 0xDD, 0xDD, 0xAC, 0x03 }, GetV5Version, "SecuROM"), - }; + if (nthSectionData == null) + continue; - string match = MatchUtil.GetFirstMatch(file, nthSectionData, matchers, includeDebug); - if (!string.IsNullOrWhiteSpace(match)) - return match; - } + var matchers = new List + { + // (char)0xCA + (char)0xDD + (char)0xDD + (char)0xAC + (char)0x03 + new ContentMatchSet(new byte?[] { 0xCA, 0xDD, 0xDD, 0xAC, 0x03 }, GetV5Version, "SecuROM"), + }; + + var match = MatchUtil.GetFirstMatch(file, nthSectionData, matchers, includeDebug); + if (!string.IsNullOrWhiteSpace(match)) + return match; } } // Get the .rdata section strings, if they exist - List strs = pex.GetFirstSectionStrings(".rdata"); + var strs = pex.GetFirstSectionStrings(".rdata"); if (strs != null) { // Both have the identifier found within `.rdata` but the version is within `.data` @@ -131,7 +138,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { @@ -156,7 +167,11 @@ namespace BinaryObjectScanner.Protection private static string GetV4Version(PortableExecutable pex) { int index = 8; // Begin reading after "AddD" +#if NET48 char version = (char)pex.OverlayData[index]; +#else + char version = (char)pex.OverlayData![index]; +#endif index += 2; string subVersion = Encoding.ASCII.GetString(pex.OverlayData, index, 2); @@ -229,9 +244,9 @@ namespace BinaryObjectScanner.Protection private static string GetV8WhiteLabelVersion(PortableExecutable pex) { - // Get the .data/DATA section, if it exists + // Get the .data/DATA section, if it exists var dataSectionRaw = pex.GetFirstSectionData(".data") ?? pex.GetFirstSectionData("DATA"); - if (dataSectionRaw != null) + if (dataSectionRaw == null) return "8"; // Search .data for the version indicator diff --git a/BinaryObjectScanner.Protection/SmartE.cs b/BinaryObjectScanner.Protection/SmartE.cs index f15493e0..1f0a4a2b 100644 --- a/BinaryObjectScanner.Protection/SmartE.cs +++ b/BinaryObjectScanner.Protection/SmartE.cs @@ -10,15 +10,19 @@ namespace BinaryObjectScanner.Protection public class SmartE : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Get the last section strings, if they exist - List strs = pex.GetSectionStrings(sections.Length - 1); + var strs = pex.GetSectionStrings(sections.Length - 1); if (strs != null) { if (strs.Any(s => s.Contains("BITARTS"))) @@ -44,7 +48,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/SoftLock.cs b/BinaryObjectScanner.Protection/SoftLock.cs index ec874ac9..79a2a299 100644 --- a/BinaryObjectScanner.Protection/SoftLock.cs +++ b/BinaryObjectScanner.Protection/SoftLock.cs @@ -15,15 +15,19 @@ namespace BinaryObjectScanner.Protection public class SoftLock : IPortableExecutableCheck, IPathCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Found in "IALib.DLL" in IA item "TAFSEERVER4SETUP" - string name = pex.InternalName; + var name = pex.InternalName; if (name?.Equals("Softlock Protected Application") == true) return "SoftLock"; @@ -97,7 +101,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/SolidShield.cs b/BinaryObjectScanner.Protection/SolidShield.cs index a353d6a8..b40422e2 100644 --- a/BinaryObjectScanner.Protection/SolidShield.cs +++ b/BinaryObjectScanner.Protection/SolidShield.cs @@ -13,22 +13,26 @@ namespace BurnOutSharp.ProtectionType public class SolidShield : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // TODO: Investigate ".pseudo" section found in "tvdm.dll" in Redump entry 68166. // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string name = pex.FileDescription; + var name = pex.FileDescription; if (name?.StartsWith("DVM Library", StringComparison.OrdinalIgnoreCase) == true) return $"SolidShield {pex.GetInternalVersion()}"; - + else if (name?.StartsWith("Solidshield Activation Library", StringComparison.OrdinalIgnoreCase) == true) return $"SolidShield Core.dll {pex.GetInternalVersion()}"; - + else if (name?.StartsWith("Activation Manager", StringComparison.OrdinalIgnoreCase) == true) return $"SolidShield Activation Manager Module {GetInternalVersion(pex)}"; @@ -39,10 +43,10 @@ namespace BurnOutSharp.ProtectionType name = pex.ProductName; if (name?.StartsWith("Solidshield Activation Library", StringComparison.OrdinalIgnoreCase) == true) return $"SolidShield Core.dll {pex.GetInternalVersion()}"; - + else if (name?.StartsWith("Solidshield Library", StringComparison.OrdinalIgnoreCase) == true) return $"SolidShield Core.dll {pex.GetInternalVersion()}"; - + else if (name?.StartsWith("Activation Manager", StringComparison.OrdinalIgnoreCase) == true) return $"SolidShield Activation Manager Module {GetInternalVersion(pex)}"; @@ -53,7 +57,10 @@ namespace BurnOutSharp.ProtectionType // Get the .init section, if it exists if (pex.ContainsSection(".init")) { - var matchers = new List + var initData = pex.GetFirstSectionData(".init"); + if (initData != null) + { + var matchers = new List { // (char)0xAD + (char)0xDE + (char)0xFE + (char)0xCA new ContentMatchSet(new byte?[] { 0xAD, 0xDE, 0xFE, 0xCA }, GetVersionPlusTages, "SolidShield"), @@ -62,24 +69,29 @@ namespace BurnOutSharp.ProtectionType new ContentMatchSet(new byte?[] { 0xEF, 0xBE, 0xAD, 0xDE }, GetExeWrapperVersion, "SolidShield EXE Wrapper"), }; - string match = MatchUtil.GetFirstMatch(file, pex.GetFirstSectionData(".init"), matchers, includeDebug); - if (!string.IsNullOrWhiteSpace(match)) - return match; + var match = MatchUtil.GetFirstMatch(file, initData, matchers, includeDebug); + if (!string.IsNullOrWhiteSpace(match)) + return match; + } } // Get the wrapper resource, if it exists var wrapperResources = pex.FindResourceByNamedType("BIN, IDR_SGT"); - if (wrapperResources.Any()) + if (wrapperResources != null && wrapperResources.Any()) return "SolidShield EXE Wrapper v1"; // Search the last two available sections - for (int i = (pex.SectionNames.Length >= 2 ? pex.SectionNames.Length - 2 : 0); i < pex.SectionNames.Length; i++) + for (int i = (pex.SectionNames != null && pex.SectionNames.Length >= 2 ? pex.SectionNames.Length - 2 : 0); i < (pex.SectionNames?.Length ?? 0); i++) { // Get the nth section strings, if they exist - List strs = pex.GetSectionStrings(i); + var strs = pex.GetSectionStrings(i); if (strs != null) { +#if NET48 string str = strs.FirstOrDefault(s => s.Contains("Solidshield ")); +#else + string? str = strs.FirstOrDefault(s => s.Contains("Solidshield ")); +#endif if (str != null) return $"SolidShield EXE Wrapper {str.Substring("Solidshield ".Length)}"; } @@ -88,15 +100,15 @@ namespace BurnOutSharp.ProtectionType // Get the import directory table, if it exists if (pex.Model.ImportTable?.ImportDirectoryTable != null) { - bool match = pex.Model.ImportTable.ImportDirectoryTable.Any(idte => idte.Name == "dvm.dll"); + bool match = pex.Model.ImportTable.ImportDirectoryTable.Any(idte => idte?.Name == "dvm.dll"); if (match) return "SolidShield EXE Wrapper v1"; - match = pex.Model.ImportTable.ImportDirectoryTable.Any(idte => idte.Name == "activation.x86.dll"); + match = pex.Model.ImportTable.ImportDirectoryTable.Any(idte => idte?.Name == "activation.x86.dll"); if (match) return "SolidShield EXE Wrapper v2"; - match = pex.Model.ImportTable.ImportDirectoryTable.Any(idte => idte.Name == "activation.x64.dll"); + match = pex.Model.ImportTable.ImportDirectoryTable.Any(idte => idte?.Name == "activation.x64.dll"); if (match) return "SolidShield EXE Wrapper v2"; } @@ -125,7 +137,11 @@ namespace BurnOutSharp.ProtectionType } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { @@ -149,7 +165,7 @@ namespace BurnOutSharp.ProtectionType else if (id1.SequenceEqual(new byte[] { 0x2E, 0x6F, 0x26 }) && id2.SequenceEqual(new byte[] { 0xDB, 0xC5, 0x20, 0x3A })) // new byte[] { 0xDB, 0xC5, 0x20, 0x3A, 0xB9 } return "v2"; // TODO: Verify against other SolidShield 2 discs - return null; + return string.Empty; } public static string GetVersionPlusTages(string file, byte[] fileContent, List positions) @@ -186,16 +202,20 @@ namespace BurnOutSharp.ProtectionType } } - return null; + return string.Empty; } private static string GetInternalVersion(PortableExecutable pex) { +#if NET48 string companyName = pex.CompanyName?.ToLowerInvariant(); +#else + string? companyName = pex.CompanyName?.ToLowerInvariant(); +#endif if (!string.IsNullOrWhiteSpace(companyName) && (companyName.Contains("solidshield") || companyName.Contains("tages"))) - return pex.GetInternalVersion(); + return pex.GetInternalVersion() ?? string.Empty; - return null; + return string.Empty; } } } diff --git a/BinaryObjectScanner.Protection/StarForce.cs b/BinaryObjectScanner.Protection/StarForce.cs index cc4c8ca7..af383b64 100644 --- a/BinaryObjectScanner.Protection/StarForce.cs +++ b/BinaryObjectScanner.Protection/StarForce.cs @@ -18,14 +18,18 @@ namespace BinaryObjectScanner.Protection // "Replay.exe" not detected, doesn't detect "[FL Disc]" (Redump entry 81756). // Doesn't detect "[Pro]" (Redump entry 91336). /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string name = pex.LegalCopyright; + var name = pex.LegalCopyright; if (name?.StartsWith("(c) Protection Technology") == true) // (c) Protection Technology (StarForce)? return $"StarForce {pex.GetInternalVersion()}"; else if (name?.Contains("Protection Technology") == true) // Protection Technology (StarForce)? @@ -136,7 +140,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { // TODO: Determine if there are any file name checks that aren't too generic to use on their own. return null; diff --git a/BinaryObjectScanner.Protection/Steam.cs b/BinaryObjectScanner.Protection/Steam.cs index 50e3bf0b..c0487157 100644 --- a/BinaryObjectScanner.Protection/Steam.cs +++ b/BinaryObjectScanner.Protection/Steam.cs @@ -9,14 +9,18 @@ namespace BinaryObjectScanner.Protection public class Steam : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string name = pex.FileDescription; + var name = pex.FileDescription; if (!string.IsNullOrEmpty(name) && name.Contains("Steam Autorun Setup")) return "Steam"; else if (!string.IsNullOrEmpty(name) && name.Contains("Steam Client API")) @@ -87,7 +91,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/Sysiphus.cs b/BinaryObjectScanner.Protection/Sysiphus.cs index fd0673ab..83f09780 100644 --- a/BinaryObjectScanner.Protection/Sysiphus.cs +++ b/BinaryObjectScanner.Protection/Sysiphus.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using BinaryObjectScanner.Interfaces; using SabreTools.Serialization.Wrappers; @@ -9,18 +8,26 @@ namespace BinaryObjectScanner.Protection public class Sysiphus : IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Get the .data/DATA section strings, if they exist - List strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); + var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA"); if (strs != null) { +#if NET48 string str = strs.FirstOrDefault(s => s.Contains("V SUHPISYS")); +#else + string? str = strs.FirstOrDefault(s => s.Contains("V SUHPISYS")); +#endif if (str != null) return $"Sysiphus {GetVersion(str)}"; } diff --git a/BinaryObjectScanner.Protection/TZCopyProtection.cs b/BinaryObjectScanner.Protection/TZCopyProtection.cs index 9eee75da..83b50b60 100644 --- a/BinaryObjectScanner.Protection/TZCopyProtection.cs +++ b/BinaryObjectScanner.Protection/TZCopyProtection.cs @@ -70,7 +70,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/Tages.cs b/BinaryObjectScanner.Protection/Tages.cs index 9dde0891..e51574ef 100644 --- a/BinaryObjectScanner.Protection/Tages.cs +++ b/BinaryObjectScanner.Protection/Tages.cs @@ -11,10 +11,14 @@ namespace BurnOutSharp.ProtectionType public class TAGES : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; @@ -28,7 +32,7 @@ namespace BurnOutSharp.ProtectionType // - TagesClient.exe // - TagesClient.dat (Does not always exist) - string name = pex.FileDescription; + var name = pex.FileDescription; if (name?.StartsWith("TagesSetup", StringComparison.OrdinalIgnoreCase) == true) return $"TAGES Driver Setup {GetVersion(pex)}"; else if (name?.StartsWith("Tagès activation client", StringComparison.OrdinalIgnoreCase) == true) @@ -53,7 +57,7 @@ namespace BurnOutSharp.ProtectionType new ContentMatchSet(new byte?[] { 0xE8, 0x75, 0x00, 0x00, 0x00, 0xE8, null, null, 0xFF, 0xFF, 0x68 }, GetVersion, "TAGES"), }; - string match = MatchUtil.GetFirstMatch(file, dataSectionRaw, matchers, includeDebug); + var match = MatchUtil.GetFirstMatch(file, dataSectionRaw, matchers, includeDebug); if (!string.IsNullOrWhiteSpace(match)) return match; } @@ -154,7 +158,11 @@ namespace BurnOutSharp.ProtectionType } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { @@ -213,7 +221,11 @@ namespace BurnOutSharp.ProtectionType private string GetVersion(PortableExecutable pex) { // Check the internal versions +#if NET48 string version = pex.GetInternalVersion(); +#else + string? version = pex.GetInternalVersion(); +#endif if (!string.IsNullOrEmpty(version)) return version; diff --git a/BinaryObjectScanner.Protection/Themida.cs b/BinaryObjectScanner.Protection/Themida.cs index 03ae4146..5f6e08f2 100644 --- a/BinaryObjectScanner.Protection/Themida.cs +++ b/BinaryObjectScanner.Protection/Themida.cs @@ -26,15 +26,23 @@ namespace BinaryObjectScanner.Protection public class Themida : IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Get the "Arcsoft " section strings, if they exist - List strs = pex.GetFirstSectionStrings("Arcsoft "); +#if NET48 + var strs = pex.GetFirstSectionStrings("Arcsoft "); +#else + List? strs = pex.GetFirstSectionStrings("Arcsoft "); +#endif if (strs != null) { // Found in "uDigital Theatre.exe" in http://downloads.fyxm.net/ArcSoft-TotalMedia-23085.html (https://web.archive.org/web/20221114042838/http://files.fyxm.net/23/23085/totalmediatheatre3platinum_retail_tbyb_all.exe). diff --git a/BinaryObjectScanner.Protection/ThreePLock.cs b/BinaryObjectScanner.Protection/ThreePLock.cs index ebcf1840..a41f7861 100644 --- a/BinaryObjectScanner.Protection/ThreePLock.cs +++ b/BinaryObjectScanner.Protection/ThreePLock.cs @@ -11,10 +11,14 @@ namespace BinaryObjectScanner.Protection public class ThreePLock : IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; diff --git a/BinaryObjectScanner.Protection/ThreeTwoOneStudios.cs b/BinaryObjectScanner.Protection/ThreeTwoOneStudios.cs index 9883e94a..092a41b7 100644 --- a/BinaryObjectScanner.Protection/ThreeTwoOneStudios.cs +++ b/BinaryObjectScanner.Protection/ThreeTwoOneStudios.cs @@ -7,10 +7,14 @@ namespace BinaryObjectScanner.Protection public class ThreeTwoOneStudios : IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; diff --git a/BinaryObjectScanner.Protection/TivolaRingProtection.cs b/BinaryObjectScanner.Protection/TivolaRingProtection.cs index 0f944c67..8b99c155 100644 --- a/BinaryObjectScanner.Protection/TivolaRingProtection.cs +++ b/BinaryObjectScanner.Protection/TivolaRingProtection.cs @@ -23,7 +23,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/Uplay.cs b/BinaryObjectScanner.Protection/Uplay.cs index 0317e801..81901b62 100644 --- a/BinaryObjectScanner.Protection/Uplay.cs +++ b/BinaryObjectScanner.Protection/Uplay.cs @@ -10,14 +10,18 @@ namespace BinaryObjectScanner.Protection public class Uplay : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string name = pex.FileDescription; + var name = pex.FileDescription; if (!string.IsNullOrEmpty(name) && name.Contains("Ubisoft Connect Installer")) return "Uplay / Ubisoft Connect"; else if (!string.IsNullOrEmpty(name) && name.Contains("Ubisoft Connect Service")) @@ -63,7 +67,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/WMDS.cs b/BinaryObjectScanner.Protection/WMDS.cs index cb3ba090..14cced7b 100644 --- a/BinaryObjectScanner.Protection/WMDS.cs +++ b/BinaryObjectScanner.Protection/WMDS.cs @@ -17,15 +17,19 @@ namespace BinaryObjectScanner.Protection public class WMDS : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Found on "All That I Am" by Santana (Barcode 8 2876-59773-2 6) - string name = pex.FileDescription; + var name = pex.FileDescription; if (name?.StartsWith("Windows Media Data Session Licensing Engine", StringComparison.OrdinalIgnoreCase) == true) return "Windows Media Data Session DRM"; @@ -60,7 +64,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/WTMCDProtect.cs b/BinaryObjectScanner.Protection/WTMCDProtect.cs index f1bd2a6c..512f38d1 100644 --- a/BinaryObjectScanner.Protection/WTMCDProtect.cs +++ b/BinaryObjectScanner.Protection/WTMCDProtect.cs @@ -10,14 +10,18 @@ namespace BinaryObjectScanner.Protection public class WTMCDProtect : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; - string name = pex.FileDescription; + var name = pex.FileDescription; if (name?.Contains("Copy Protection Viewer") == true) return "WTM Protection Viewer"; @@ -30,7 +34,7 @@ namespace BinaryObjectScanner.Protection return "WTM Protection Viewer"; // Get the code/CODE section strings, if they exist - List strs = pex.GetFirstSectionStrings("code") ?? pex.GetFirstSectionStrings("CODE"); + var strs = pex.GetFirstSectionStrings("code") ?? pex.GetFirstSectionStrings("CODE"); if (strs != null) { if (strs.Any(s => s.Contains("wtmdum.imp"))) @@ -66,7 +70,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { // TODO: Add ImageX.imp as a wildcard, if possible var matchers = new List diff --git a/BinaryObjectScanner.Protection/WinLock.cs b/BinaryObjectScanner.Protection/WinLock.cs index 6a8b044e..e680d0fe 100644 --- a/BinaryObjectScanner.Protection/WinLock.cs +++ b/BinaryObjectScanner.Protection/WinLock.cs @@ -31,7 +31,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/XCP.cs b/BinaryObjectScanner.Protection/XCP.cs index caf477f4..96108d68 100644 --- a/BinaryObjectScanner.Protection/XCP.cs +++ b/BinaryObjectScanner.Protection/XCP.cs @@ -13,15 +13,23 @@ namespace BinaryObjectScanner.Protection public class XCP : IPathCheck, IPortableExecutableCheck { /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // Get the .rdata section strings, if they exist - List strs = pex.GetFirstSectionStrings(".rdata"); +#if NET48 + var strs = pex.GetFirstSectionStrings(".rdata"); +#else + List? strs = pex.GetFirstSectionStrings(".rdata"); +#endif if (strs != null) { if (strs.Any(s => s.Contains("XCP.DAT"))) @@ -49,10 +57,18 @@ namespace BinaryObjectScanner.Protection if (files.Any(f => Path.GetFileName(f).Equals("XCP.DAT", StringComparison.OrdinalIgnoreCase)) || files.Any(f => Path.GetFileName(f).Equals("ECDPlayerControl.ocx", StringComparison.OrdinalIgnoreCase))) { +#if NET48 string versionDatPath = files.FirstOrDefault(f => Path.GetFileName(f).Equals("VERSION.DAT", StringComparison.OrdinalIgnoreCase)); +#else + string? versionDatPath = files.FirstOrDefault(f => Path.GetFileName(f).Equals("VERSION.DAT", StringComparison.OrdinalIgnoreCase)); +#endif if (!string.IsNullOrWhiteSpace(versionDatPath)) { +#if NET48 string xcpVersion = GetDatVersion(versionDatPath); +#else + string? xcpVersion = GetDatVersion(versionDatPath); +#endif if (!string.IsNullOrWhiteSpace(xcpVersion)) protections.Enqueue(xcpVersion); } @@ -66,7 +82,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { if (Path.GetFileName(path).Equals("XCP.DAT", StringComparison.OrdinalIgnoreCase) || Path.GetFileName(path).Equals("ECDPlayerControl.ocx", StringComparison.OrdinalIgnoreCase)) @@ -77,7 +97,11 @@ namespace BinaryObjectScanner.Protection return null; } +#if NET48 private static string GetDatVersion(string path) +#else + private static string? GetDatVersion(string path) +#endif { try { @@ -86,7 +110,7 @@ namespace BinaryObjectScanner.Protection } catch { - return null; + return null; } } } diff --git a/BinaryObjectScanner.Protection/Zzxzz.cs b/BinaryObjectScanner.Protection/Zzxzz.cs index 29e54180..686b3860 100644 --- a/BinaryObjectScanner.Protection/Zzxzz.cs +++ b/BinaryObjectScanner.Protection/Zzxzz.cs @@ -22,7 +22,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Protection/nProtect.cs b/BinaryObjectScanner.Protection/nProtect.cs index c001c7c2..490df752 100644 --- a/BinaryObjectScanner.Protection/nProtect.cs +++ b/BinaryObjectScanner.Protection/nProtect.cs @@ -29,16 +29,20 @@ namespace BinaryObjectScanner.Protection // TODO: Add text check for the string mentioned in https://github.com/mnadareski/BurnOutSharp/issues/154. /// +#if NET48 public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#else + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) +#endif { // Get the sections from the executable, if possible - var sections = pex?.Model.SectionTable; + var sections = pex.Model.SectionTable; if (sections == null) return null; // TODO: Investigate if there are any viable checks for the game EXE itself. - string name = pex.FileDescription; + var name = pex.FileDescription; // Found in "GameGuard.des" in Redump entry 90526 and 99598. if (name?.Contains("nProtect GameGuard Launcher") == true) @@ -97,7 +101,11 @@ namespace BinaryObjectScanner.Protection } /// +#if NET48 public string CheckFilePath(string path) +#else + public string? CheckFilePath(string path) +#endif { var matchers = new List { diff --git a/BinaryObjectScanner.Utilities/BitStream.cs b/BinaryObjectScanner.Utilities/BitStream.cs index 3d78cbd6..651e397e 100644 --- a/BinaryObjectScanner.Utilities/BitStream.cs +++ b/BinaryObjectScanner.Utilities/BitStream.cs @@ -19,7 +19,11 @@ namespace BinaryObjectScanner.Utilities /// /// Bit array representing the current byte in the stream /// +#if NET48 private BitArray _bitBuffer; +#else + private BitArray? _bitBuffer; +#endif /// /// Next bit position to read from in the buffer @@ -49,7 +53,11 @@ namespace BinaryObjectScanner.Utilities /// /// Number of bits to read /// Array representing the read bits, null on error +#if NET48 public BitArray ReadBits(int bitCount) +#else + public BitArray? ReadBits(int bitCount) +#endif { // If we have an invalid bit count if (bitCount <= 0) @@ -60,7 +68,7 @@ namespace BinaryObjectScanner.Utilities RefreshBuffer(); // Create an array to hold the bits - BitArray bits = new BitArray(bitCount); + var bits = new BitArray(bitCount); // Loop through and populate the bits for (int i = 0; i < bitCount; i++) @@ -103,14 +111,18 @@ namespace BinaryObjectScanner.Utilities /// /// Number of bytes to read /// Array representing the read bytes, null on error +#if NET48 public byte[] ReadAlignedBytes(int byteCount) +#else + public byte[]? ReadAlignedBytes(int byteCount) +#endif { // Read back a single byte if (_stream.Position > 0) _stream.Seek(-1, SeekOrigin.Current); // Read the value and refreah the buffer - byte[] value = _stream.ReadBytes(byteCount); + var value = _stream.ReadBytes(byteCount); RefreshBuffer(); return value; } diff --git a/BinaryObjectScanner.Utilities/Extensions.cs b/BinaryObjectScanner.Utilities/Extensions.cs index 1ba210d3..c3672ef3 100644 --- a/BinaryObjectScanner.Utilities/Extensions.cs +++ b/BinaryObjectScanner.Utilities/Extensions.cs @@ -33,7 +33,11 @@ namespace BinaryObjectScanner.Utilities { while (!values.IsEmpty) { +#if NET48 if (!values.TryDequeue(out string value)) +#else + if (!values.TryDequeue(out string? value)) +#endif return; original.Enqueue(value); diff --git a/BinaryObjectScanner.Utilities/Hashing.cs b/BinaryObjectScanner.Utilities/Hashing.cs index 919c1988..7aa19c9d 100644 --- a/BinaryObjectScanner.Utilities/Hashing.cs +++ b/BinaryObjectScanner.Utilities/Hashing.cs @@ -14,14 +14,18 @@ namespace BinaryObjectScanner.Utilities /// /// Path to the file to be hashed /// SHA1 hash as a string on success, null on error +#if NET48 public static string GetFileSHA1(string path) +#else + public static string? GetFileSHA1(string? path) +#endif { if (string.IsNullOrWhiteSpace(path)) return null; try { - SHA1 sha1 = SHA1.Create(); + var sha1 = SHA1.Create(); using (Stream fileStream = File.OpenRead(path)) { byte[] buffer = new byte[32768]; @@ -40,7 +44,11 @@ namespace BinaryObjectScanner.Utilities } } +#if NET48 string hash = BitConverter.ToString(sha1.Hash); +#else + string hash = BitConverter.ToString(sha1.Hash!); +#endif hash = hash.Replace("-", string.Empty); return hash; }