2022-10-26 20:38:12 -07:00
using System ;
2023-03-07 11:31:55 -05:00
using System.Collections.Concurrent ;
2022-10-26 20:38:12 -07:00
using System.Collections.Generic ;
2023-03-07 11:31:55 -05:00
using System.IO ;
2023-03-07 11:28:02 -05:00
using System.Linq ;
2023-03-07 11:31:55 -05:00
using System.Text ;
2023-03-07 16:59:14 -05:00
using BinaryObjectScanner.Matching ;
using BinaryObjectScanner.Wrappers ;
2022-10-26 20:38:12 -07:00
2023-03-09 23:19:27 -05:00
namespace BinaryObjectScanner.Protection
2022-10-26 20:38:12 -07:00
{
/// <summary>
2022-10-27 17:40:16 -06:00
/// CactusDataShield was a copy protection originally developed by Midbar Technologies, which was then purchased by Macrovision in 2002 (https://variety.com/2002/digital/news/macrovision-acquires-midbar-cuts-ttr-link-1117875824/).
/// Macrovision's product page for CDS: https://web.archive.org/web/20050215235405/http://www.macrovision.com/products/cds/index.shtml
/// CDS-100 appears to function by attempting to prevent dumping/ripping the discs protected with it.
/// CDS-200+ uses a dedicated audio player to play the music "legitimately".
/// Patent relating to CDS-100: https://patents.google.com/patent/US6425098B1/
/// Known CDS versions:
/// CDS-100 ("The Loveparade Compilation 2001" by various artists (Barcode 74321 86986 2) (Likely Discogs Release Code [r155963]) and "World Of Our Own" (Limited Edition) by Westlife (Barcode 7 43218 98572 0) (Discogs Release Code [r1357706])).
/// CDS-200 (PlayJ) (("Volumia!" by Puur (Barcode 7 43218 63282 2) (Discogs Release Code [r795427])) (Confirmed to be CDS-200 from https://www.cdrinfo.com/d7/content/cactus-data-shield-200?page=2).
/// CDS200.0.4 - 3.0 build 16a (Redump entry 95036)
/// CDS200.0.4 - 3.0 build 16c ("TMF Hitzone 20" by various artists (Barcode 7 31458 37062 8)).
/// CDS200.0.4 - 4.1 build 2a ("Ich Habe Einen Traum" by Uwe Busse (Barcode 9 002723 251203)).
/// CDS200.0.4 - 4.1 build 2e ("Hallucinations" by David Usher (Barcode 7 24359 30322 2)).
/// CDS200.5.11.90 - 5.10.090 ("Finn 5 Fel!" by Gyllene Tider (Barcode 7 24357 10922 2)).
/// CDS-300
/// Further information:
/// https://www.cdrinfo.com/d7/content/cactus-data-shield-200
/// https://www.cdmediaworld.com/hardware/cdrom/cd_protections_cactus_data_shield.shtml
2022-10-26 20:38:12 -07:00
/// </summary>
public partial class Macrovision
{
2023-03-09 11:52:28 -05:00
/// <inheritdoc cref="BinaryObjectScanner.Interfaces.IPortableExecutableCheck.CheckPortableExecutable(string, PortableExecutable, bool)"/>
2023-03-07 11:28:02 -05:00
internal string CactusDataShieldCheckPortableExecutable ( string file , PortableExecutable pex , bool includeDebug )
{
// Get the sections from the executable, if possible
var sections = pex ? . SectionTable ;
if ( sections = = null )
return null ;
// Get the .data/DATA section strings, if they exist
List < string > strs = pex . GetFirstSectionStrings ( ".data" ) ? ? pex . GetFirstSectionStrings ( "DATA" ) ;
if ( strs ! = null )
{
if ( strs . Any ( s = > s . Contains ( "\\*.CDS" ) ) )
return "Cactus Data Shield 200" ;
if ( strs . Any ( s = > s . Contains ( "DATA.CDS" ) ) )
return "Cactus Data Shield 200" ;
}
// Found in "Volumia!" by Puur (Barcode 7 43218 63282 2) (Discogs Release Code [r795427]).
// Modified version of the PlayJ Music Player specificaly for CDS, as indicated by the About page present when running the executable.
var resources = pex . FindGenericResource ( "CactusPJ" ) ;
if ( resources . Any ( ) )
return "PlayJ Music Player (Cactus Data Shield 200)" ;
2023-03-08 15:21:21 -05:00
// Found in various files in "Les Paul & Friends" (Barcode 4 98806 834170).
string name = pex . ProductName ;
if ( name ? . Equals ( "CDS300" , StringComparison . OrdinalIgnoreCase ) = = true )
return $"Cactus Data Shield 300" ;
2023-03-07 11:28:02 -05:00
return null ;
}
2023-03-07 11:31:55 -05:00
2023-03-09 11:52:28 -05:00
/// <inheritdoc cref="BinaryObjectScanner.Interfaces.IPathCheck.CheckDirectoryPath(string, IEnumerable{string})"/>
2023-03-07 11:31:55 -05:00
internal ConcurrentQueue < string > CactusDataShieldCheckDirectoryPath ( string path , IEnumerable < string > files )
{
// TODO: Verify if these are OR or AND
var matchers = new List < PathMatchSet >
{
// Found in "Volumia!" by Puur (Barcode 7 43218 63282 2) (Discogs Release Code [r795427]).
// Modified version of the PlayJ Music Player specificaly for CDS, as indicated by the About page present when running the executable.
// The file "DATA16.BML" is also present on this disc but the name is too generic to check for.
new PathMatchSet ( new PathMatch ( "CACTUSPJ.exe" , useEndsWith : true ) , "PlayJ Music Player (Cactus Data Shield 200)" ) ,
// Found in "Volumia!" by Puur (Barcode 7 43218 63282 2) (Discogs Release Code [r795427]).
// In "Volumina! - Puur" (7 43218 63282 2), this file is composed of multiple PLJ files combined together.
// In later versions, this file is a padded dummy file. ("Ich Habe Einen Traum" by Uwe Busse (Barcode 9 002723 251203)).
new PathMatchSet ( new PathMatch ( "YUCCA.CDS" , useEndsWith : true ) , "Cactus Data Shield 200" ) ,
// TODO: Find samples of the following:
new PathMatchSet ( new PathMatch ( "CDSPlayer.app" , useEndsWith : true ) , GetCactusDataShieldVersion , "Cactus Data Shield" ) ,
new PathMatchSet ( new PathMatch ( "wmmp.exe" , useEndsWith : true ) , GetCactusDataShieldVersion , "Cactus Data Shield" ) ,
// The file "00000001.TMP" (with a filesize of 2,048 bytes) can be found in CDS-300, as well as SafeDisc.
// Due to this file being used in both protections, this file is detected within the general Macrovision checks.
} ;
return MatchUtil . GetAllMatches ( files , matchers , any : false ) ;
}
2023-03-09 11:52:28 -05:00
/// <inheritdoc cref="BinaryObjectScanner.Interfaces.IPathCheck.CheckFilePath(string)"/>
2023-03-07 11:31:55 -05:00
internal string CactusDataShieldCheckFilePath ( string path )
{
var matchers = new List < PathMatchSet >
{
// Found in "Volumia!" by Puur (Barcode 7 43218 63282 2) (Discogs Release Code [r795427]).
// Modified version of the PlayJ Music Player specificaly for CDS, as indicated by the About page present when running the executable.
// The file "DATA16.BML" is also present on this disc but the name is too generic to check for.
new PathMatchSet ( new PathMatch ( "CACTUSPJ.exe" , useEndsWith : true ) , "PlayJ Music Player (Cactus Data Shield 200)" ) ,
// Found in "Volumia!" by Puur (Barcode 7 43218 63282 2) (Discogs Release Code [r795427]),
// In "Volumia! - Puur", this file is composed of multiple PLJ files combined together.
// In later versions, this file is a padded dummy file. ("Ich Habe Einen Traum" by Uwe Busse (Barcode 9 002723 251203)).
new PathMatchSet ( new PathMatch ( "YUCCA.CDS" , useEndsWith : true ) , "Cactus Data Shield 200" ) ,
// TODO: Find samples of the following:
new PathMatchSet ( new PathMatch ( "CDSPlayer.app" , useEndsWith : true ) , "Cactus Data Shield 200" ) ,
new PathMatchSet ( new PathMatch ( "wmmp.exe" , useEndsWith : true ) , "Cactus Data Shield 200" ) ,
// The file "00000001.TMP" (with a filesize of 2,048 bytes) can be found in CDS-300, as well as SafeDisc.
// Due to this file being used in both protections, this file is detected within the general Macrovision checks.
} ;
return MatchUtil . GetFirstMatch ( path , matchers , any : true ) ;
}
public static string GetCactusDataShieldVersion ( string firstMatchedString , IEnumerable < string > files )
{
// Find the version.txt file first
string versionPath = files . FirstOrDefault ( f = > Path . GetFileName ( f ) . Equals ( "version.txt" , StringComparison . OrdinalIgnoreCase ) ) ;
if ( ! string . IsNullOrWhiteSpace ( versionPath ) )
{
string version = GetCactusDataShieldInternalVersion ( versionPath ) ;
if ( ! string . IsNullOrWhiteSpace ( version ) )
return version ;
}
return "200" ;
}
private static string GetCactusDataShieldInternalVersion ( string path )
{
if ( ! File . Exists ( path ) )
return null ;
try
{
using ( var sr = new StreamReader ( path , Encoding . Default ) )
{
return $"{sr.ReadLine().Substring(3)} ({sr.ReadLine()})" ;
}
}
catch
{
return null ;
}
}
2022-10-26 20:38:12 -07:00
}
}