From da165345b6d0a85d58c3cd1607f32ebd91e4f472 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Mon, 22 Mar 2021 11:13:14 -0700 Subject: [PATCH] Use framework for more content protections --- BurnOutSharp/ProtectionType/ImpulseReactor.cs | 45 ++++-- BurnOutSharp/ProtectionType/JoWooDXProt.cs | 13 +- BurnOutSharp/ProtectionType/LaserLock.cs | 37 +++-- BurnOutSharp/ProtectionType/ProtectDisc.cs | 66 ++++---- BurnOutSharp/ProtectionType/SafeDisc.cs | 134 +++++++-------- BurnOutSharp/ProtectionType/SolidShield.cs | 152 +++++++++++------- BurnOutSharp/ProtectionType/StarForce.cs | 30 ++-- BurnOutSharp/ProtectionType/Tages.cs | 51 +++--- .../ProtectionType/VOBProtectCDDVD.cs | 77 ++++----- 9 files changed, 355 insertions(+), 250 deletions(-) diff --git a/BurnOutSharp/ProtectionType/ImpulseReactor.cs b/BurnOutSharp/ProtectionType/ImpulseReactor.cs index 8d212b66..6d2c3678 100644 --- a/BurnOutSharp/ProtectionType/ImpulseReactor.cs +++ b/BurnOutSharp/ProtectionType/ImpulseReactor.cs @@ -2,28 +2,49 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using BurnOutSharp.Matching; namespace BurnOutSharp.ProtectionType { - // TODO: Figure out how to use GetContentMatches here public class ImpulseReactor : IContentCheck, IPathCheck { /// public string CheckContents(string file, byte[] fileContent, bool includePosition = false) { - // "CVPInitializeClient" - byte?[] check = new byte?[] { 0x43, 0x56, 0x50, 0x49, 0x6E, 0x69, 0x74, 0x69, 0x61, 0x6C, 0x69, 0x7A, 0x65, 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74 }; - if (fileContent.FirstPosition(check, out int position)) + var matchers = new List { - // "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" - 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 }; - if (fileContent.FirstPosition(check2, out int position2)) - return $"Impulse Reactor {Utilities.GetFileVersion(file)}" + (includePosition ? $" (Index {position}, {position2})" : string.Empty); - else - return "Impulse Reactor" + (includePosition ? $" (Index {position})" : string.Empty); - } + new Matcher(new List + { + // CVPInitializeClient + new byte?[] + { + 0x43, 0x56, 0x50, 0x49, 0x6E, 0x69, 0x74, 0x69, + 0x61, 0x6C, 0x69, 0x7A, 0x65, 0x43, 0x6C, 0x69, + 0x65, 0x6E, 0x74 + }, - return 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"), + + // CVPInitializeClient + new Matcher(new byte?[] + { + 0x43, 0x56, 0x50, 0x49, 0x6E, 0x69, 0x74, 0x69, + 0x61, 0x6C, 0x69, 0x7A, 0x65, 0x43, 0x6C, 0x69, + 0x65, 0x6E, 0x74 + }, "Impulse Reactor"), + }; + + return MatchUtil.GetFirstContentMatch(file, fileContent, matchers, includePosition); } /// diff --git a/BurnOutSharp/ProtectionType/JoWooDXProt.cs b/BurnOutSharp/ProtectionType/JoWooDXProt.cs index f6b0faff..3f928713 100644 --- a/BurnOutSharp/ProtectionType/JoWooDXProt.cs +++ b/BurnOutSharp/ProtectionType/JoWooDXProt.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.Linq; +using BurnOutSharp.Matching; namespace BurnOutSharp.ProtectionType { @@ -21,12 +23,13 @@ namespace BurnOutSharp.ProtectionType return $"JoWooD X-Prot v1" + (includePosition ? $" (Index {position})" : string.Empty); } - // "@HC09 " - check = new byte?[] { 0x40, 0x48, 0x43, 0x30, 0x39, 0x20, 0x20, 0x20, 0x20 }; - if (fileContent.FirstPosition(check, out position)) - return $"JoWooD X-Prot v2" + (includePosition ? $" (Index {position})" : string.Empty); + var matchers = new List + { + // @HC09 + new Matcher(new byte?[] { 0x40, 0x48, 0x43, 0x30, 0x39, 0x20, 0x20, 0x20, 0x20 }, "JoWooD X-Prot v2"), + }; - return null; + return MatchUtil.GetFirstContentMatch(file, fileContent, matchers, includePosition); } private static string GetVersion(byte[] fileContent, int position) diff --git a/BurnOutSharp/ProtectionType/LaserLock.cs b/BurnOutSharp/ProtectionType/LaserLock.cs index 8c2c4875..347f7e7b 100644 --- a/BurnOutSharp/ProtectionType/LaserLock.cs +++ b/BurnOutSharp/ProtectionType/LaserLock.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using BurnOutSharp.Matching; namespace BurnOutSharp.ProtectionType { @@ -29,17 +30,35 @@ namespace BurnOutSharp.ProtectionType if (file != null && string.Equals(Path.GetFileName(file), "NOMOUSE.SP", StringComparison.OrdinalIgnoreCase)) return $"LaserLock {GetVersion16Bit(fileContent)}" + (includePosition ? $" (Index 71)" : string.Empty); - // ":\\LASERLOK\\LASERLOK.IN" + (char)0x00 + "C:\\NOMOUSE.SP" - check = new byte?[] { 0x3A, 0x5C, 0x5C, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x5C, 0x5C, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x2E, 0x49, 0x4E, 0x00, 0x43, 0x3A, 0x5C, 0x5C, 0x4E, 0x4F, 0x4D, 0x4F, 0x55, 0x53, 0x45, 0x2E, 0x53, 0x50 }; - if (fileContent.FirstPosition(check, out position)) - return "LaserLock 3" + (includePosition ? $" (Index {position})" : string.Empty); + var matchers = new List + { + // :\\LASERLOK\\LASERLOK.IN + (char)0x00 + C:\\NOMOUSE.SP + new Matcher(new byte?[] + { + 0x3A, 0x5C, 0x5C, 0x4C, 0x41, 0x53, 0x45, 0x52, + 0x4C, 0x4F, 0x4B, 0x5C, 0x5C, 0x4C, 0x41, 0x53, + 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x2E, 0x49, 0x4E, + 0x00, 0x43, 0x3A, 0x5C, 0x5C, 0x4E, 0x4F, 0x4D, + 0x4F, 0x55, 0x53, 0x45, 0x2E, 0x53, 0x50 + }, "LaserLock 3"), - // "LASERLOK_INIT" + (char)0xC + "LASERLOK_RUN" + (char)0xE + "LASERLOK_CHECK" + (char)0xF + "LASERLOK_CHECK2" + (char)0xF + "LASERLOK_CHECK3" - check = new byte?[] { 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x5F, 0x49, 0x4E, 0x49, 0x54, 0x0C, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x5F, 0x52, 0x55, 0x4E, 0x0E, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x5F, 0x43, 0x48, 0x45, 0x43, 0x4B, 0x0F, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x5F, 0x43, 0x48, 0x45, 0x43, 0x4B, 0x32, 0x0F, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x5F, 0x43, 0x48, 0x45, 0x43, 0x4B, 0x33 }; - if (fileContent.FirstPosition(check, out position)) - return "LaserLock 5" + (includePosition ? $" (Index {position})" : string.Empty); + // LASERLOK_INIT + (char)0xC + LASERLOK_RUN + (char)0xE + LASERLOK_CHECK + (char)0xF + LASERLOK_CHECK2 + (char)0xF + LASERLOK_CHECK3 + new Matcher(new byte?[] + { + 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, + 0x5F, 0x49, 0x4E, 0x49, 0x54, 0x0C, 0x4C, 0x41, + 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x5F, 0x52, + 0x55, 0x4E, 0x0E, 0x4C, 0x41, 0x53, 0x45, 0x52, + 0x4C, 0x4F, 0x4B, 0x5F, 0x43, 0x48, 0x45, 0x43, + 0x4B, 0x0F, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, + 0x4F, 0x4B, 0x5F, 0x43, 0x48, 0x45, 0x43, 0x4B, + 0x32, 0x0F, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, + 0x4F, 0x4B, 0x5F, 0x43, 0x48, 0x45, 0x43, 0x4B, + 0x33 + }, "LaserLock 5"), + }; - return null; + return MatchUtil.GetFirstContentMatch(file, fileContent, matchers, includePosition); } /// diff --git a/BurnOutSharp/ProtectionType/ProtectDisc.cs b/BurnOutSharp/ProtectionType/ProtectDisc.cs index 247ff56e..354deb37 100644 --- a/BurnOutSharp/ProtectionType/ProtectDisc.cs +++ b/BurnOutSharp/ProtectionType/ProtectDisc.cs @@ -1,49 +1,57 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading; +using BurnOutSharp.Matching; namespace BurnOutSharp.ProtectionType { - // TODO: Figure out how to use GetContentMatches here public class ProtectDisc : IContentCheck { /// public string CheckContents(string file, byte[] fileContent, bool includePosition = false) { - // "HúMETINF" - byte?[] check = new byte?[] { 0x48, 0xFA, 0x4D, 0x45, 0x54, 0x49, 0x4E, 0x46 }; - if (fileContent.FirstPosition(check, out int position)) + var matchers = new List { - string version = SearchProtectDiscVersion(file, fileContent); - if (version.Length > 0) - { - string[] astrVersionArray = version.Split('.'); - if (astrVersionArray[0] == "9") - { - if (GetVersionBuild76till10(fileContent, position, out int ibuild).Length > 0) - return $"ProtectDisc {astrVersionArray[0]}.{astrVersionArray[1]}{astrVersionArray[2]}.{astrVersionArray[3]} (Build {ibuild})" + (includePosition ? $" (Index {position})" : string.Empty); - } - else - { - return $"ProtectDisc {astrVersionArray[0]}.{astrVersionArray[1]}.{astrVersionArray[2]} (Build {astrVersionArray[3]})" + (includePosition ? $" (Index {position})" : string.Empty); - } - } + // HúMETINF + new Matcher(new byte?[] { 0x48, 0xFA, 0x4D, 0x45, 0x54, 0x49, 0x4E, 0x46 }, GetVersion76till10, "ProtectDisc"), + + // ACE-PCD + new Matcher(new byte?[] { 0x41, 0x43, 0x45, 0x2D, 0x50, 0x43, 0x44 }, GetVersion6till8, "ProtectDisc"), + }; + + return MatchUtil.GetFirstContentMatch(file, fileContent, matchers, includePosition); + } + + public static string GetVersion6till8(string file, byte[] fileContent, int position) + { + string version = SearchProtectDiscVersion(file, fileContent); + if (version.Length > 0) + { + string[] astrVersionArray = version.Split('.'); + return $"{astrVersionArray[0]}.{astrVersionArray[1]}.{astrVersionArray[2]} (Build {astrVersionArray[3]})"; } - // "ACE-PCD" - check = new byte?[] { 0x41, 0x43, 0x45, 0x2D, 0x50, 0x43, 0x44 }; - if (fileContent.FirstPosition(check, out position)) - { - string version = SearchProtectDiscVersion(file, fileContent); - if (version.Length > 0) - { - string[] astrVersionArray = version.Split('.'); - return $"ProtectDisc {astrVersionArray[0]}.{astrVersionArray[1]}.{astrVersionArray[2]} (Build {astrVersionArray[3]})" + (includePosition ? $" (Index {position})" : string.Empty); - } + return $"{GetVersionBuild6till8(fileContent, position)}"; + } - return $"ProtectDisc {GetVersionBuild6till8(fileContent, position)}" + (includePosition ? $" (Index {position})" : string.Empty); + public static string GetVersion76till10(string file, byte[] fileContent, int position) + { + string version = SearchProtectDiscVersion(file, fileContent); + if (version.Length > 0) + { + string[] astrVersionArray = version.Split('.'); + if (astrVersionArray[0] == "9") + { + if (GetVersionBuild76till10(fileContent, position, out int ibuild).Length > 0) + return $"{astrVersionArray[0]}.{astrVersionArray[1]}{astrVersionArray[2]}.{astrVersionArray[3]} (Build {ibuild})"; + } + else + { + return $"{astrVersionArray[0]}.{astrVersionArray[1]}.{astrVersionArray[2]} (Build {astrVersionArray[3]})"; + } } return null; diff --git a/BurnOutSharp/ProtectionType/SafeDisc.cs b/BurnOutSharp/ProtectionType/SafeDisc.cs index 32e66c6f..4abb37cd 100644 --- a/BurnOutSharp/ProtectionType/SafeDisc.cs +++ b/BurnOutSharp/ProtectionType/SafeDisc.cs @@ -4,61 +4,56 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Text; +using BurnOutSharp.Matching; namespace BurnOutSharp.ProtectionType { - // TODO: Figure out how to use GetContentMatches here public class SafeDisc : IContentCheck, IPathCheck { /// public string CheckContents(string file, byte[] fileContent, bool includePosition = false) { - // "BoG_ *90.0&!! Yy>" - byte?[] check = new byte?[] { 0x42, 0x6F, 0x47, 0x5F, 0x20, 0x2A, 0x39, 0x30, 0x2E, 0x30, 0x26, 0x21, 0x21, 0x20, 0x20, 0x59, 0x79, 0x3E }; - if (fileContent.FirstPosition(check, out int position)) + var matchers = new List { - // "product activation library" - byte?[] check2 = new byte?[] { 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x6C, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79 }; - if (fileContent.FirstPosition(check2, out int position2)) - return $"SafeCast {GetVersion(fileContent, position)}" + (includePosition ? $" (Index {position}, {position2})" : string.Empty); - else - return $"SafeDisc {GetVersion(fileContent, position)}" + (includePosition ? $" (Index {position})" : string.Empty); - } + new Matcher(new List + { + // BoG_ *90.0&!! Yy> + new byte?[] + { + 0x42, 0x6F, 0x47, 0x5F, 0x20, 0x2A, 0x39, 0x30, + 0x2E, 0x30, 0x26, 0x21, 0x21, 0x20, 0x20, 0x59, + 0x79, 0x3E + }, - // (char)0x00 + (char)0x00 + "BoG_" - check = new byte?[] { 0x00, 0x00, 0x42, 0x6F, 0x47, 0x5F }; - if (fileContent.FirstPosition(check, out position)) - { - string version = SearchSafeDiscVersion(file, fileContent); - if (version.Length > 0) - return $"SafeDisc {version}" + (includePosition ? $" (Index {position})" : string.Empty); + // product activation library + new byte?[] + { + 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x20, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x20, 0x6C, 0x69, 0x62, 0x72, 0x61, + 0x72, 0x79 + }, + }, GetVersion, "SafeCast"), - return "SafeDisc 3.20-4.xx (version removed)" + (includePosition ? $" (Index {position})" : string.Empty); - } + // BoG_ *90.0&!! Yy> + new Matcher(new byte?[] + { + 0x42, 0x6F, 0x47, 0x5F, 0x20, 0x2A, 0x39, 0x30, + 0x2E, 0x30, 0x26, 0x21, 0x21, 0x20, 0x20, 0x59, + 0x79, 0x3E + }, "SafeDisc"), - // "stxt774" - check = new byte?[] { 0x73, 0x74, 0x78, 0x74, 0x37, 0x37, 0x34 }; - if (fileContent.FirstPosition(check, out position)) - { - string version = SearchSafeDiscVersion(file, fileContent); - if (version.Length > 0) - return $"SafeDisc {version}" + (includePosition ? $" (Index {position})" : string.Empty); + // (char)0x00 + (char)0x00 + BoG_ + new Matcher(new byte?[] { 0x00, 0x00, 0x42, 0x6F, 0x47, 0x5F }, Get320to4xVersion, "SafeDisc"), - return "SafeDisc 3.20-4.xx (version removed)" + (includePosition ? $" (Index {position})" : string.Empty); - } + // stxt774 + new Matcher(new byte?[] { 0x73, 0x74, 0x78, 0x74, 0x37, 0x37, 0x34 }, Get320to4xVersion, "SafeDisc"), - // "stxt371" - check = new byte?[] { 0x73, 0x74, 0x78, 0x74, 0x33, 0x37, 0x31 }; - if (fileContent.FirstPosition(check, out position)) - { - string version = SearchSafeDiscVersion(file, fileContent); - if (version.Length > 0) - return $"SafeDisc {version}" + (includePosition ? $" (Index {position})" : string.Empty); + // stxt371 + new Matcher(new byte?[] { 0x73, 0x74, 0x78, 0x74, 0x33, 0x37, 0x31 }, Get320to4xVersion, "SafeDisc"), + }; - return "SafeDisc 3.20-4.xx (version removed)" + (includePosition ? $" (Index {position})" : string.Empty); - } - - return null; + return MatchUtil.GetFirstContentMatch(file, fileContent, matchers, includePosition); } /// @@ -136,6 +131,40 @@ namespace BurnOutSharp.ProtectionType return null; } + public static string GetVersion(string file, byte[] fileContent, int position) + { + int index = position + 20; // Begin reading after "BoG_ *90.0&!! Yy>" for old SafeDisc + int version = BitConverter.ToInt32(fileContent, index); + index += 4; + int subVersion = BitConverter.ToInt32(fileContent, index); + index += 4; + int subsubVersion = BitConverter.ToInt32(fileContent, index); + + if (version != 0) + return $"{version}.{subVersion:00}.{subsubVersion:000}"; + + index = position + 18 + 14; // Begin reading after "BoG_ *90.0&!! Yy>" for newer SafeDisc + version = BitConverter.ToInt32(fileContent, index); + index += 4; + subVersion = BitConverter.ToInt32(fileContent, index); + index += 4; + subsubVersion = BitConverter.ToInt32(fileContent, index); + + if (version == 0) + return ""; + + return $"{version}.{subVersion:00}.{subsubVersion:000}"; + } + + public static string Get320to4xVersion(string file, byte[] fileContent, int position) + { + string version = SearchSafeDiscVersion(file, fileContent); + if (version.Length > 0) + return version; + + return "3.20-4.xx (version removed)"; + } + private static string GetDPlayerXVersion(string file) { if (file == null || !File.Exists(file)) @@ -226,31 +255,6 @@ namespace BurnOutSharp.ProtectionType return "SafeDisc 1 or greater"; } - private static string GetVersion(byte[] fileContent, int position) - { - int index = position + 20; // Begin reading after "BoG_ *90.0&!! Yy>" for old SafeDisc - int version = BitConverter.ToInt32(fileContent, index); - index += 4; - int subVersion = BitConverter.ToInt32(fileContent, index); - index += 4; - int subsubVersion = BitConverter.ToInt32(fileContent, index); - - if (version != 0) - return $"{version}.{subVersion:00}.{subsubVersion:000}"; - - index = position + 18 + 14; // Begin reading after "BoG_ *90.0&!! Yy>" for newer SafeDisc - version = BitConverter.ToInt32(fileContent, index); - index += 4; - subVersion = BitConverter.ToInt32(fileContent, index); - index += 4; - subsubVersion = BitConverter.ToInt32(fileContent, index); - - if (version == 0) - return ""; - - return $"{version}.{subVersion:00}.{subsubVersion:000}"; - } - // TODO: Analyze this method and figure out if this can be done without attempting execution private static string SearchSafeDiscVersion(string file, byte[] fileContent) { diff --git a/BurnOutSharp/ProtectionType/SolidShield.cs b/BurnOutSharp/ProtectionType/SolidShield.cs index 94829c23..2578a9ef 100644 --- a/BurnOutSharp/ProtectionType/SolidShield.cs +++ b/BurnOutSharp/ProtectionType/SolidShield.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; +using BurnOutSharp.Matching; namespace BurnOutSharp.ProtectionType { @@ -12,68 +13,80 @@ namespace BurnOutSharp.ProtectionType /// public string CheckContents(string file, byte[] fileContent, bool includePosition = false) { - // "D" + (char)0x00 + "V" + (char)0x00 + "M" + (char)0x00 + " " + (char)0x00 + "L" + (char)0x00 + "i" + (char)0x00 + "b" + (char)0x00 + "r" + (char)0x00 + "a" + (char)0x00 + "r" + (char)0x00 + "y" - byte?[] check = new byte?[] { 0x44, 0x00, 0x56, 0x00, 0x4D, 0x00, 0x20, 0x00, 0x4C, 0x00, 0x69, 0x00, 0x62, 0x00, 0x72, 0x00, 0x61, 0x00, 0x72, 0x00, 0x79 }; - if (fileContent.FirstPosition(check, out int position)) - return $"SolidShield {Utilities.GetFileVersion(file)}" + (includePosition ? $" (Index {position})" : string.Empty); - - // "S" + (char)0x00 + "o" + (char)0x00 + "l" + (char)0x00 + "i" + (char)0x00 + "d" + (char)0x00 + "s" + (char)0x00 + "h" + (char)0x00 + "i" + (char)0x00 + "e" + (char)0x00 + "l" + (char)0x00 + "d" + (char)0x00 + " " + (char)0x00 + "L" + (char)0x00 + "i" + (char)0x00 + "b" + (char)0x00 + "r" + (char)0x00 + "a" + (char)0x00 + "r" + (char)0x00 + "y" - check = new byte?[] { 0x53, 0x00, 0x6F, 0x00, 0x6C, 0x00, 0x69, 0x00, 0x64, 0x00, 0x73, 0x00, 0x68, 0x00, 0x69, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x64, 0x00, 0x20, 0x00, 0x4C, 0x00, 0x69, 0x00, 0x62, 0x00, 0x72, 0x00, 0x61, 0x00, 0x72, 0x00, 0x79 }; - if (fileContent.FirstPosition(check, out position)) + var matchers = new List { - string companyName = string.Empty; - if (file != null) - companyName = FileVersionInfo.GetVersionInfo(file).CompanyName.ToLower(); + // D + (char)0x00 + V + (char)0x00 + M + (char)0x00 + + (char)0x00 + L + (char)0x00 + i + (char)0x00 + b + (char)0x00 + r + (char)0x00 + a + (char)0x00 + r + (char)0x00 + y + (char)0x00 + new Matcher(new byte?[] + { + 0x44, 0x00, 0x56, 0x00, 0x4D, 0x00, 0x20, 0x00, + 0x4C, 0x00, 0x69, 0x00, 0x62, 0x00, 0x72, 0x00, + 0x61, 0x00, 0x72, 0x00, 0x79, 0x00 + }, Utilities.GetFileVersion, "SolidShield"), - if (companyName.Contains("solidshield") || companyName.Contains("tages")) - return $"SolidShield Core.dll {Utilities.GetFileVersion(file)}" + (includePosition ? $" (Index {position})" : string.Empty); - } + // S + (char)0x00 + o + (char)0x00 + l + (char)0x00 + i + (char)0x00 + d + (char)0x00 + s + (char)0x00 + h + (char)0x00 + i + (char)0x00 + e + (char)0x00 + l + (char)0x00 + d + (char)0x00 + + (char)0x00 + L + (char)0x00 + i + (char)0x00 + b + (char)0x00 + r + (char)0x00 + a + (char)0x00 + r + (char)0x00 + y + (char)0x00 + new Matcher(new byte?[] + { + 0x53, 0x00, 0x6F, 0x00, 0x6C, 0x00, 0x69, 0x00, + 0x64, 0x00, 0x73, 0x00, 0x68, 0x00, 0x69, 0x00, + 0x65, 0x00, 0x6C, 0x00, 0x64, 0x00, 0x20, 0x00, + 0x4C, 0x00, 0x69, 0x00, 0x62, 0x00, 0x72, 0x00, + 0x61, 0x00, 0x72, 0x00, 0x79, 0x00 + }, GetFileVersion, "SolidShield Core.dll"), - // "S" + (char)0x00 + "o" + (char)0x00 + "l" + (char)0x00 + "i" + (char)0x00 + "d" + (char)0x00 + "s" + (char)0x00 + "h" + (char)0x00 + "i" + (char)0x00 + "e" + (char)0x00 + "l" + (char)0x00 + "d" + (char)0x00 + " " + (char)0x00 + "A" + (char)0x00 + "c" + (char)0x00 + "t" + (char)0x00 + "i" + (char)0x00 + "v" + (char)0x00 + "a" + (char)0x00 + "t" + (char)0x00 + "i" + (char)0x00 + "o" + (char)0x00 + "n" + (char)0x00 + " " + (char)0x00 + "L" + (char)0x00 + "i" + (char)0x00 + "b" + (char)0x00 + "r" + (char)0x00 + "a" + (char)0x00 + "r" + (char)0x00 + "y" - check = new byte?[] { 0x53, 0x00, 0x6F, 0x00, 0x6C, 0x00, 0x69, 0x00, 0x64, 0x00, 0x73, 0x00, 0x68, 0x00, 0x69, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x64, 0x00, 0x20, 0x00, 0x41, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x76, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x20, 0x00, 0x4C, 0x00, 0x69, 0x00, 0x62, 0x00, 0x72, 0x00, 0x61, 0x00, 0x72, 0x00, 0x79 }; - if (fileContent.FirstPosition(check, out position)) - { - string companyName = string.Empty; - if (file != null) - companyName = FileVersionInfo.GetVersionInfo(file).CompanyName.ToLower(); + // S + (char)0x00 + o + (char)0x00 + l + (char)0x00 + i + (char)0x00 + d + (char)0x00 + s + (char)0x00 + h + (char)0x00 + i + (char)0x00 + e + (char)0x00 + l + (char)0x00 + d + (char)0x00 + + (char)0x00 + A + (char)0x00 + c + (char)0x00 + t + (char)0x00 + i + (char)0x00 + v + (char)0x00 + a + (char)0x00 + t + (char)0x00 + i + (char)0x00 + o + (char)0x00 + n + (char)0x00 + + (char)0x00 + L + (char)0x00 + i + (char)0x00 + b + (char)0x00 + r + (char)0x00 + a + (char)0x00 + r + (char)0x00 + y + (char)0x00 + new Matcher(new byte?[] + { + 0x53, 0x00, 0x6F, 0x00, 0x6C, 0x00, 0x69, 0x00, + 0x64, 0x00, 0x73, 0x00, 0x68, 0x00, 0x69, 0x00, + 0x65, 0x00, 0x6C, 0x00, 0x64, 0x00, 0x20, 0x00, + 0x41, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, + 0x76, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, + 0x6F, 0x00, 0x6E, 0x00, 0x20, 0x00, 0x4C, 0x00, + 0x69, 0x00, 0x62, 0x00, 0x72, 0x00, 0x61, 0x00, + 0x72, 0x00, 0x79, 0x00 + }, GetFileVersion, "SolidShield Core.dll"), - if (companyName.Contains("solidshield") || companyName.Contains("tages")) - return $"SolidShield Core.dll {Utilities.GetFileVersion(file)}" + (includePosition ? $" (Index {position})" : string.Empty); - } + // (char)0xEF + (char)0xBE + (char)0xAD + (char)0xDE + new Matcher(new byte?[] { 0xEF, 0xBE, 0xAD, 0xDE }, GetExeWrapperVersion, "SolidShield"), - // (char)0xEF + (char)0xBE + (char)0xAD + (char)0xDE - check = new byte?[] { }; - if (fileContent.FirstPosition(check, out position)) - { - var id1 = new ArraySegment(fileContent, position + 5, 3); - var id2 = new ArraySegment(fileContent, position + 16, 4); + // A + (char)0x00 + c + (char)0x00 + t + (char)0x00 + i + (char)0x00 + v + (char)0x00 + a + (char)0x00 + t + (char)0x00 + i + (char)0x00 + o + (char)0x00 + n + (char)0x00 + + (char)0x00 + M + (char)0x00 + a + (char)0x00 + n + (char)0x00 + a + (char)0x00 + g + (char)0x00 + e + (char)0x00 + r + (char)0x00 + new Matcher(new byte?[] + { + 0x41, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, + 0x76, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, + 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x4d, 0x00, + 0x61, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x67, 0x00, + 0x65, 0x00, 0x72, 0x00 + }, GetFileVersion, "SolidShield Activation Manager Module"), - if (id1.SequenceEqual(new byte[] { 0x00, 0x00, 0x00 }) && id2.SequenceEqual(new byte[] { 0x00, 0x10, 0x00, 0x00 })) - return "SolidShield 1 (SolidShield EXE Wrapper)" + (includePosition ? $" (Index {position})" : string.Empty); - else if (id1.SequenceEqual(new byte[] { 0x2E, 0x6F, 0x26 }) && id2.SequenceEqual(new byte[] { 0xDB, 0xC5, 0x20, 0x3A, 0xB9 })) - return "SolidShield 2 (SolidShield v2 EXE Wrapper)" + (includePosition ? $" (Index {position})" : string.Empty); // TODO: Verify against other SolidShield 2 discs - } + // dvm.dll + new Matcher(new byte?[] { 0x64, 0x76, 0x6D, 0x2E, 0x64, 0x6C, 0x6C }, "SolidShield EXE Wrapper"), - // "A" + (char)0x00 + "c" + (char)0x00 + "t" + (char)0x00 + "i" + (char)0x00 + "v" + (char)0x00 + "a" + (char)0x00 + "t" + (char)0x00 + "i" + (char)0x00 + "o" + (char)0x00 + "n" + (char)0x00 + " " + (char)0x00 + "M" + (char)0x00 + "a" + (char)0x00 + "n" + (char)0x00 + "a" + (char)0x00 + "g" + (char)0x00 + "e" + (char)0x00 + "r" - check = new byte?[] { 0x41, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x76, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x4d, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72 }; - if (fileContent.FirstPosition(check, out position)) - { - string companyName = string.Empty; - if (file != null) - companyName = FileVersionInfo.GetVersionInfo(file).CompanyName.ToLower(); + // Placeholder for the complex SolidShield + TAGES check - if (companyName.Contains("solidshield") || companyName.Contains("tages")) - return $"SolidShield Activation Manager Module {Utilities.GetFileVersion(file)}" + (includePosition ? $" (Index {position})" : string.Empty); - } + // Solidshield + new Matcher(new byte?[] + { + 0x53, 0x6F, 0x6C, 0x69, 0x64, 0x73, 0x68, 0x69, + 0x65, 0x6C, 0x64 + }, GetVersion, "SolidShield"), - // dvm.dll - check = new byte?[] { 0x64, 0x76, 0x6D, 0x2E, 0x64, 0x6C, 0x6C }; - if (fileContent.FirstPosition(check, out position)) - return $"SolidShield EXE Wrapper" + (includePosition ? $" (Index {position})" : string.Empty); + // B + (char)0x00 + I + (char)0x00 + N + (char)0x00 + (char)0x7 + (char)0x00 + I + (char)0x00 + D + (char)0x00 + R + (char)0x00 + _ + (char)0x00 + S + (char)0x00 + G + (char)0x00 + T + (char)0x00 + new Matcher(new byte?[] + { + 0x42, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x07, 0x00, + 0x49, 0x00, 0x44, 0x00, 0x52, 0x00, 0x5F, 0x00, + 0x53, 0x00, 0x47, 0x00, 0x54, 0x00 + }, "SolidShield"), + }; + + string firstMatch = MatchUtil.GetFirstContentMatch(file, fileContent, matchers, includePosition); + if (firstMatch != null) + return firstMatch; // (char)0xAD + (char)0xDE + (char)0xFE + (char)0xCA - check = new byte?[] { 0xAD, 0xDE, 0xFE, 0xCA }; - if (fileContent.FirstPosition(check, out position)) + byte?[] check = new byte?[] { 0xAD, 0xDE, 0xFE, 0xCA }; + if (fileContent.FirstPosition(check, out int position)) { var id1 = new ArraySegment(fileContent, position + 4, 3); var id2 = new ArraySegment(fileContent, position + 15, 4); @@ -101,16 +114,6 @@ namespace BurnOutSharp.ProtectionType } } - // "Solidshield" - check = new byte?[] { 0x53, 0x6F, 0x6C, 0x69, 0x64, 0x73, 0x68, 0x69, 0x65, 0x6C, 0x64 }; - if (fileContent.FirstPosition(check, out position)) - return $"SolidShield {GetVersion(fileContent, position)}" + (includePosition ? $" (Index {position})" : string.Empty); - - // "B" + (char)0x00 + "I" + (char)0x00 + "N" + (char)0x00 + (char)0x7 + (char)0x00 + "I" + (char)0x00 + "D" + (char)0x00 + "R" + (char)0x00 + "_" + (char)0x00 + "S" + (char)0x00 + "G" + (char)0x00 + "T" + (char)0x0 - check = new byte?[] { 0x42, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x07, 0x00, 0x49, 0x00, 0x44, 0x00, 0x52, 0x00, 0x5F, 0x00, 0x53, 0x00, 0x47, 0x00, 0x54, 0x00 }; - if (fileContent.FirstPosition(check, out position)) - return "SolidShield" + (includePosition ? $" (Index {position})" : string.Empty); - return null; } @@ -143,7 +146,32 @@ namespace BurnOutSharp.ProtectionType return null; } - private static string GetVersion(byte[] fileContent, int position) + public static string GetExeWrapperVersion(string file, byte[] fileContent, int position) + { + var id1 = new ArraySegment(fileContent, position + 5, 3); + var id2 = new ArraySegment(fileContent, position + 16, 4); + + if (id1.SequenceEqual(new byte[] { 0x00, 0x00, 0x00 }) && id2.SequenceEqual(new byte[] { 0x00, 0x10, 0x00, 0x00 })) + return "1 (SolidShield EXE Wrapper)"; + else if (id1.SequenceEqual(new byte[] { 0x2E, 0x6F, 0x26 }) && id2.SequenceEqual(new byte[] { 0xDB, 0xC5, 0x20, 0x3A, 0xB9 })) + return "2 (SolidShield v2 EXE Wrapper)"; // TODO: Verify against other SolidShield 2 discs + + return null; + } + + public static string GetFileVersion(string file, byte[] fileContent, int position) + { + string companyName = string.Empty; + if (file != null) + companyName = FileVersionInfo.GetVersionInfo(file).CompanyName.ToLower(); + + if (companyName.Contains("solidshield") || companyName.Contains("tages")) + return Utilities.GetFileVersion(file); + + return null; + } + + public static string GetVersion(string file, byte[] fileContent, int position) { int index = position + 12; // Begin reading after "Solidshield" char version = (char)fileContent[index]; diff --git a/BurnOutSharp/ProtectionType/StarForce.cs b/BurnOutSharp/ProtectionType/StarForce.cs index 54f6f684..b1852b68 100644 --- a/BurnOutSharp/ProtectionType/StarForce.cs +++ b/BurnOutSharp/ProtectionType/StarForce.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using BurnOutSharp.Matching; namespace BurnOutSharp.ProtectionType { @@ -47,22 +48,25 @@ namespace BurnOutSharp.ProtectionType return $"StarForce {Utilities.GetFileVersion(file)}" + (includePosition ? $" (Index {position}, {position2})" : string.Empty); } - // ".sforce" - check = new byte?[] { 0x2E, 0x73, 0x66, 0x6F, 0x72, 0x63, 0x65 }; - if (fileContent.FirstPosition(check, out position)) - return "StarForce 3-5" + (includePosition ? $" (Index {position})" : string.Empty); + var matchers = new List + { + // .sforce + new Matcher(new byte?[] { 0x2E, 0x73, 0x66, 0x6F, 0x72, 0x63, 0x65 }, "StarForce 3-5"), - // ".brick" - check = new byte?[] { 0x2E, 0x62, 0x72, 0x69, 0x63, 0x6B }; - if (fileContent.FirstPosition(check, out position)) - return "StarForce 3-5" + (includePosition ? $" (Index {position})" : string.Empty); + // .brick + new Matcher(new byte?[] { 0x2E, 0x62, 0x72, 0x69, 0x63, 0x6B }, "StarForce 3-5"), - // "P" + (char)0x00 + "r" + (char)0x00 + "o" + (char)0x00 + "t" + (char)0x00 + "e" + (char)0x00 + "c" + (char)0x00 + "t" + (char)0x00 + "e" + (char)0x00 + "d" + (char)0x00 + " " + (char)0x00 + "M" + (char)0x00 + "o" + (char)0x00 + "d" + (char)0x00 + "u" + (char)0x00 + "l" + (char)0x00 + "e" - check = new byte?[] { 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x4d, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x65 }; - if (fileContent.FirstPosition(check, out position)) - return "StarForce 5" + (includePosition ? $" (Index {position})" : string.Empty); + // P + (char)0x00 + r + (char)0x00 + o + (char)0x00 + t + (char)0x00 + e + (char)0x00 + c + (char)0x00 + t + (char)0x00 + e + (char)0x00 + d + (char)0x00 + + (char)0x00 + M + (char)0x00 + o + (char)0x00 + d + (char)0x00 + u + (char)0x00 + l + (char)0x00 + e + (char)0x00 + new Matcher(new byte?[] + { + 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x74, 0x00, + 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x65, 0x00, + 0x64, 0x00, 0x20, 0x00, 0x4d, 0x00, 0x6f, 0x00, + 0x64, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x65, 0x00 + }, "StarForce 5"), + }; - return null; + return MatchUtil.GetFirstContentMatch(file, fileContent, matchers, includePosition); } /// diff --git a/BurnOutSharp/ProtectionType/Tages.cs b/BurnOutSharp/ProtectionType/Tages.cs index 03ef23e0..090e3127 100644 --- a/BurnOutSharp/ProtectionType/Tages.cs +++ b/BurnOutSharp/ProtectionType/Tages.cs @@ -2,35 +2,39 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using BurnOutSharp.Matching; namespace BurnOutSharp.ProtectionType { - // TODO: Figure out how to use GetContentMatches here public class Tages : IContentCheck, IPathCheck { /// public string CheckContents(string file, byte[] fileContent, bool includePosition = false) { - // "protected-tages-runtime.exe" - byte?[] check = new byte?[] { 0x70, 0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x2D, 0x74, 0x61, 0x67, 0x65, 0x73, 0x2D, 0x72, 0x75, 0x6E, 0x74, 0x69, 0x6D, 0x65, 0x2E, 0x65, 0x78, 0x65 }; - if (fileContent.FirstPosition(check, out int position)) - return $"TAGES {Utilities.GetFileVersion(file)}" + (includePosition ? $" (Index {position})" : string.Empty); - - // "tagesprotection.com" - check = new byte?[] { 0x74, 0x61, 0x67, 0x65, 0x73, 0x70, 0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x63, 0x6F, 0x6D }; - if (fileContent.FirstPosition(check, out position)) - return $"TAGES {Utilities.GetFileVersion(file)}" + (includePosition ? $" (Index {position})" : string.Empty); - - // (char)0xE8 + "u" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0xE8 - check = new byte?[] { 0xE8, 0x75, 0x00, 0x00, 0x00, 0xE8 }; - if (fileContent.FirstPosition(check, out position)) + var matchers = new List { - // (char)0xFF + (char)0xFF + "h" - if (new ArraySegment(fileContent, --position + 8, 3).SequenceEqual(new byte[] { 0xFF, 0xFF, 0x68 })) // TODO: Verify this subtract - return $"TAGES {GetVersion(fileContent, position)}" + (includePosition ? $" (Index {position})" : string.Empty); - } + // protected-tages-runtime.exe + new Matcher(new byte?[] + { + 0x70, 0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x65, + 0x64, 0x2D, 0x74, 0x61, 0x67, 0x65, 0x73, 0x2D, + 0x72, 0x75, 0x6E, 0x74, 0x69, 0x6D, 0x65, 0x2E, + 0x65, 0x78, 0x65 + }, Utilities.GetFileVersion, "TAGES"), - return null; + // tagesprotection.com + new Matcher(new byte?[] + { + 0x74, 0x61, 0x67, 0x65, 0x73, 0x70, 0x72, 0x6F, + 0x74, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x2E, + 0x63, 0x6F, 0x6D + }, Utilities.GetFileVersion, "TAGES"), + + // (char)0xE8 + u + (char)0x00 + (char)0x00 + (char)0x00 + (char)0xE8 + new Matcher(new byte?[] { 0xE8, 0x75, 0x00, 0x00, 0x00, 0xE8 }, GetVersion, "TAGES"), + }; + + return MatchUtil.GetFirstContentMatch(file, fileContent, matchers, includePosition); } /// @@ -90,6 +94,15 @@ namespace BurnOutSharp.ProtectionType return null; } + public static string GetVersion(string file, byte[] fileContent, int position) + { + // (char)0xFF + (char)0xFF + "h" + if (new ArraySegment(fileContent, --position + 8, 3).SequenceEqual(new byte[] { 0xFF, 0xFF, 0x68 })) // TODO: Verify this subtract + return GetVersion(fileContent, position); + + return null; + } + private static string GetVersion(byte[] fileContent, int position) { switch (fileContent[position + 7]) diff --git a/BurnOutSharp/ProtectionType/VOBProtectCDDVD.cs b/BurnOutSharp/ProtectionType/VOBProtectCDDVD.cs index 69c83af4..04ad5fbd 100644 --- a/BurnOutSharp/ProtectionType/VOBProtectCDDVD.cs +++ b/BurnOutSharp/ProtectionType/VOBProtectCDDVD.cs @@ -4,46 +4,32 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Threading; +using BurnOutSharp.Matching; namespace BurnOutSharp.ProtectionType { - // TODO: Figure out how to use GetContentMatches here public class VOBProtectCDDVD : IContentCheck, IPathCheck { /// public string CheckContents(string file, byte[] fileContent, bool includePosition = false) { - // "VOB ProtectCD" - byte?[] check = new byte?[] { 0x56, 0x4F, 0x42, 0x20, 0x50, 0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x43, 0x44 }; - if (fileContent.FirstPosition(check, out int position)) - return $"VOB ProtectCD/DVD {GetOldVersion(fileContent, --position)}" + (includePosition ? $" (Index {position})" : string.Empty); // TODO: Verify this subtract - - // "DCP-BOV" + (char)0x00 + (char)0x00 - check = new byte?[] { 0x44, 0x43, 0x50, 0x2D, 0x42, 0x4F, 0x56, 0x00, 0x00 }; - if (fileContent.FirstPosition(check, out position)) + var matchers = new List { - string version = GetVersion(fileContent, --position); // TODO: Verify this subtract - if (version.Length > 0) - return $"VOB ProtectCD/DVD {version}" + (includePosition ? $" (Index {position})" : string.Empty); - - version = SearchProtectDiscVersion(file, fileContent); - if (version.Length > 0) + // VOB ProtectCD + new Matcher(new byte?[] { - if (version.StartsWith("2")) - version = $"6{version.Substring(1)}"; + 0x56, 0x4F, 0x42, 0x20, 0x50, 0x72, 0x6F, 0x74, + 0x65, 0x63, 0x74, 0x43, 0x44 + }, GetOldVersion, "VOB ProtectCD/DVD"), - return $"VOB ProtectCD/DVD {version}" + (includePosition ? $" (Index {position})" : string.Empty); - } + // DCP-BOV + (char)0x00 + (char)0x00 + new Matcher(new byte?[] { 0x44, 0x43, 0x50, 0x2D, 0x42, 0x4F, 0x56, 0x00, 0x00 }, GetVersion, "VOB ProtectCD/DVD"), - return $"VOB ProtectCD/DVD 5.9-6.0 {GetBuild(fileContent, position)}" + (includePosition ? $" (Index {position})" : string.Empty); - } + // .vob.pcd + new Matcher(new byte?[] { 0x2E, 0x76, 0x6F, 0x62, 0x2E, 0x70, 0x63, 0x64 }, "VOB ProtectCD"), + }; - // ".vob.pcd" - check = new byte?[] { 0x2E, 0x76, 0x6F, 0x62, 0x2E, 0x70, 0x63, 0x64 }; - if (fileContent.FirstPosition(check, out position)) - return "VOB ProtectCD" + (includePosition ? $" (Index {position})" : string.Empty); - - return null; + return MatchUtil.GetFirstContentMatch(file, fileContent, matchers, includePosition); } /// @@ -64,6 +50,34 @@ namespace BurnOutSharp.ProtectionType return null; } + public static string GetOldVersion(string file, byte[] fileContent, int position) + { + position--; // TODO: Verify this subtract + char[] version = new ArraySegment(fileContent, position + 16, 4).Select(b => (char)b).ToArray(); // Begin reading after "VOB ProtectCD" + if (char.IsNumber(version[0]) && char.IsNumber(version[2]) && char.IsNumber(version[3])) + return $"{version[0]}.{version[2]}{version[3]}"; + + return "old"; + } + + public static string GetVersion(string file, byte[] fileContent, int position) + { + string version = GetVersion(fileContent, --position); // TODO: Verify this subtract + if (version.Length > 0) + return version; + + version = SearchProtectDiscVersion(file, fileContent); + if (version.Length > 0) + { + if (version.StartsWith("2")) + version = $"6{version.Substring(1)}"; + + return version; + } + + return $"5.9-6.0 {GetBuild(fileContent, position)}"; + } + private static string GetBuild(byte[] fileContent, int position) { if (!char.IsNumber((char)fileContent[position - 13])) @@ -73,15 +87,6 @@ namespace BurnOutSharp.ProtectionType return $" (Build {build})"; } - private static string GetOldVersion(byte[] fileContent, int position) - { - char[] version = new ArraySegment(fileContent, position + 16, 4).Select(b => (char)b).ToArray(); // Begin reading after "VOB ProtectCD" - if (char.IsNumber(version[0]) && char.IsNumber(version[2]) && char.IsNumber(version[3])) - return $"{version[0]}.{version[2]}{version[3]}"; - - return "old"; - } - private static string GetVersion(byte[] fileContent, int position) { if (fileContent[position - 2] == 5)