2023-08-28 13:09:25 -06:00
using System ;
using System.Collections.Concurrent ;
using System.Collections.Generic ;
using System.Linq ;
using BinaryObjectScanner.Interfaces ;
2023-09-16 22:08:18 -04:00
using SabreTools.Matching ;
2023-09-16 02:04:47 -04:00
using SabreTools.Serialization.Wrappers ;
2023-08-28 13:09:25 -06:00
namespace BinaryObjectScanner.Protection
{
/// <summary>
/// Engine32 is the presumed name of a specific disc check DRM. This disc check merely checks for the presence of a specifically named file on the disc.
/// The file "engine32.dll" is always present (hence the name), and is where the disc checking logic is present.
2023-09-10 23:26:32 -04:00
/// <see href="https://github.com/TheRogueArchivist/DRML/blob/main/entries/engine32/engine32.md"/>
2023-08-28 13:09:25 -06:00
/// </summary>
public class Engine32 : IPathCheck , IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable ( string file , PortableExecutable pex , bool includeDebug )
{
// Get the sections from the executable, if possible
2023-09-15 22:21:05 -04:00
var sections = pex ? . Model . SectionTable ;
2023-08-28 13:09:25 -06:00
if ( sections = = null )
return null ;
// Most every tested sample of "engine32.dll" has a product name of "engine32", and the file description typically follows the naming pattern of "[Game Name] DLL-helper".
// Detects Engine32 within the game executables that contain it.
2023-09-15 22:21:05 -04:00
if ( pex . Model . ImportTable ? . ImportDirectoryTable ! = null & & pex . Model . ImportTable ? . HintNameTable ! = null )
2023-08-28 13:09:25 -06:00
{
2023-09-15 22:21:05 -04:00
bool importDirectoryTableMatch = pex . Model . ImportTable . ImportDirectoryTable . Any ( idte = > idte . Name ? . Equals ( "ENGINE32.DLL" , StringComparison . OrdinalIgnoreCase ) = = true ) ;
bool hintNameTableMatch = pex . Model . ImportTable ? . HintNameTable . Any ( ihne = > ihne . Name = = "InitEngine" ) ? ? false ;
2023-08-28 13:09:25 -06:00
// The Hint/Name Table Entry "DeinitEngine" is present in every tested sample, aside from TOCA Race Driver 2 (Redump entries 104593-104596).
if ( hintNameTableMatch & & importDirectoryTableMatch )
return "Engine32" ;
}
// Detects Engine32 within the file "engine32.dll".
2023-09-15 22:21:05 -04:00
if ( pex . Model . ExportTable ? . ExportNameTable ? . Strings ! = null )
2023-08-28 13:09:25 -06:00
{
2023-09-15 22:21:05 -04:00
bool exportNameTableMatch1 = pex . Model . ExportTable . ExportNameTable . Strings . Any ( s = > s = = "engine32.dll" ) ;
bool exportNameTableMatch2 = pex . Model . ExportTable . ExportNameTable . Strings . Any ( s = > s = = "DeinitEngine" ) ;
2023-08-28 13:09:25 -06:00
if ( exportNameTableMatch1 & & exportNameTableMatch2 )
return "Engine32" ;
}
return null ;
}
/// <inheritdoc/>
public ConcurrentQueue < string > CheckDirectoryPath ( string path , IEnumerable < string > files )
{
var matchers = new List < PathMatchSet >
{
// The file "engine32.dll" is present in every known instance of this DRM, but isn't being checked for currently due to the generic file name.
} ;
return MatchUtil . GetAllMatches ( files , matchers , any : true ) ;
}
/// <inheritdoc/>
public string CheckFilePath ( string path )
{
var matchers = new List < PathMatchSet >
{
// The file "engine32.dll" is present in every known instance of this DRM, but isn't being checked for currently due to the generic file name.
} ;
return MatchUtil . GetFirstMatch ( path , matchers , any : true ) ;
}
}
}