Overhaul Macrovision and related protections (#248)

* Improve several SafeCast checks

* Add new SafeCast versions.

* Add SafeCast NE checks.

* Move stxt* checks to Macrovision, and add SafeCast specific check.

* Confirm SafeCast file and add relevant executable checks.

* Add empty file detection for some SafeDisc drivers.

* Various Macrovision improvements

* Move and improve stxt* section checks.

* Add proper Redump entry number for Puyo Puyo Fever.

* Add directory separator to some SafeDisc checks to avoid false positives.

* Add SafeWrap skeleton with notes.

* Minor Macrovision fixes

* Fix stxt* section checks.

* Add product identification for one CDS-300 version.

* Further Macrovision improvements

* Add product detection via version for SafeDisc Lite and SafeCast ESD.

* Add improved SafeDisc LT/Lite checks.

* Add various notes about SafeCast/SafeDisc.

* Add new secdrv version detection.

* Herald the upcoming secdrv cataclysm.

* Move SecDrv checks into Macrovision

* Move SecDrv checks into Macrovision, as it's known to be present on multiple Macrovision products.

* Improve SafeCast checks

* Add new SafeCast executable and path checks.

* Change a C-Dilla output.

* ah sweet, man-made horrors beyond my comprehension

* Split new and old "BoG" string checks to make finding an expunged version easier.

* Confirm unconfirmed SafeCast version, add new unconfirmed version.

* Remove now unneeded result list cleaning.

* Improve SafeCast notes.

* Add new SafeCast file description and file name checks.

* Remove "GetSafeDisc320to4xVersion" and improve CLCD16 version report.

* Address PR comments

* Address further PR comments
This commit is contained in:
TheRogueArchivist
2023-04-21 20:38:18 -06:00
committed by GitHub
parent 20de40014d
commit d91ce3100b
5 changed files with 399 additions and 222 deletions

View File

@@ -27,6 +27,7 @@ namespace BinaryObjectScanner.Protection
/// 3.23.000 (IA item "3ds-max-4.2original").
/// 3.24.010 (IA item "ejay_nestle_trial").
/// 3.27.000 (https://download.autodesk.com/mne/web/support/3dstudio/C-Dilla3.27.zip).
/// 4.11.000 (Possibly an internal version used by SafeCast in Redump entry 95524).
///
/// TODO:
/// Investigate C-Dilla CD-Compress.
@@ -93,9 +94,9 @@ namespace BinaryObjectScanner.Protection
if (name?.Equals("C-Dilla Windows NT RTS", StringComparison.OrdinalIgnoreCase) == true)
return $"C-Dilla License Management System Version {pex.ProductVersion}";
// Found in "CDANTSRV.EXE" from C-Dilla LMS version 3.27.000 for Windows NT.
// Found in "CDANTSRV.EXE" from C-Dilla LMS version 3.27.000 for Windows NT, and an embedded executable contained in Redump entry 95524.
if (name?.Equals("C-Dilla RTS Service", StringComparison.OrdinalIgnoreCase) == true)
return $"C-Dilla License Management System Version {pex.ProductVersion}";
return $"C-Dilla RTS Service Version {pex.ProductVersion}";
name = pex.ProductName;

View File

@@ -2,6 +2,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BinaryObjectScanner.Matching;
using BinaryObjectScanner.Wrappers;
@@ -12,7 +13,9 @@ namespace BinaryObjectScanner.Protection
/// Although SafeCast is most commonly used in non-game software, there is one game that comes with both SafeDisc and SafeCast protections (Redump entry 83145).
/// Macrovision bought the company C-Dilla and created SafeCast based on C-Dilla's existing products (https://web.archive.org/web/20030212040047/http://www.auditmypc.com/freescan/readingroom/cdilla.asp).
/// There are multiple different versions of SafeCast out there.
/// Deep dive of MechWarrior 4 and its expansions, which use SafeDisc, possibly SafeDisc LT, and SafeCast: https://digipres.club/@TheRogueArchivist/110224192068908590
/// SafeCast ESD: https://web.archive.org/web/20000306044246/http://www.macrovision.com/safecast_ESD.html
/// SafeCast ESD Demo: https://web.archive.org/web/20010417215236/http://www.macrovision.com:80/demos/SafeCast_ESD.exe
/// SafeCast Gold: https://web.archive.org/web/20000129071444/http://www.macrovision.com/scp_gold.html
/// SafeCast LM: https://web.archive.org/web/20000128224337/http://www.macrovision.com/safecast_LM.html
/// SafeCast UNSORTED samples:
@@ -24,6 +27,7 @@ namespace BinaryObjectScanner.Protection
/// https://archive.org/details/eJayXtremeSoundtraxx
/// https://community.ptc.com/t5/Mathcad/SafeCast/td-p/25233
/// SafeCast resources:
/// http://web.archive.org/web/20010417222834/http://www.macrovision.com/press_rel3_17_99.html (Press release introducing SafeCast)
/// https://web.archive.org/web/20000129013431/http://www.macrovision.com/safecast_faq.html (SafeCast FAQ)
/// https://web.archive.org/web/20040223025801/http://www.macrovision.com/products/legacy_products/safecast/safecast_cdilla_faq.shtml
/// https://web.archive.org/web/20031204024544mp_/http://www.macrovision.com/products/safecast/index.shtml
@@ -36,18 +40,31 @@ namespace BinaryObjectScanner.Protection
/// <inheritdoc cref="BinaryObjectScanner.Interfaces.INewExecutableCheck.CheckNewExecutable(string, NewExecutable, bool)"/>
internal string SafeCastCheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
{
// Check we have a valid executable
// Check we have a valid executable.
if (nex == null)
return null;
// TODO: Implement the following NE checks:
// Check for the CDAC01AA name string.
bool cdac01aaNameFound = nex.ResidentNameTable.Where(rnte => rnte?.NameString != null)
.Select(rnte => Encoding.ASCII.GetString(rnte.NameString))
.Any(s => s.Contains("CDAC01AA"));
if (cdac01aaNameFound)
return "SafeCast";
// File Description "CdaC01A" in "cdac01aa.dll" from IA item "ejay_nestle_trial".
// File Description "CdaC01BA" in "cdac01ba.dll" from IA item "ejay_nestle_trial".
// Product name "SafeCas" in "cdac01aa.dll" from IA item "ejay_nestle_trial".
// Product name "SafeCast" in "cdac01ba.dll" from IA item "ejay_nestle_trial".
// TODO: Don't read entire file
var data = nex.ReadArbitraryRange();
if (data == null)
return null;
return null;
var neMatchSets = new List<ContentMatchSet>
{
// 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"),
};
return MatchUtil.GetFirstMatch(file, data, neMatchSets, includeDebug);
}
/// <inheritdoc cref="BinaryObjectScanner.Interfaces.IPortableExecutableCheck.CheckPortableExecutable(string, PortableExecutable, bool)"/>
@@ -69,6 +86,7 @@ namespace BinaryObjectScanner.Protection
}
// Get the dialog box resources
// Found in "CDAC21BA.DLL" in Redump entry 95524.
var resource = pex.FindDialogByTitle("SafeCast API");
if (resource.Any())
return "SafeCast";
@@ -87,12 +105,40 @@ namespace BinaryObjectScanner.Protection
if (name?.Equals("SafeCast2", StringComparison.OrdinalIgnoreCase) == true)
return "SafeCast";
// Found in "cdac01ba.dll" from IA item "ejay_nestle_trial".
// TODO: Figure out a reasonable way to parse version.
if (name?.Equals("CdaC01BA", StringComparison.OrdinalIgnoreCase) == true)
return $"SafeCast";
// Found in "C2CDEL.EXE" in IA item "britney-spears-special-edition-cd-rom".
if (name?.Equals("32-bit SafeCast Copy To Clear Delete", StringComparison.OrdinalIgnoreCase) == true)
return $"SafeCast";
// Found in "C2C.DLL" in IA item "britney-spears-special-edition-cd-rom".
if (name?.Equals("32-bit SafeCast Shell Copy To Clear DLL", StringComparison.OrdinalIgnoreCase) == true)
return $"SafeCast";
// Found in "SCRfrsh.exe" in Redump entry 102979.
if (name?.Equals("32-bit SafeCast Toolkit", StringComparison.OrdinalIgnoreCase) == true)
return $"SafeCast {pex.FileVersion}";
// Found in "CDAC14BA.DLL" in Redump entry 95524.
if (name?.Equals("32-bit SafeCast Anchor Installer", StringComparison.OrdinalIgnoreCase) == true)
return $"SafeCast";
// Found in "CDAC21BA.DLL" in Redump entry 95524.
if (name?.Equals("32-bit CdaC20BA", StringComparison.OrdinalIgnoreCase) == true)
return $"SafeCast";
// Found in hidden resource of "32bit\Tax02\cdac14ba.dll" in IA item "TurboTax Deluxe Tax Year 2002 for Wndows (2.00R)(Intuit)(2002)(352282)".
// TODO: Fix Product Name not getting properly pulled for this executable.
name = pex.ProductName;
if (name?.Equals("SafeCast Windows NT", StringComparison.OrdinalIgnoreCase) == true)
return "SafeCast";
// Found in "cdac01ba.dll" from IA item "ejay_nestle_trial".
if (name?.Equals("SafeCast", StringComparison.OrdinalIgnoreCase) == true)
return "SafeCast";
// Check for CDSHARE/DISAG_SH sections
return null;
@@ -103,18 +149,39 @@ namespace BinaryObjectScanner.Protection
{
var matchers = new List<PathMatchSet>
{
// Found in IA item "britney-spears-special-edition-cd-rom".
new PathMatchSet(new List<PathMatch>
{
new PathMatch("C2C.16", useEndsWith: true),
new PathMatch("C2C.DLL", useEndsWith: true),
new PathMatch("C2CDEL.16", useEndsWith: true),
new PathMatch("C2CDEL.EXE", useEndsWith: true),
}, "SafeCast"),
// Found in IA item "ejay_nestle_trial".
new PathMatchSet(new PathMatch("cdac01aa.dll", useEndsWith: true), "SafeCast"),
new PathMatchSet(new PathMatch("cdac01ba.dll", useEndsWith: true), "SafeCast"),
// Found in multiple versions of SafeCast, including Redump entry 83145 and IA item "TurboTax_Deluxe_Tax_Year_2002_for_Wndows_2.00R_Intuit_2002_352282".
// Found in multiple versions of SafeCast, including Redump entries 83145 and 95524, as well as IA item "TurboTax_Deluxe_Tax_Year_2002_for_Wndows_2.00R_Intuit_2002_352282".
new PathMatchSet(new PathMatch("cdac14ba.dll", useEndsWith: true), "SafeCast"),
// Found in Redump entry 83145.
new PathMatchSet(new PathMatch("CDAC21BA.DLL", useEndsWith: true), "SafeCast"),
// Shown in multiple sources (such as https://groups.google.com/g/alt.english.usage/c/kcBzeqXgE-M) to be associated with SafeCast, but no samples have been found as of yet.
new PathMatchSet(new PathMatch("SCRfrsh.exe", useEndsWith: true), "SafeCast (Unconfirmed - Please report to us on Github)"),
// Found in Redump entry 102979.
new PathMatchSet(new PathMatch("SCRfrsh.exe", useEndsWith: true), "SafeCast"),
// Found in Redump entries 26211 and 95524.
new PathMatchSet(new PathMatch("SCSHD.CSA", useEndsWith: true), "SafeCast"),
// Found in Redump entries 95524.
new PathMatchSet(new PathMatch("SCSHD.EXE", useEndsWith: true), "SafeCast"),
// Found in IA item "TurboTax_Deluxe_Tax_Year_2002_for_Wndows_2.00R_Intuit_2002_352282".
new PathMatchSet(new PathMatch("CDAC15BA.SYS", useEndsWith: true), "SafeCast"),
// Found in "cdac14ba.dll" in IA item "TurboTax_Deluxe_Tax_Year_2002_for_Wndows_2.00R_Intuit_2002_352282".
new PathMatchSet(new PathMatch("CDAC13BA.EXE", useEndsWith: true), "SafeCast"),
};
return MatchUtil.GetAllMatches(files, matchers, any: false);
@@ -137,8 +204,20 @@ namespace BinaryObjectScanner.Protection
// Found in Redump entry 83145.
new PathMatchSet(new PathMatch("CDAC21BA.DLL", useEndsWith: true), "SafeCast"),
// Shown in multiple sources (such as https://groups.google.com/g/alt.english.usage/c/kcBzeqXgE-M) to be associated with SafeCast, but no samples have been found as of yet.
new PathMatchSet(new PathMatch("SCRfrsh.exe", useEndsWith: true), "SafeCast (Unconfirmed - Please report to us on Github)"),
// Found in Redump entry 102979.
new PathMatchSet(new PathMatch("SCRfrsh.exe", useEndsWith: true), "SafeCast"),
// Found in Redump entries 26211 and 95524.
new PathMatchSet(new PathMatch("SCSHD.CSA", useEndsWith: true), "SafeCast"),
// Found in Redump entries 95524.
new PathMatchSet(new PathMatch("SCSHD.EXE", useEndsWith: true), "SafeCast"),
// Found in IA item "TurboTax_Deluxe_Tax_Year_2002_for_Wndows_2.00R_Intuit_2002_352282".
new PathMatchSet(new PathMatch("CDAC15BA.SYS", useEndsWith: true), "SafeCast"),
// Found in "cdac14ba.dll" in IA item "TurboTax_Deluxe_Tax_Year_2002_for_Wndows_2.00R_Intuit_2002_352282".
new PathMatchSet(new PathMatch("CDAC13BA.EXE", useEndsWith: true), "SafeCast"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);

View File

@@ -15,13 +15,25 @@ namespace BinaryObjectScanner.Protection
/// SafeDisc has been most commonly found on PC games and applications, though there a number of Mac discs that contain the protection as well.
/// At least one system other than PC/Mac is known to use SafeDisc as well, this being the "ZAPiT Games Game Wave Family Entertainment System" which seems to use a form of SafeDisc 4 (Redump entry 46269).
/// SafeDisc resources:
/// https://web.archive.org/web/20010707163339/http://www.macrovision.com:80/demos/safedisc.exe (SafeDisc Demo)
/// https://web.archive.org/web/20000307003925/http://www.macrovision.com/scp_faq.html (SafeDisc FAQ)
/// https://web.archive.org/web/20030620175810/http://www.macrovision.com:80/solutions/software/cdrom/SafeDisc_V2_FAQ_April_2002.pdf (SafeDisc 2 FAQ)
/// https://web.archive.org/web/20040610212031/http://www.macrovision.com:80/pdfs/SafeDisc_V3_FAQ_Oct2003.pdf (SafeDisc 3 FAQ)
/// https://web.archive.org/web/20040610205241/http://www.macrovision.com:80/pdfs/SafeDisc_v315_FAQ_Dec2003.pdf (SafeDisc 3.15 FAQ)
/// https://web.archive.org/web/20051015170118/http://www.macrovision.com/pdfs/safedisc_v4_FAQ_sep2004.pdf (SafeDisc 4 FAQ)
/// https://web.archive.org/web/20070124144331/http://www.macrovision.com/pdfs/SafeDisc_Brochure_Oct04.pdf (SafeDisc brochure)
/// https://web.archive.org/web/20041008173722/http://www.macrovision.com/pdfs/safedisc_datasheet.pdf (SafeDisc datasheet)
/// https://web.archive.org/web/20030421023647/http://www.macrovision.com:80/solutions/software/cdrom/SafeDisc_WhitePaper_4-17-02-web.pdf (SafeDisc WhitePaper)
/// https://web.archive.org/web/20011005034102/http://www.macrovision.com/solutions/software/cdrom/pccdrom/safedischd.php3 (SafeDisc HD product page)
/// https://web.archive.org/web/20031009091909/http://www.macrovision.com/products/safedisc/index.shtml
/// https://web.archive.org/web/20041023011150/http://www.macrovision.com/products/safedisc/index.shtml (Marketed as "SafeDisc Advanced")
/// https://web.archive.org/web/20080604020524/http://www.trymedia.com/safedisc-advanced.html
/// https://web.archive.org/web/20041008173722/http://www.macrovision.com/pdfs/safedisc_datasheet.pdf
/// https://www.cdmediaworld.com/hardware/cdrom/cd_protections_safedisc.shtml
/// https://computerizedaccount.tripod.com/computerizedaccountingtraining/id27.html
///
/// SafeDisc Lite/LT is an alternate version of SafeDisc available that was based on SafeDisc 1 (https://web.archive.org/web/20030421023647/http://www.macrovision.com:80/solutions/software/cdrom/SafeDisc_WhitePaper_4-17-02-web.pdf).
/// Although seemingly only officially referred to as "SafeDisc LT", a multitude of sources, including one that seemingly worked directly with Macrovision, call it "SafeDisc Lite" (http://www.eclipsedata.com/insidepages.asp?pageID=149).
/// Other protections in the Macrovision "Safe-" family of protections that need further investigation:
/// SafeScan (https://cdn.loc.gov/copyright/1201/2003/reply/029.pdf).
/// SafeDisc HD (https://web.archive.org/web/20000129100449/http://www.macrovision.com/scp_hd.html).
@@ -37,12 +49,32 @@ namespace BinaryObjectScanner.Protection
if (sections == null)
return null;
// Found in Redump entry 57986.
bool hintNameTableMatch = pex.ImportHintNameTable?.Any(ihne => ihne == "LTDLL_Authenticate") ?? false;
if (hintNameTableMatch)
return "SafeDisc Lite";
// Found in Redump entry 57986.
bool importTableMatch = (pex.ImportTable?.ImportDirectoryTable?.Any(idte => idte.Name == "ltdll.dll") ?? false);
if (importTableMatch)
return "SafeDisc Lite";
// Get the .data/DATA section strings, if they exist
List<string> strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
if (strs != null)
{
// Found in Redump entries 14928, 25579, 32751.
if (strs.Any(s => s.Contains("LTDLL_Initialise")))
return "SafeDisc Lite";
if (strs.Any(s => s.Contains("LTDLL_Authenticate")))
return "SafeDisc Lite";
if (strs.Any(s => s.Contains("LTDLL_Unwrap")))
return "SafeDisc Lite";
}
string name = pex.FileDescription;
// Present in "secdrv.sys" files found in SafeDisc 2.80.010+.
if (name?.Equals("Macrovision SECURITY Driver", StringComparison.OrdinalIgnoreCase) == true)
return $"SafeDisc Security Driver {GetSecDrvExecutableVersion(pex)}";
// Present in "Diag.exe" files from SafeDisc 4.50.000+.
else if (name?.Equals("SafeDisc SRV Tool APP", StringComparison.OrdinalIgnoreCase) == true)
if (name?.Equals("SafeDisc SRV Tool APP", StringComparison.OrdinalIgnoreCase) == true)
return $"SafeDisc SRV Tool APP {GetSafeDiscDiagExecutableVersion(pex)}";
// Present on all "CLOKSPL.DLL" versions before SafeDisc 1.06.000. Found on Redump entries 61731 and 66004.
@@ -53,24 +85,6 @@ namespace BinaryObjectScanner.Protection
else if (name?.Equals("SafeDisc SRV Tool APP", StringComparison.OrdinalIgnoreCase) == true)
return $"SafeDisc SRV Tool APP {GetSafeDiscDiagExecutableVersion(pex)}";
// Get the stxt371 and stxt774 sections, if they exist -- TODO: Confirm if both are needed or either/or is fine.
// Found together in seemingly every SafeDisc 2+ game, and appear to always be the final two sections.
bool stxt371Section = pex.ContainsSection("stxt371", exact: true);
bool stxt774Section = pex.ContainsSection("stxt774", exact: true);
if (stxt371Section || stxt774Section)
{
int entryPointIndex = pex.FindEntryPointSectionIndex();
string entryPointSectionName = pex.SectionNames[entryPointIndex];
// Check if the entry point is one of the known protected sections.
// If it isn't, the executable has likely been cracked to remove the protection, or has been corrupted or tampered with and is no longer functional.
// TODO: Check if both sections can be entry points.
if (entryPointSectionName == "stxt371" || entryPointSectionName == "stxt774")
return "SafeDisc 2+";
return "SafeDisc 2+ (Entry point not present in a stxt* section. Executable is either unprotected or nonfunctional)";
}
// Present on all "CLOKSPL.EXE" versions before SafeDisc 1.06.000. Found on Redump entries 61731 and 66004.
// Only found so far on SafeDisc 1.00.025-1.01.044, but the report is currently left generic due to the generic nature of the check.
name = pex.FileDescription;
@@ -143,9 +157,8 @@ namespace BinaryObjectScanner.Protection
// Found in many versions of SafeDisc, beginning in 2.05.030 and being used all the way until the final version 4.90.010. It is not always present, even in versions it has been used in. Found in Redump entries 56319 and 72195.
new PathMatchSet(new PathMatch("00000002.TMP", useEndsWith: true), "SafeDisc 2+"),
new PathMatchSet(new PathMatch("DPLAYERX.DLL", useEndsWith: true), GetSafeDiscDPlayerXVersion, "SafeDisc"),
new PathMatchSet(new PathMatch("drvmgt.dll", useEndsWith: true), GetSafeDiscDrvmgtVersion, "SafeDisc"),
new PathMatchSet(new PathMatch("secdrv.sys", useEndsWith: true), GetSafeDiscSecdrvVersion, "SafeDisc Security Driver"),
new PathMatchSet(new PathMatch($"{Path.DirectorySeparatorChar}DPLAYERX.DLL", useEndsWith: true), GetSafeDiscDPlayerXVersion, "SafeDisc"),
new PathMatchSet(new PathMatch($"{Path.DirectorySeparatorChar}drvmgt.dll", useEndsWith: true), GetSafeDiscDrvmgtVersion, "SafeDisc"),
// The SD0XXX.dll files appear to solely contain custom strings that allowed the publisher to customize the SafeDisc error messages. They are currently only known to be used by EA.
// Each file appears to contain strings for a specific language each.
@@ -218,9 +231,8 @@ namespace BinaryObjectScanner.Protection
// TODO: Research "splash16.bmp" and "splash256.bmp".
new PathMatchSet(new PathMatch("DPLAYERX.DLL", useEndsWith: true), GetSafeDiscDPlayerXVersion, "SafeDisc"),
new PathMatchSet(new PathMatch("drvmgt.dll", useEndsWith: true), GetSafeDiscDrvmgtVersion, "SafeDisc"),
new PathMatchSet(new PathMatch("secdrv.sys", useEndsWith: true), GetSafeDiscSecdrvVersion, "SafeDisc Security Driver"),
new PathMatchSet(new PathMatch($"{Path.DirectorySeparatorChar}DPLAYERX.DLL", useEndsWith: true), GetSafeDiscDPlayerXVersion, "SafeDisc"),
new PathMatchSet(new PathMatch($"{Path.DirectorySeparatorChar}drvmgt.dll", useEndsWith: true), GetSafeDiscDrvmgtVersion, "SafeDisc"),
// The SD0XXX.dll files appear to solely contain custom strings that allowed the publisher to customize the SafeDisc error messages. They are currently only known to be used by EA.
// Each file appears to contain strings for a specific language each.
@@ -282,8 +294,6 @@ namespace BinaryObjectScanner.Protection
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
internal static string GetSafeDisc320to4xVersion(string file, byte[] fileContent, List<int> positions) => "3.20-4.xx [version expunged]";
internal static string GetSafeDiscCLCD16Version(string firstMatchedString, IEnumerable<string> files)
{
if (string.IsNullOrEmpty(firstMatchedString) || !File.Exists(firstMatchedString))
@@ -302,7 +312,7 @@ namespace BinaryObjectScanner.Protection
return "1.00.026";
// Found in Redump entries 31149 and 28810.
case "848EDF9F45A8437438B7289BB4D2D1BCF752FD4A":
return "1.06.000-1.50.020";
return "1.06.000-1.50.020/Lite";
default:
return "Unknown Version (Report this to us on GitHub)";
}
@@ -565,6 +575,9 @@ namespace BinaryObjectScanner.Protection
string sha1 = GetFileSHA1(firstMatchedString);
switch (sha1)
{
// Found in Redump entry 102979.
case "B858CB282617FB0956D960215C8E84D1CCF909C6":
return "(Empty File)";
// Found in Redump entries 29073 and 31149.
case "33434590D7DE4EEE2C35FCC98B0BF141F422B26D":
return "1.06.000";
@@ -689,7 +702,7 @@ namespace BinaryObjectScanner.Protection
// Found in Redump entry 56320.
case "84480ABCE4676EEB9C43DFF7C5C49F0D574FAC25":
return "4.70.000";
// Found distributed in https://web.archive.org/web/20040614184055/http://www.macrovision.com:80/products/safedisc/safedisc.exe, but unknown what version it is associated with.
// Found distributed in https://web.archive.org/web/20040614184055/http://www.macrovision.com:80/products/safedisc/safedisc.exe and https://web.archive.org/web/20010707163339/http://www.macrovision.com:80/demos/safedisc.exe, but unknown what version it is associated with.
case "8426690FA43076EE466FD1B2D1F2F1267F9CC3EC":
return "Unknown Version (Report this to us on GitHub)";
default:
@@ -708,76 +721,6 @@ namespace BinaryObjectScanner.Protection
}
}
// TODO: Verify these checks and remove any that may not be needed, file version checks should remove the need for any checks for 2.80+.
internal static string GetSafeDiscSecdrvVersion(string firstMatchedString, IEnumerable<string> files)
{
if (string.IsNullOrEmpty(firstMatchedString) || !File.Exists(firstMatchedString))
return string.Empty;
FileInfo fi = new FileInfo(firstMatchedString);
switch (fi.Length)
{
// Found in Redump entries 9718, 12885, 21154, 31149, 37523, 37920.
case 14_304:
return "/ SafeDisc 1.06.000-1.20.001";
// Found in Redump entries 9617 and 31526.
case 14_368:
return "/ SafeDisc 1.30.010-1.35.000";
// Found in Redump entries 2595, 37832, and 44350.
case 10_848:
return "/ SafeDisc 1.40.004-1.41.001";
// Found in Redump entries 30555 and 55078.
case 11_968:
return "/ SafeDisc 1.45.011";
// Found in Redump entries 28810 and 62935.
case 11_616:
return "/ SafeDisc 1.50.020";
// Found in Redump entries 72195 and 73502.
case 18_768:
return "/ SafeDisc 2.05.030";
// Found in Redump entries 38541 and 59462.
case 20_128:
return "/ SafeDisc 2.10.030";
// Found in Redump entries 9819, 15312, 55823.
case 27_440:
return "/ SafeDisc 2.30.030-2.30.033";
// Found in Redump entries 9846 and 23786.
case 28_624:
return "/ SafeDisc 2.40.010-2.40.011";
// Found in Redump entries 30022 and 31666.
case 28_400:
return "/ SafeDisc 2.51.020-2.51.021";
// Found in Redump entries 2064 and 47047.
case 29_392:
return "/ SafeDisc 2.60.052";
// Found in Redump entries 13048 and 48101.
case 11_376:
return "/ SafeDisc 2.70.030-2.72.000";
// Found in Redump entries 32783 and 39273.
case 12_464:
return "3.17.000 / SafeDisc 2.80.010";
// Found in Redump entries 11638 and 52606.
case 12_400:
return "3.18.000 / SafeDisc 2.90.010-2.90.040";
// Found in Redump entries 13230, 15383, and 36511.
case 12_528:
return "3.19.000 / SafeDisc 3.10.020-3.15.011";
// Found in Redump entries 58625 and 84586.
case 11_973:
return "3.22.000 / SafeDisc 3.20.020-3.20.022";
// Found in Redump entries 15614, 42034, 45686, 56320, 60021, 79729, and 80776.
case 163_644:
return "4.00.060 / SafeDisc 4.00.000-4.70.000";
// Found distributed online, but so far not in a game release. TODO: Discover original source.
// Can be found at https://github.com/ericwj/PsSecDrv/blob/master/tools/SECDRV/SECDRV.sys, and the file is confirmed to be distributed officialy by Microsoft: https://www.virustotal.com/gui/file/34bbb0459c96b3de94ccb0d73461562935c583d7bf93828da4e20a6bc9b7301d/.
case 23_040:
return "4.03.086 / Unknown SafeDisc version";
// This file is not currently known to be used in versions past 4.70.000.
default:
return "Unknown Version (Report this to us on GitHub)";
}
}
private string GetVersionFromSHA1Hash(string sha1Hash)
{
switch (sha1Hash.ToLowerInvariant())
@@ -853,47 +796,5 @@ namespace BinaryObjectScanner.Protection
return "Unknown Version (Report this to us on GitHub)";
}
private string GetSecDrvExecutableVersion(PortableExecutable pex)
{
// 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.
string version = pex.FileVersion;
if (!string.IsNullOrEmpty(version))
{
switch (version)
{
// Found to be in Redump entry 32783.
// The product version is "3.17.000 Windows NT 2002/07/01".
case "3.17.000":
return "3.17.000 / SafeDisc 2.80.010-2.80.011";
// Found to be in Redump entry 52606.
// The product version is "3.18.000 Windows NT 2002/11/14".
case "3.18.000":
return "3.18.000 / SafeDisc 2.90.010-2.90.040";
// Found to be in Redump entry 13230.
// The product version is "3.19.000 Windows NT/2K/XP 2003/03/19".
case "3.19.000":
return "3.19.000 / SafeDisc 3.10.020-3.15.011";
// Found to be in Redump entry 58625.
// The product version is "SECURITY Driver 3.22.000 2004/01/16".
case "3.22.000":
return "3.22.000 / SafeDisc 3.20.020-3.20.022";
// Found to be in Redump entry 15614.
// The product version is "SECURITY Driver 4.00.060 2004/08/31".
case "4.00.060":
return "4.00.060 / SafeDisc 4.00.000-4.70.000";
// Found distributed online, but so far not in a game release. TODO: Discover original source.
// Can be found at https://github.com/ericwj/PsSecDrv/blob/master/tools/SECDRV/SECDRV.sys, and the file is confirmed to be distributed officialy by Microsoft: https://www.virustotal.com/gui/file/34bbb0459c96b3de94ccb0d73461562935c583d7bf93828da4e20a6bc9b7301d/.
// The product version is "SECURITY Driver 4.03.086 2006/09/13".
case "4.03.086":
return "4.03.086 / Unknown SafeDisc version";
default:
return $"Unknown Version {version} (Report this to us on GitHub)";
}
}
return "Unknown Version (Report this to us on GitHub)";
}
}
}

View File

@@ -0,0 +1,45 @@
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Protection
{
/// <summary>
/// SafeWrap (https://web.archive.org/web/20010803054324/http://www.macrovision.com:80/solutions/software/safewrap.php3) is a wrapper created by Macrovision used to protect software.
/// It's used (to an unknown extent) within SafeCast and SafeDisc (https://web.archive.org/web/20030829044647/http://www.macrovision.com:80/solutions/software/SafeWrap_FAQ_July2003.pdf Section #3).
/// It can be used separately from any other Macrovision product, such as (supposedly) for RioPort (https://www.cdrinfo.com/d7/content/macrovision-invests-next-generation-security-and-transport-technologies-internet-delivery).
/// No direct SafeWrap only sample has currently been found, nor is it exactly clear what parts of SafeCast/SafeDisc are SafeWrap.
/// It's claimed that SafeWrap uses one DLL and one .SYS "security driver" (https://www.cdrinfo.com/d7/content/macrovision-invests-next-generation-security-and-transport-technologies-internet-delivery Section #30).
/// This would appear to be referring to the "drvmgt.dll" and "secdrv.sys" files, the latter of which is officially referred to as the "Macrovision SECURITY Driver" in some SafeDisc versions.
/// This may not be fully accurate, as not all of these files are known to always be used with SafeCast, though this does need further investigation.
/// The .stxt* sections found in various Macrovision products may indicate SafeWrap, as they started being used around the time that SafeWrap was made public.
/// It may also be that the "BoG" string known to be present in Macrovision executables could be related to SafeWrap, though its use predates the first known mention of SafeWrap by a few years.
/// SafeWrap may have its origins in SafeDisc-related tech if that's the case, further confusing matters.
/// This unforuantely has several possible unpleasant implications for current checks, such as if the X.YY.ZZZ version string is a generic property of SafeWrap and can be non-standard when used for different products.
/// Currently, no known patents or trademarks for SafeWrap have been found.
///
/// Further information and resources:
/// Macrovision press release that mentions SafeWrap: https://www.sec.gov/Archives/edgar/data/1027443/000100547701501658/ex99-1.txt
/// SafeAudio news that mentions SafeWrap: https://www.cdmediaworld.com/hardware/cdrom/news/0201/safeaudio_3.shtml
/// Eclipse SafeAudio news that mentions SafeWrap: http://www.eclipsedata.com/PDFs/21.pdf
/// Report to congress that mentions SafeWrap: https://www.uspto.gov/sites/default/files/web/offices/dcom/olia/teachreport.pdf
/// Patent that mentions possibly using SafeWrap: https://patents.google.com/patent/US7493289B2/en
/// MacroSafe presentation that mentions current customer of SafeWrap/SafeCast/SafeDisc: https://slideplayer.com/slide/6840826/
/// List of DRM companies and products: https://www1.villanova.edu/villanova/generalcounsel/copyright/digitized/companies.html
/// Forum post that briefly mentions SafeWrap: https://www.ttlg.com/forums/showthread.php?t=70035
/// Document that mentions SafeWrap as third-party security tool: https://www.cs.clemson.edu/course/cpsc420/material/Papers/Guide_AppSecurity.pdf
/// Japanese PDF that mentions SafeWrap: https://ipsj.ixsq.nii.ac.jp/ej/index.php?action=pages_view_main&active_action=repository_action_common_download&item_id=64743&item_no=1&attribute_id=1&file_no=1&page_id=13&block_id=8
/// Korean PDF that mentions SafeWrap: http://contents.kocw.or.kr/contents4/document/lec/2012/KonKuk_glocal/Nohyounghee1/9.pdf
/// Patents that mention the possible use of SafeWrap:
/// https://patentscope.wipo.int/search/en/detail.jsf?docId=US42774631&_cid=P20-LGE2MB-82932-1
/// https://patentscope.wipo.int/search/en/detail.jsf?docId=US40713491&_cid=P20-LGE2MB-82932-1
/// </summary>
public partial class Macrovision
{
/// <inheritdoc cref="BinaryObjectScanner.Interfaces.IPortableExecutableCheck.CheckPortableExecutable(string, PortableExecutable, bool)"/>
internal string SafeWrapCheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// TODO: Figure out what SafeWrap is exactly, and add checks.
return null;
}
}
}

View File

@@ -11,7 +11,11 @@ using System;
namespace BinaryObjectScanner.Protection
{
/// <summary>
/// This is a placeholder for all Macrovision-based protections. See partial classes for more details
/// Macrovision was a company that specialized in various forms of DRM. They had an extensive product line, their most infamous product (within this context) being SafeDisc.
/// Due to there being a significant amount of backend tech being shared between various protections, a separate class is needed for generic Macrovision detections.
///
/// Macrovision Corporation CD-ROM Unauthorized Copying Study: https://web.archive.org/web/20011005161810/http://www.macrovision.com/solutions/software/cdrom/images/Games_CD-ROM_Study.PDF
/// List of trademarks associated with Marovision: https://tmsearch.uspto.gov/bin/showfield?f=toc&state=4804%3Au8wykd.5.1&p_search=searchss&p_L=50&BackReference=&p_plural=yes&p_s_PARA1=&p_tagrepl%7E%3A=PARA1%24LD&expr=PARA1+AND+PARA2&p_s_PARA2=macrovision&p_tagrepl%7E%3A=PARA2%24ALL&p_op_ALL=AND&a_default=search&a_search=Submit+Query&a_search=Submit+Query
/// </summary>
public partial class Macrovision : IPathCheck, INewExecutableCheck, IPortableExecutableCheck
{
@@ -48,36 +52,82 @@ namespace BinaryObjectScanner.Protection
if (sections == null)
return null;
// Check for specific indications for individual Macrovision protections.
List<string> resultsList = new List<string>();
// Check for generic indications of Macrovision protections first.
string name = pex.FileDescription;
// Present in "secdrv.sys" files found in SafeDisc 2.80.010+.
if (name?.Equals("Macrovision SECURITY Driver", StringComparison.OrdinalIgnoreCase) == true)
resultsList.Add($"Macrovision Security Driver {GetSecDrvExecutableVersion(pex)}");
// Found in hidden resource of "32bit\Tax02\cdac14ba.dll" in IA item "TurboTax Deluxe Tax Year 2002 for Wndows (2.00R)(Intuit)(2002)(352282)".
// TODO: Fix File Description not getting properly pulled for this executable.
// Known versions:
// 4.16.050 Windows NT 2002/04/24
if (name?.Equals("Macrovision RTS Service", StringComparison.OrdinalIgnoreCase) == true)
return $"Macrovision RTS Service {pex.FileVersion}";
resultsList.Add($"Macrovision RTS Service {pex.FileVersion}");
// Check for specific indications for individual Macrovision protections.
List<string> resultsList = new List<string>();
// Check the header padding
string match = CheckSectionForProtection(file, includeDebug, pex.HeaderPaddingStrings, pex.HeaderPaddingData);
if (!string.IsNullOrWhiteSpace(match))
// The stxt371 and stxt774 sections are found in various newer Macrovision products, including various versions of CDS-300, SafeCast, and SafeDisc.
// They may indicate SafeWrap, but this hasn't been confirmed yet.
bool stxt371Section = pex.ContainsSection("stxt371", exact: true);
bool stxt774Section = pex.ContainsSection("stxt774", exact: true);
if (stxt371Section || stxt774Section)
{
resultsList.Add(match);
// Check the header padding for protected sections.
string sectionMatch = CheckSectionForProtection(file, includeDebug, pex.HeaderPaddingStrings, pex.HeaderPaddingData, true);
if (!string.IsNullOrWhiteSpace(sectionMatch))
{
resultsList.Add(sectionMatch);
}
else
{
// Get the .data section, if it exists, for protected sections.
sectionMatch = CheckSectionForProtection(file, includeDebug, pex.GetFirstSectionStrings(".data"), pex.GetFirstSectionData(".data"), true);
if (!string.IsNullOrWhiteSpace(sectionMatch))
resultsList.Add(sectionMatch);
}
int entryPointIndex = pex.FindEntryPointSectionIndex();
string entryPointSectionName = pex.SectionNames[entryPointIndex];
switch (entryPointSectionName)
{
// Check if the entry point is in the expected section for normal protected executables.
// If it isn't, the executable has likely been cracked to remove the protection, or has been corrupted or tampered with and is no longer functional.
case "stxt371":
resultsList.Add("Macrovision Protected Application");
break;
// It isn't known if this section ever contains the entry point, so if that does happen, it's worth investigating.
case "stxt774":
resultsList.Add("Macrovision Protected Application (Report this to us on GitHub)");
break;
default:
resultsList.Add("Macrovision Protected Application (Entry point not present in the stxt371 section. Executable is either unprotected or nonfunctional)");
break;
}
}
// If the file doesn't have the stxt* sections, check if any sections are protected assuming it's an older Macrovision product.
else
{
// Get the .data section, if it exists
match = CheckSectionForProtection(file, includeDebug, pex.GetFirstSectionStrings(".data"), pex.GetFirstSectionData(".data"));
if (!string.IsNullOrWhiteSpace(match))
resultsList.Add(match);
// Check the header padding for protected sections.
string sectionMatch = CheckSectionForProtection(file, includeDebug, pex.HeaderPaddingStrings, pex.HeaderPaddingData, false);
if (!string.IsNullOrWhiteSpace(sectionMatch))
{
resultsList.Add(sectionMatch);
}
else
{
// Check the .data section, if it exists, for protected sections.
sectionMatch = CheckSectionForProtection(file, includeDebug, pex.GetFirstSectionStrings(".data"), pex.GetFirstSectionData(".data"), false);
if (!string.IsNullOrWhiteSpace(sectionMatch))
resultsList.Add(sectionMatch);
}
}
// Run Cactus Data Shield PE checks
match = CactusDataShieldCheckPortableExecutable(file, pex, includeDebug);
string match = CactusDataShieldCheckPortableExecutable(file, pex, includeDebug);
if (!string.IsNullOrWhiteSpace(match))
resultsList.Add(match);
@@ -187,6 +237,7 @@ namespace BinaryObjectScanner.Protection
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("00000001.TMP", useEndsWith: true), Get00000001TMPVersion, string.Empty),
new PathMatchSet(new PathMatch($"{Path.DirectorySeparatorChar}secdrv.sys", useEndsWith: true), GetSecdrvFileSizeVersion, "Macrovision Security Driver"),
};
return MatchUtil.GetAllMatches(files, matchers, any: false);
@@ -198,6 +249,7 @@ namespace BinaryObjectScanner.Protection
var matchers = new List<PathMatchSet>
{
new PathMatchSet(new PathMatch("00000001.TMP", useEndsWith: true), Get00000001TMPVersion, string.Empty),
new PathMatchSet(new PathMatch($"{Path.DirectorySeparatorChar}secdrv.sys", useEndsWith: true), GetSecdrvFileSizeVersion, "Macrovision Security Driver"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
@@ -228,16 +280,139 @@ namespace BinaryObjectScanner.Protection
}
}
private string CheckSectionForProtection(string file, bool includeDebug, List<string> sectionStrings, byte[] sectionRaw)
// TODO: Verify these checks and remove any that may not be needed, file version checks should remove the need for any checks for 2.80+.
internal static string GetSecdrvFileSizeVersion(string firstMatchedString, IEnumerable<string> files)
{
if (string.IsNullOrEmpty(firstMatchedString) || !File.Exists(firstMatchedString))
return string.Empty;
FileInfo fi = new FileInfo(firstMatchedString);
switch (fi.Length)
{
// Found in Redump entry 102979.
case 1:
return "(Empty File)";
// Found in Redump entries 9718, 12885, 21154, 31149, 37523, 37920.
case 14_304:
return "/ SafeDisc 1.06.000-1.20.001";
// Found in Redump entries 9617 and 31526.
case 14_368:
return "/ SafeDisc 1.30.010-1.35.000";
// Found in Redump entries 2595, 37832, and 44350.
case 10_848:
return "/ SafeDisc 1.40.004-1.41.001";
// Found in Redump entries 30555 and 55078.
case 11_968:
return "/ SafeDisc 1.45.011";
// Found in Redump entries 28810 and 62935.
case 11_616:
return "/ SafeDisc 1.50.020";
// Found in Redump entries 72195 and 73502.
case 18_768:
return "/ SafeDisc 2.05.030";
// Found in Redump entries 38541 and 59462.
case 20_128:
return "/ SafeDisc 2.10.030";
// Found in Redump entries 9819, 15312, 55823.
case 27_440:
return "/ SafeDisc 2.30.030-2.30.033";
// Found in Redump entries 9846 and 23786.
case 28_624:
return "/ SafeDisc 2.40.010-2.40.011";
// Found in Redump entries 30022 and 31666.
case 28_400:
return "/ SafeDisc 2.51.020-2.51.021";
// Found in Redump entries 2064 and 47047.
case 29_392:
return "/ SafeDisc 2.60.052";
// Found in Redump entries 13048 and 48101.
case 11_376:
return "/ SafeDisc 2.70.030-2.72.000";
// Found in Redump entries 32783 and 39273.
case 12_464:
return "3.17.000 / SafeDisc 2.80.010-2.80.011";
// Found in Redump entries 11638 and 52606.
case 12_400:
return "3.18.000 / SafeDisc 2.90.010-2.90.040";
// Found in Redump entries 13230, 15383, and 36511.
case 12_528:
return "3.19.000 / SafeDisc 3.10.020-3.15.011";
// Found in Redump entries 58625 and 84586.
case 11_973:
return "3.22.000 / SafeDisc 3.20.020-3.20.022";
// Found in Redump entries 15614, 42034, 45686, 56320, 60021, 79729, and 80776.
case 163_644:
return "4.00.060 / SafeDisc 4.00.000-4.70.000";
// Found distributed online, but so far not in a game release. TODO: Discover original source.
// Can be found at https://github.com/ericwj/PsSecDrv/blob/master/tools/SECDRV/SECDRV.sys, and the file is confirmed to be distributed officialy by Microsoft: https://www.virustotal.com/gui/file/34bbb0459c96b3de94ccb0d73461562935c583d7bf93828da4e20a6bc9b7301d/.
case 23_040:
return "4.03.086 / Product Unknown";
// Found in https://web.archive.org/web/20010417215205/http://www.macrovision.com:80/demos/Trialware.exe.
case 10_784:
return "/ SafeCast ESD 2.02.040";
// This file is not currently known to be used in versions past 4.70.000.
default:
return "/ Product Unknown (Report this to us on GitHub)";
}
}
// TODO: Combine with filesize version checks if possible.
private string GetSecDrvExecutableVersion(PortableExecutable pex)
{
// 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.
string version = pex.FileVersion;
if (!string.IsNullOrEmpty(version))
{
switch (version)
{
// Found to be in Redump entry 32783.
// The product version is "3.17.000 Windows NT 2002/07/01".
case "3.17.000":
return "3.17.000 / SafeDisc 2.80.010-2.80.011";
// Found to be in Redump entry 52606.
// The product version is "3.18.000 Windows NT 2002/11/14".
case "3.18.000":
return "3.18.000 / SafeDisc 2.90.010-2.90.040";
// Found to be in Redump entry 13230.
// The product version is "3.19.000 Windows NT/2K/XP 2003/03/19".
case "3.19.000":
return "3.19.000 / SafeDisc 3.10.020-3.15.011";
// Found to be in Redump entry 58625.
// The product version is "SECURITY Driver 3.22.000 2004/01/16".
case "3.22.000":
return "3.22.000 / SafeDisc 3.20.020-3.20.022";
// Found to be in Redump entry 15614.
// The product version is "SECURITY Driver 4.00.060 2004/08/31".
case "4.00.060":
return "4.00.060 / SafeDisc 4.00.000-4.70.000";
// Found distributed online, but so far not in a game release. TODO: Discover original source.
// Can be found at https://github.com/ericwj/PsSecDrv/blob/master/tools/SECDRV/SECDRV.sys, and the file is confirmed to be distributed officialy by Microsoft: https://www.virustotal.com/gui/file/34bbb0459c96b3de94ccb0d73461562935c583d7bf93828da4e20a6bc9b7301d/.
// The product version is "SECURITY Driver 4.03.086 2006/09/13".
case "4.03.086":
return "4.03.086 / Unknown SafeDisc version";
default:
return $"Unknown Version {version} (Report this to us on GitHub)";
}
}
return "Unknown Version (Report this to us on GitHub)";
}
private string CheckSectionForProtection(string file, bool includeDebug, List<string> sectionStrings, byte[] sectionRaw, bool newVersion)
{
// Get the section strings, if they exist
if (sectionStrings == null)
return null;
// If we don't have the "BoG_" string
if (!sectionStrings.Any(s => s.Contains("BoG_ *90.0&!! Yy>")))
// 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<ContentMatchSet>
{
@@ -255,8 +430,8 @@ namespace BinaryObjectScanner.Protection
internal static string GetMacrovisionVersion(string file, byte[] fileContent, List<int> positions)
{
// Begin reading after "BoG_ *90.0&!! Yy>" for older versions
int index = positions[0] + 20;
// Begin reading 2 bytes after "BoG_ *90.0&!! Yy>" for older versions
int index = positions[0] + 18 + 2;
int version = fileContent.ReadInt32(ref index);
int subVersion = fileContent.ReadInt32(ref index);
int subsubVersion = fileContent.ReadInt32(ref index);
@@ -267,8 +442,8 @@ namespace BinaryObjectScanner.Protection
return $"{MacrovisionVersionToProductName(versionString)} {versionString}";
}
// Begin reading after "BoG_ *90.0&!! Yy>" for newer versions
index = positions[0] + 18 + 14; // Begin reading after "BoG_ *90.0&!! Yy>" for newer SafeDisc
// Begin reading 14 bytes after "BoG_ *90.0&!! Yy>" for newer versions
index = positions[0] + 18 + 14;
version = fileContent.ReadInt32(ref index);
subVersion = fileContent.ReadInt32(ref index);
subsubVersion = fileContent.ReadInt32(ref index);
@@ -286,19 +461,30 @@ namespace BinaryObjectScanner.Protection
{
switch (version)
{
// CDS-300 (Confirmed)
case "2.90.044": // Found in "American Made World Played" by Les Paul & Friends (Japan) (https://www.discogs.com/release/18934432-Les-Paul-Friends-American-Made-World-Played) and "X&Y" by Coldplay (Japan) (https://www.discogs.com/release/822378-Coldplay-XY).
return "CDS-300";
// SafeCast (Confirmed)
// Version 1.04.000/1.4.0.0 can be found in "cdac01aa.dll" and "cdac01ba.dll" from IA item "ejay_nestle_trial", but needs further research.
case "2.11.010": // Found in Redump entry 83145.
case "2.11.060": // Found in Redump entry 102979.
case "2.16.050": // Found in IA items "cdrom-turbotax-2002", "TurboTax_Deluxe_Tax_Year_2002_for_Wndows_2.00R_Intuit_2002_352282", and "TurboTax_Premier_Tax_Year_2002_for_Windows_v02.00Z-R_Intuit_352283_2002".
case "2.60.030": // Found in Redump entry 74384 (Semi-confirmed) and "Data Becker Web To Date v3.1" according to https://web.archive.org/web/20210331144912/https://protectionid.net/ (Unconfirmed).
case "2.67.010": // Found in "[Win] Photoshop CS2.7z" in IA item "Adobe-CS2".
return "SafeCast";
// SafeCast (Unconfirmed)
case "2.41.000": // Found in Adobe Photoshop according to http://www.reversing.be/article.php?story=2006102413541932
case "2.42.000": // Found in "Dreamweaver MX 2004 v7.0.1" according to https://web.archive.org/web/20210331144912/https://protectionid.net/.
case "2.50.030": // Found in "ArcSoft Media Card Companion v1.0" according to https://web.archive.org/web/20210331144912/https://protectionid.net/.
case "2.51.000": // Found in "Autodesk Inventor Professional v9.0" according to https://web.archive.org/web/20210331144912/https://protectionid.net/.
case "2.67.010": // Found in "Adobe Photoshop CS2" according to https://web.archive.org/web/20210331144912/https://protectionid.net/.
return "SafeCast (Unconfirmed - Please report to us on GitHub)";
// SafeCast ESD (Confirmed)
case "2.02.040": // Found in https://web.archive.org/web/20010417215205/http://www.macrovision.com:80/demos/Trialware.exe.
return "SafeCast ESD";
// SafeDisc (Confirmed)
case "1.00.025": // Found in Redump entry 66005.
case "1.00.026": // Found in Redump entries 1882 and 30049.
@@ -361,6 +547,10 @@ namespace BinaryObjectScanner.Protection
case "1.01.045": // Currently only found in a pirate compilation disc: IA item "cdrom-classic-fond-58".
return "SafeDisc (Unconfirmed - Please report to us on GitHub)";
// SafeDisc Lite (Confirmed)
case "2.60.020": // Found in Redump entry 14928.
return "SafeDisc Lite";
default:
return "Macrovision Protected Application (Generic detection - Report to us on GitHub)";
}
@@ -372,45 +562,6 @@ namespace BinaryObjectScanner.Protection
if (resultsList == null || resultsList.Count == 0)
return resultsList;
// Cache the version expunged string
string versionExpunged = GetSafeDisc320to4xVersion(null, null, null);
// Clean SafeCast results
if (resultsList.Any(s => s == "SafeCast") && resultsList.Any(s => s.StartsWith("Macrovision Protected Application")))
{
resultsList = resultsList.Select(s =>
{
if (s.StartsWith("Macrovision Protected Application"))
return s.Replace("Macrovision Protected Application", "SafeCast");
else if (s == "SafeCast" || s.EndsWith(versionExpunged))
return null;
else
return s;
})
.Where(s => s != null)
.ToList();
}
// Clean SafeDisc results
if (resultsList.Any(s => s == "SafeDisc") && resultsList.Any(s => s.StartsWith("Macrovision Protected Application")))
{
resultsList = resultsList.Select(s =>
{
if (s.StartsWith("Macrovision Protected Application"))
return s.Replace("Macrovision Protected Application", "SafeDisc");
else if (s == "SafeDisc" || s.EndsWith(versionExpunged))
return null;
else
return s;
})
.Where(s => s != null)
.ToList();
}
// Clean incorrect version expunged results
if (resultsList.Any(s => s.StartsWith("Macrovision Protected Application")) && resultsList.Any(s => s.EndsWith(versionExpunged)))
resultsList = resultsList.Where(s => !s.EndsWith(versionExpunged)).ToList();
// Get distinct and order
return resultsList.Distinct().OrderBy(s => s).ToList();
}