From 4946d4e7ff52a61c4d231a1e32c0dbacfb8e7c0d Mon Sep 17 00:00:00 2001 From: TheRogueArchivist <24215969+TheRogueArchivist@users.noreply.github.com> Date: Mon, 1 Apr 2024 10:14:13 -0600 Subject: [PATCH] Add Roxxe detection (#293) * Add Roxxe detection * Fix Roxxe PR review comments --- BinaryObjectScanner/Protection/Roxxe.cs | 83 +++++++++++++++++++++++++ README.md | 1 + 2 files changed, 84 insertions(+) create mode 100644 BinaryObjectScanner/Protection/Roxxe.cs diff --git a/BinaryObjectScanner/Protection/Roxxe.cs b/BinaryObjectScanner/Protection/Roxxe.cs new file mode 100644 index 00000000..6f957487 --- /dev/null +++ b/BinaryObjectScanner/Protection/Roxxe.cs @@ -0,0 +1,83 @@ +using System; +#if NET40_OR_GREATER || NETCOREAPP +using System.Collections.Concurrent; +#endif +using System.Collections.Generic; +using System.Linq; +using BinaryObjectScanner.Interfaces; +using SabreTools.Matching; +using SabreTools.Serialization.Wrappers; + +namespace BinaryObjectScanner.Protection +{ + /// + /// Roxxe was a Czech DRM. It appears to have been a simple disc check that also relied on unusual disc manufacturing and dummy files to attempt to prevent copying. + /// + /// DRML: https://github.com/TheRogueArchivist/DRML/blob/main/entries/Roxxe/Roxxe.md + /// + public class Roxxe : IPathCheck, IPortableExecutableCheck + { + /// + public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) + { + // Get the sections from the executable, if possible + var sections = pex.Model.SectionTable; + if (sections == null) + return null; + + // Get the code/CODE section strings, if they exist + var strs = pex.GetFirstSectionStrings("code") ?? pex.GetFirstSectionStrings("CODE"); + if (strs != null) + { + // Found in "Owar.exe" in IA item "game4u-22-cd". + if (strs.Any(s => s.Contains("TRCHANGER.INI"))) + return "Roxxe"; + } + + // Get the .rsrc section strings, if they exist + // TODO: Check for these strings specifically within the application-defined resource that they're found in, not just the generic resource section. + strs = pex.GetFirstSectionStrings(".rsrc"); + if (strs != null) + { + // Found in "Owar.exe" in IA items "game4u-22-cd" and "original-war". + // These checks are less reliable, as they are still found in a version of the game that appears to have patched out Roxxe (the version present in IA item "original-war"). + if (strs.Any(s => s.Contains("PRRT01"))) + return "Roxxe (Possibly remnants)"; + + if (strs.Any(s => s.Contains("CommonPRRT"))) + return "Roxxe (Possibly remnants)"; + + if (strs.Any(s => s.Contains("roxe"))) + return "Roxxe (Possibly remnants)"; + } + + return null; + } + + /// +#if NET20 || NET35 + public Queue CheckDirectoryPath(string path, IEnumerable? files) +#else + public ConcurrentQueue CheckDirectoryPath(string path, IEnumerable? files) +#endif + { + var matchers = new List + { + // Files such as "TRCHANGER.INI" may be present, but haven't been found yet. + }; + + return MatchUtil.GetAllMatches(files, matchers, any: true); + } + + /// + public string? CheckFilePath(string path) + { + var matchers = new List + { + // Files such as "TRCHANGER.INI" may be present, but haven't been found yet. + }; + + return MatchUtil.GetFirstMatch(path, matchers, any: true); + } + } +} diff --git a/README.md b/README.md index 45e96864..873b1447 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,7 @@ Below is a list of protections detected by BinaryObjectScanner. The two columns | Rainbow Sentinel | True | True | | | Ring PROTECH / ProRing | True | True | Partially unconfirmed² | | RipGuard | True | True | Partially unconfirmed² | +| Roxxe | True | False | | | SafeDisc / SafeCast | True | True | Can't distinguish between some versions of SafeDisc and SafeCast | | SafeLock | False | True | | | SecuROM | True | True | v8.x and White Label detected partially² |