diff --git a/BurnOutSharp/ProtectionType/ImpulseReactor.cs b/BurnOutSharp/ProtectionType/ImpulseReactor.cs index 12718d09..01ca89a5 100644 --- a/BurnOutSharp/ProtectionType/ImpulseReactor.cs +++ b/BurnOutSharp/ProtectionType/ImpulseReactor.cs @@ -1,58 +1,74 @@ using System.Collections.Concurrent; using System.Collections.Generic; +using System.Linq; +using System.Text; +using BurnOutSharp.ExecutableType.Microsoft; using BurnOutSharp.Matching; using BurnOutSharp.Tools; namespace BurnOutSharp.ProtectionType { + // Note that this set of checks also contains "Stardock Product Activation" + // This is intentional, as that protection is highly related to Impulse Reactor public class ImpulseReactor : IContentCheck, IPathCheck { /// - public List GetContentMatchSets() - { - return new List - { - new ContentMatchSet(new List - { - // CVPInitializeClient - new byte?[] - { - 0x43, 0x56, 0x50, 0x49, 0x6E, 0x69, 0x74, 0x69, - 0x61, 0x6C, 0x69, 0x7A, 0x65, 0x43, 0x6C, 0x69, - 0x65, 0x6E, 0x74 - }, + public List GetContentMatchSets() => null; - // A + (char)0x00 + T + (char)0x00 + T + (char)0x00 + L + (char)0x00 + I + (char)0x00 + S + (char)0x00 + T + (char)0x00 + (char)0x00 + (char)0x00 + E + (char)0x00 + L + (char)0x00 + E + (char)0x00 + M + (char)0x00 + E + (char)0x00 + N + (char)0x00 + T + (char)0x00 + (char)0x00 + (char)0x00 + N + (char)0x00 + O + (char)0x00 + T + (char)0x00 + A + (char)0x00 + T + (char)0x00 + I + (char)0x00 + O + (char)0x00 + N + (char)0x00 - new byte?[] - { - 0x41, 0x00, 0x54, 0x00, 0x54, 0x00, 0x4C, 0x00, - 0x49, 0x00, 0x53, 0x00, 0x54, 0x00, 0x00, 0x00, - 0x45, 0x00, 0x4C, 0x00, 0x45, 0x00, 0x4D, 0x00, - 0x45, 0x00, 0x4E, 0x00, 0x54, 0x00, 0x00, 0x00, - 0x4E, 0x00, 0x4F, 0x00, 0x54, 0x00, 0x41, 0x00, - 0x54, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x4E - }, - }, Utilities.GetFileVersion, "Impulse Reactor"), + /// + public string CheckContents(string file, byte[] fileContent, bool includeDebug = false) + { + // Get the sections from the executable, if possible + PortableExecutable pex = PortableExecutable.Deserialize(fileContent, 0); + var sections = pex?.SectionTable; + if (sections == null) + return null; + + // Get the .rdata section, if it exists + var rdataSection = sections.FirstOrDefault(s => Encoding.ASCII.GetString(s.Name).StartsWith(".rdata")); + if (rdataSection != null) + { + int sectionAddr = (int)rdataSection.PointerToRawData; + int sectionEnd = sectionAddr + (int)rdataSection.VirtualSize; // CVPInitializeClient - new ContentMatchSet(new byte?[] + byte?[] check = new byte?[] { 0x43, 0x56, 0x50, 0x49, 0x6E, 0x69, 0x74, 0x69, 0x61, 0x6C, 0x69, 0x7A, 0x65, 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74 - }, "Impulse Reactor"), - }; - } + }; + bool containsCheck = fileContent.FirstPosition(check, out int position, start: sectionAddr, end: sectionEnd); - /// - public string CheckContents(string file, byte[] fileContent, bool includeDebug = false) => null; + // A + (char)0x00 + T + (char)0x00 + T + (char)0x00 + L + (char)0x00 + I + (char)0x00 + S + (char)0x00 + T + (char)0x00 + (char)0x00 + (char)0x00 + E + (char)0x00 + L + (char)0x00 + E + (char)0x00 + M + (char)0x00 + E + (char)0x00 + N + (char)0x00 + T + (char)0x00 + (char)0x00 + (char)0x00 + N + (char)0x00 + O + (char)0x00 + T + (char)0x00 + A + (char)0x00 + T + (char)0x00 + I + (char)0x00 + O + (char)0x00 + N + (char)0x00 + byte?[] check2 = new byte?[] + { + 0x41, 0x00, 0x54, 0x00, 0x54, 0x00, 0x4C, 0x00, + 0x49, 0x00, 0x53, 0x00, 0x54, 0x00, 0x00, 0x00, + 0x45, 0x00, 0x4C, 0x00, 0x45, 0x00, 0x4D, 0x00, + 0x45, 0x00, 0x4E, 0x00, 0x54, 0x00, 0x00, 0x00, + 0x4E, 0x00, 0x4F, 0x00, 0x54, 0x00, 0x41, 0x00, + 0x54, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x4E + }; + bool containsCheck2 = fileContent.FirstPosition(check2, out int position2, start: sectionAddr, end: sectionEnd); + + if (containsCheck && containsCheck2) + return $"Impulse Reactor Core Module {Utilities.GetFileVersion(file, fileContent, new List { position, position2 })}" + (includeDebug ? $" (Index {position}, {position2})" : string.Empty); + else if (containsCheck && !containsCheck2) + return $"Impulse Reactor" + (includeDebug ? $" (Index {position})" : string.Empty); + } + + return null; + } /// public ConcurrentQueue CheckDirectoryPath(string path, IEnumerable files) { + // TODO: Verify if these are AND or OR var matchers = new List { - new PathMatchSet(new PathMatch("ImpulseReactor.dll", useEndsWith: true), Utilities.GetFileVersion, "Impulse Reactor"), + new PathMatchSet(new PathMatch("ImpulseReactor.dll", useEndsWith: true), Utilities.GetFileVersion, "Impulse Reactor Core Module"), + new PathMatchSet(new PathMatch("ReactorActivate.exe", useEndsWith: true), Utilities.GetFileVersion, "Stardock Product Activation"), }; return MatchUtil.GetAllMatches(files, matchers, any: true); @@ -61,9 +77,11 @@ namespace BurnOutSharp.ProtectionType /// public string CheckFilePath(string path) { + // TODO: Verify if these are AND or OR var matchers = new List { - new PathMatchSet(new PathMatch("ImpulseReactor.dll", useEndsWith: true), Utilities.GetFileVersion, "Impulse Reactor"), + new PathMatchSet(new PathMatch("ImpulseReactor.dll", useEndsWith: true), Utilities.GetFileVersion, "Impulse Reactor Core Module"), + new PathMatchSet(new PathMatch("ReactorActivate.exe", useEndsWith: true), Utilities.GetFileVersion, "Stardock Product Activation"), }; return MatchUtil.GetFirstMatch(path, matchers, any: true);