2019-09-27 23:52:24 -07:00
using System ;
2021-07-18 09:44:23 -07:00
using System.Collections.Concurrent ;
2019-09-27 23:52:24 -07:00
using System.Collections.Generic ;
using System.Linq ;
2021-09-05 23:02:55 -07:00
using System.Text ;
using BurnOutSharp.ExecutableType.Microsoft ;
2021-03-22 11:13:14 -07:00
using BurnOutSharp.Matching ;
2021-08-25 15:09:42 -07:00
using BurnOutSharp.Tools ;
2019-09-27 23:52:24 -07:00
namespace BurnOutSharp.ProtectionType
{
2021-09-05 23:02:55 -07:00
// TODO: Not matching all SolidShield Wrapper v1 (See JackKeane)
// TODO: Not matching all SolidShield Wrapper v1 (See NFS11)
2021-02-26 01:26:49 -08:00
public class SolidShield : IContentCheck , IPathCheck
2019-09-27 23:52:24 -07:00
{
2021-04-01 15:00:22 -07:00
/// <summary>
/// Set of all PathMatchSets for this protection
/// </summary>
private static readonly List < PathMatchSet > pathMatchers = new List < PathMatchSet >
{
new PathMatchSet ( new PathMatch ( "dvm.dll" , useEndsWith : true ) , "SolidShield" ) ,
new PathMatchSet ( new PathMatch ( "hc.dll" , useEndsWith : true ) , "SolidShield" ) ,
new PathMatchSet ( new PathMatch ( "solidshield-cd.dll" , useEndsWith : true ) , "SolidShield" ) ,
new PathMatchSet ( new PathMatch ( "c11prot.dll" , useEndsWith : true ) , "SolidShield" ) ,
} ;
2021-03-23 09:52:09 -07:00
/// <inheritdoc/>
2021-09-10 15:32:37 -07:00
private List < ContentMatchSet > GetContentMatchSets ( )
2021-03-23 09:52:09 -07:00
{
2021-09-05 23:02:55 -07:00
// TODO: Obtain a sample to find where this string is in a typical executable
2021-08-25 19:37:32 -07:00
return new List < ContentMatchSet >
2021-07-17 23:40:16 -07:00
{
// (char)0xAD + (char)0xDE + (char)0xFE + (char)0xCA
new ContentMatchSet ( new byte? [ ] { 0xAD , 0xDE , 0xFE , 0xCA } , GetVersionPlusTages , "SolidShield" ) ,
// 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 ContentMatchSet ( new byte? [ ]
{
0x42 , 0x00 , 0x49 , 0x00 , 0x4E , 0x00 , 0x07 , 0x00 ,
0x49 , 0x00 , 0x44 , 0x00 , 0x52 , 0x00 , 0x5F , 0x00 ,
0x53 , 0x00 , 0x47 , 0x00 , 0x54 , 0x00
2021-09-05 23:02:55 -07:00
} , "SolidShield [ContentMatchSet]" ) ,
2021-07-17 23:40:16 -07:00
} ;
2021-08-25 19:37:32 -07:00
}
2021-07-17 23:40:16 -07:00
2021-08-25 19:37:32 -07:00
/// <inheritdoc/>
2021-09-10 16:10:15 -07:00
public string CheckContents ( string file , byte [ ] fileContent , bool includeDebug , PortableExecutable pex , NewExecutable nex )
2021-09-05 23:02:55 -07:00
{
2021-09-10 13:51:32 -07:00
// Get the sections from the executable, if possible
var sections = pex ? . SectionTable ;
if ( sections = = null )
return null ;
2021-09-05 23:02:55 -07:00
2021-09-10 13:59:35 -07:00
string name = Utilities . GetFileDescription ( pex ) ;
2021-09-05 23:02:55 -07:00
if ( ! string . IsNullOrWhiteSpace ( name ) & & name . StartsWith ( "DVM Library" , StringComparison . OrdinalIgnoreCase ) )
2021-09-10 13:51:32 -07:00
return $"SolidShield {Utilities.GetFileVersion(pex)}" ;
2021-09-05 23:02:55 -07:00
else if ( ! string . IsNullOrWhiteSpace ( name ) & & name . StartsWith ( "Solidshield Activation Library" , StringComparison . OrdinalIgnoreCase ) )
2021-09-10 13:51:32 -07:00
return $"SolidShield Core.dll {Utilities.GetFileVersion(pex)}" ;
2021-09-05 23:02:55 -07:00
else if ( ! string . IsNullOrWhiteSpace ( name ) & & name . StartsWith ( "Activation Manager" , StringComparison . OrdinalIgnoreCase ) )
2021-09-10 13:51:32 -07:00
return $"SolidShield Activation Manager Module {GetFileVersion(pex)}" ;
2021-09-05 23:02:55 -07:00
2021-09-10 13:51:32 -07:00
name = Utilities . GetProductName ( pex ) ;
2021-09-05 23:02:55 -07:00
if ( ! string . IsNullOrWhiteSpace ( name ) & & name . StartsWith ( "Solidshield Activation Library" , StringComparison . OrdinalIgnoreCase ) )
2021-09-10 13:51:32 -07:00
return $"SolidShield Core.dll {Utilities.GetFileVersion(pex)}" ;
2021-09-05 23:02:55 -07:00
else if ( ! string . IsNullOrWhiteSpace ( name ) & & name . StartsWith ( "Solidshield Library" , StringComparison . OrdinalIgnoreCase ) )
2021-09-10 13:51:32 -07:00
return $"SolidShield Core.dll {Utilities.GetFileVersion(pex)}" ;
2021-09-05 23:02:55 -07:00
else if ( ! string . IsNullOrWhiteSpace ( name ) & & name . StartsWith ( "Activation Manager" , StringComparison . OrdinalIgnoreCase ) )
2021-09-10 13:51:32 -07:00
return $"SolidShield Activation Manager Module {GetFileVersion(pex)}" ;
2021-09-05 23:02:55 -07:00
2021-09-10 13:51:32 -07:00
// Get the .init section, if it exists
2021-09-05 23:02:55 -07:00
var initSection = sections . FirstOrDefault ( s = > Encoding . ASCII . GetString ( s . Name ) . StartsWith ( ".init" ) ) ;
if ( initSection ! = null )
{
int sectionAddr = ( int ) initSection . PointerToRawData ;
int sectionEnd = sectionAddr + ( int ) initSection . VirtualSize ;
var matchers = new List < ContentMatchSet >
{
// (char)0xEF + (char)0xBE + (char)0xAD + (char)0xDE
new ContentMatchSet (
new ContentMatch ( new byte? [ ] { 0xEF , 0xBE , 0xAD , 0xDE } , start : sectionAddr , end : sectionEnd ) ,
GetExeWrapperVersion , "SolidShield EXE Wrapper" ) ,
// dvm.dll
new ContentMatchSet (
new ContentMatch ( new byte? [ ] { 0x64 , 0x76 , 0x6D , 0x2E , 0x64 , 0x6C , 0x6C } , start : sectionAddr , end : sectionEnd ) ,
"SolidShield EXE Wrapper v1" ) ,
} ;
string match = MatchUtil . GetFirstMatch ( file , fileContent , matchers , includeDebug ) ;
if ( ! string . IsNullOrWhiteSpace ( match ) )
return match ;
}
// Search the last two available sections
for ( int i = sections . Length - 2 ; i < sections . Length ; i + + )
{
2021-09-10 16:10:15 -07:00
var nthSection = i < 0 ? null : sections [ i ] ;
2021-09-05 23:02:55 -07:00
if ( nthSection ! = null )
{
int sectionAddr = ( int ) nthSection . PointerToRawData ;
int sectionEnd = sectionAddr + ( int ) nthSection . VirtualSize ;
var matchers = new List < ContentMatchSet >
{
// Solidshield
new ContentMatchSet (
new ContentMatch ( new byte? [ ]
{
0x53 , 0x6F , 0x6C , 0x69 , 0x64 , 0x73 , 0x68 , 0x69 ,
0x65 , 0x6C , 0x64
} , start : sectionAddr , end : sectionEnd ) ,
GetVersion , "SolidShield EXE Wrapper" ) ,
} ;
string match = MatchUtil . GetFirstMatch ( file , fileContent , matchers , includeDebug ) ;
if ( ! string . IsNullOrWhiteSpace ( match ) )
return match ;
}
}
2021-09-10 15:32:37 -07:00
var contentMatchSets = GetContentMatchSets ( ) ;
if ( contentMatchSets ! = null & & contentMatchSets . Any ( ) )
return MatchUtil . GetFirstMatch ( file , fileContent , contentMatchSets , includeDebug ) ;
2021-09-05 23:02:55 -07:00
return null ;
}
2019-09-27 23:52:24 -07:00
2021-02-26 00:32:09 -08:00
/// <inheritdoc/>
2021-07-18 09:44:23 -07:00
public ConcurrentQueue < string > CheckDirectoryPath ( string path , IEnumerable < string > files )
2019-09-27 23:52:24 -07:00
{
2021-03-19 15:41:49 -07:00
// TODO: Verify if these are OR or AND
2021-04-01 15:00:22 -07:00
return MatchUtil . GetAllMatches ( files , pathMatchers , any : true ) ;
2021-03-19 15:41:49 -07:00
}
/// <inheritdoc/>
public string CheckFilePath ( string path )
{
2021-04-01 15:00:22 -07:00
return MatchUtil . GetFirstMatch ( path , pathMatchers , any : true ) ;
2019-09-27 23:52:24 -07:00
}
2021-03-22 11:43:51 -07:00
public static string GetExeWrapperVersion ( string file , byte [ ] fileContent , List < int > positions )
2021-03-22 11:13:14 -07:00
{
2021-04-01 15:00:22 -07:00
int position = positions [ 0 ] ;
var id1 = new ArraySegment < byte > ( fileContent , position + 5 , 3 ) ;
var id2 = new ArraySegment < byte > ( fileContent , position + 16 , 4 ) ;
2021-03-22 11:13:14 -07:00
if ( id1 . SequenceEqual ( new byte [ ] { 0x00 , 0x00 , 0x00 } ) & & id2 . SequenceEqual ( new byte [ ] { 0x00 , 0x10 , 0x00 , 0x00 } ) )
2021-09-05 23:02:55 -07:00
return "v1" ;
2021-04-01 15:00:22 -07:00
else if ( id1 . SequenceEqual ( new byte [ ] { 0x2E , 0x6F , 0x26 } ) & & id2 . SequenceEqual ( new byte [ ] { 0xDB , 0xC5 , 0x20 , 0x3A } ) ) // new byte[] { 0xDB, 0xC5, 0x20, 0x3A, 0xB9 }
2021-09-05 23:02:55 -07:00
return "v2" ; // TODO: Verify against other SolidShield 2 discs
2021-03-22 11:13:14 -07:00
return null ;
}
2021-03-22 11:43:51 -07:00
public static string GetVersion ( string file , byte [ ] fileContent , List < int > positions )
2019-09-27 23:52:24 -07:00
{
2021-03-22 11:43:51 -07:00
int index = positions [ 0 ] + 12 ; // Begin reading after "Solidshield"
2020-09-10 21:10:32 -07:00
char version = ( char ) fileContent [ index ] ;
index + + ;
index + + ;
char subVersion = ( char ) fileContent [ index ] ;
index + + ;
index + + ;
char subSubVersion = ( char ) fileContent [ index ] ;
index + + ;
index + + ;
char subSubSubVersion = ( char ) fileContent [ index ] ;
2021-09-05 23:02:55 -07:00
if ( ! char . IsNumber ( version ) )
return null ;
2020-09-10 21:10:32 -07:00
return $"{version}.{subVersion}.{subSubVersion}.{subSubSubVersion}" ;
2019-09-27 23:52:24 -07:00
}
2021-03-22 11:43:51 -07:00
public static string GetVersionPlusTages ( string file , byte [ ] fileContent , List < int > positions )
{
int position = positions [ 0 ] ;
var id1 = new ArraySegment < byte > ( fileContent , position + 4 , 3 ) ;
var id2 = new ArraySegment < byte > ( fileContent , position + 15 , 4 ) ;
if ( ( fileContent [ position + 3 ] = = 0x04 | | fileContent [ position + 3 ] = = 0x05 )
& & id1 . SequenceEqual ( new byte [ ] { 0x00 , 0x00 , 0x00 } )
& & id2 . SequenceEqual ( new byte [ ] { 0x00 , 0x10 , 0x00 , 0x00 } ) )
{
return "2 (SolidShield v2 EXE Wrapper)" ;
}
else if ( id1 . SequenceEqual ( new byte [ ] { 0x00 , 0x00 , 0x00 } )
& & id2 . SequenceEqual ( new byte [ ] { 0x00 , 0x00 , 0x00 , 0x00 } ) )
{
// "T" + (char)0x00 + "a" + (char)0x00 + "g" + (char)0x00 + "e" + (char)0x00 + "s" + (char)0x00 + "S" + (char)0x00 + "e" + (char)0x00 + "t" + (char)0x00 + "u" + (char)0x00 + "p" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + "0" + (char)0x00 + (char)0x8 + (char)0x00 + (char)0x1 + (char)0x0 + "F" + (char)0x00 + "i" + (char)0x00 + "l" + (char)0x00 + "e" + (char)0x00 + "V" + (char)0x00 + "e" + (char)0x00 + "r" + (char)0x00 + "s" + (char)0x00 + "i" + (char)0x00 + "o" + (char)0x00 + "n" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00
2021-04-01 15:00:22 -07:00
byte? [ ] check2 = new byte? [ ]
{
0x54 , 0x61 , 0x67 , 0x65 , 0x73 , 0x53 , 0x65 , 0x74 ,
0x75 , 0x70 , 0x30 , 0x08 , 0x01 , 0x00 , 0x46 , 0x69 ,
0x6C , 0x65 , 0x56 , 0x65 , 0x72 , 0x73 , 0x69 , 0x6F ,
0x6E , 0x00 , 0x00 , 0x00 , 0x00
} ;
2021-03-22 11:43:51 -07:00
if ( fileContent . FirstPosition ( check2 , out int position2 ) )
{
position2 - - ; // TODO: Verify this subtract
2021-03-22 11:44:16 -07:00
return $"2 + Tagès {fileContent[position2 + 0x38]}.{fileContent[position2 + 0x38 + 4]}.{fileContent[position2 + 0x38 + 8]}.{fileContent[position + 0x38 + 12]}" ;
2021-03-22 11:43:51 -07:00
}
else
{
return "2 (SolidShield v2 EXE Wrapper)" ;
}
}
return null ;
}
2021-09-10 13:51:32 -07:00
private static string GetFileVersion ( PortableExecutable pex )
{
string companyName = Utilities . GetCompanyName ( pex ) ? . ToLowerInvariant ( ) ;
if ( ! string . IsNullOrWhiteSpace ( companyName ) & & ( companyName . Contains ( "solidshield" ) | | companyName . Contains ( "tages" ) ) )
return Utilities . GetFileVersion ( pex ) ;
return null ;
}
2019-09-27 23:52:24 -07:00
}
}