From 3a6b512bc1c0a03311403c7827f8fc8e98d44ee0 Mon Sep 17 00:00:00 2001 From: bestest Date: Sun, 27 Oct 2024 13:27:14 -0400 Subject: [PATCH 1/4] Improve Copy-X Light detection with additional folder check. --- BinaryObjectScanner/Protection/CopyX.cs | 54 ++++++++++++++++--------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/BinaryObjectScanner/Protection/CopyX.cs b/BinaryObjectScanner/Protection/CopyX.cs index 968a1f62..dcad9f59 100644 --- a/BinaryObjectScanner/Protection/CopyX.cs +++ b/BinaryObjectScanner/Protection/CopyX.cs @@ -21,7 +21,7 @@ public class CopyX : IPathCheck, IPortableExecutableCheck { // Previous check 'Tivola Ring Protect' removed because it was found to actually be copy-x. // The checks were for ZDAT/webmast.dxx and ZDAT/webmast.dxx, for Redump IDs 81628 and 116418. - + // https://web.archive.org/web/20011016234742/http://www.optimal-online.de:80/product/copy_x.htm // There are four kinds of copy-X; Light, Profesisonal, audio, and Trial Maker. // Audio is for Audio CDs. Might be scannable, might not. Samples needed to confirm. @@ -37,14 +37,15 @@ public class CopyX : IPathCheck, IPortableExecutableCheck // Both Light and Professional have a directory at the end of the image. The files within this directory are // intersected by the physical ring. // This file is usually called ZDAT, but not always. At least one instance of Light calls it ZDATA. At least one - // instance of Professional calls it System. + // instance of Light calls it System. // Seemingly it can be anything. It doesn't help that most known samples are specifically from one company's // games, Tivola. Still, most use ZDAT. // Professional: // All instances of professional contain a disc check, performed via optgraph.dll. - // All instances of professional contain in the directory at the end of the image 3 files. gov_[something].x64, - // iofile.x64, and sound.x64. + // All instances of professional contain in a directory usually (but not always, German Emergency 2 Deluxe has a + // Videos folder as well, which isn't involved in rings/protection) at the end of the image, 3 files: + // gov_[something].x64, iofile.x64, and sound.x64. So far, they have always been in a directory called "System". // Due to gov's minor name variance, sound.x64 sometimes being intersected by a ring at the start, and // iofile.x64 being referenced directly in optgraph.x64, only iofile.x64 is being checked for now. // TODO: optgraph.dll also contains DRM to prevent kernel debugger SoftICE from being used, via a process called @@ -53,9 +54,10 @@ public class CopyX : IPathCheck, IPortableExecutableCheck // It has none here since it wouldn't be necessary. // Light: - // All instances of light contain 1 or more files in the directory at the end of the image. They all consist of - // either 0x00, or some data that matches between entries (and also is present in the 3 Professional files), - // except for the parts with the rings running through them. + // All instances of light contain 1 or more files in the directory usually (but not always; Kenny's Adventure has + // uses a System folder, and then has a non-protection Xtras folder on the disc as well) at the end of the image. + // They all consist of either 0x00, or some data that matches between entries (and also is present in the 3 + // Professional files), except for the parts with the rings running through them. // TODO: Check the last directory alphabetically and not just ZDAT* /// @@ -114,22 +116,33 @@ public ConcurrentQueue CheckDirectoryPath(string path, IEnumerable !f.EndsWith(".x64", StringComparison.OrdinalIgnoreCase)) - .Where(f => + + string[] dirs = ["ZDAT", "System/", "System\\"];//Kenny's Adventure uses System instead of ZDAT. + List? lightFiles = null; + // TODO: Compensate for the check being run a directory or more higher + var fileList = files.Where(f => !f.EndsWith(".x64", StringComparison.OrdinalIgnoreCase)); + { + foreach (var dir in dirs) { - // TODO: Compensate for the check being run a directory or more higher - f = f.Remove(0, path.Length); - f = f.TrimStart('/', '\\'); - return f.StartsWith("ZDAT", StringComparison.OrdinalIgnoreCase); - }) - .OrderBy(f => f) - .ToList(); - - if (fileList.Count > 0) + lightFiles = fileList.Where(f => + { + f = f.Remove(0, path.Length); + f = f.TrimStart('/', '\\'); + return f.StartsWith(dir, StringComparison.OrdinalIgnoreCase); + }) + .OrderBy(f => f) + .ToList(); + if (lightFiles.Any()) + { + break; + } + } + } + if (lightFiles.Count > 0) { try { - using var stream = File.OpenRead(fileList[0]); + using var stream = File.OpenRead(lightFiles[0]); byte[] block = stream.ReadBytes(1024); var matchers = new List @@ -153,7 +166,7 @@ public ConcurrentQueue CheckDirectoryPath(string path, IEnumerable CheckDirectoryPath(string path, IEnumerable Date: Sun, 27 Oct 2024 20:07:11 -0400 Subject: [PATCH 2/4] Add requested changes to additional copy-X light folder check. --- BinaryObjectScanner/Protection/CopyX.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/BinaryObjectScanner/Protection/CopyX.cs b/BinaryObjectScanner/Protection/CopyX.cs index dcad9f59..05d59ca9 100644 --- a/BinaryObjectScanner/Protection/CopyX.cs +++ b/BinaryObjectScanner/Protection/CopyX.cs @@ -58,7 +58,7 @@ public class CopyX : IPathCheck, IPortableExecutableCheck // uses a System folder, and then has a non-protection Xtras folder on the disc as well) at the end of the image. // They all consist of either 0x00, or some data that matches between entries (and also is present in the 3 // Professional files), except for the parts with the rings running through them. - // TODO: Check the last directory alphabetically and not just ZDAT* + // Find a viable way to check the last directory alphabetically and not just ZDAT* /// public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug) @@ -117,7 +117,7 @@ public ConcurrentQueue CheckDirectoryPath(string path, IEnumerable? lightFiles = null; // TODO: Compensate for the check being run a directory or more higher var fileList = files.Where(f => !f.EndsWith(".x64", StringComparison.OrdinalIgnoreCase)); @@ -128,17 +128,15 @@ public ConcurrentQueue CheckDirectoryPath(string path, IEnumerable f) .ToList(); - if (lightFiles.Any()) - { + if (lightFiles.Count() > 0) break; - } } } - if (lightFiles.Count > 0) + if ((lightFiles != null) && (lightFiles.Count > 0)) { try { From 09fdd81933e4460b7242934c4d78d85f0ecd22b4 Mon Sep 17 00:00:00 2001 From: bestest Date: Sun, 27 Oct 2024 20:13:37 -0400 Subject: [PATCH 3/4] Cleaned up changes. --- BinaryObjectScanner/Protection/CopyX.cs | 26 ++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/BinaryObjectScanner/Protection/CopyX.cs b/BinaryObjectScanner/Protection/CopyX.cs index 05d59ca9..5861efbb 100644 --- a/BinaryObjectScanner/Protection/CopyX.cs +++ b/BinaryObjectScanner/Protection/CopyX.cs @@ -119,23 +119,23 @@ public ConcurrentQueue CheckDirectoryPath(string path, IEnumerable? lightFiles = null; + // TODO: Compensate for the check being run a directory or more higher var fileList = files.Where(f => !f.EndsWith(".x64", StringComparison.OrdinalIgnoreCase)); + foreach (var dir in dirs) { - foreach (var dir in dirs) - { - lightFiles = fileList.Where(f => - { - f = f.Remove(0, path.Length); - f = f.TrimStart('/', '\\'); - return f.StartsWith(dir + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase); - }) - .OrderBy(f => f) - .ToList(); - if (lightFiles.Count() > 0) - break; - } + lightFiles = fileList.Where(f => + { + f = f.Remove(0, path.Length); + f = f.TrimStart('/', '\\'); + return f.StartsWith(dir + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase); + }) + .OrderBy(f => f) + .ToList(); + if (lightFiles.Count() > 0) + break; } + if ((lightFiles != null) && (lightFiles.Count > 0)) { try From c6cb8faf35781d3a0e251e457aa2ab393e21c592 Mon Sep 17 00:00:00 2001 From: bestest Date: Sun, 27 Oct 2024 20:19:19 -0400 Subject: [PATCH 4/4] One final comment cleanup. --- BinaryObjectScanner/Protection/CopyX.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/BinaryObjectScanner/Protection/CopyX.cs b/BinaryObjectScanner/Protection/CopyX.cs index 5861efbb..16066d3d 100644 --- a/BinaryObjectScanner/Protection/CopyX.cs +++ b/BinaryObjectScanner/Protection/CopyX.cs @@ -117,7 +117,8 @@ public ConcurrentQueue CheckDirectoryPath(string path, IEnumerable? lightFiles = null; // TODO: Compensate for the check being run a directory or more higher