Compare commits

...

47 Commits

Author SHA1 Message Date
Matt Nadareski
e5dc66b140 Bump version 2024-11-03 20:01:41 -05:00
HeroponRikiBestest
41e10a4150 Add aditional light directory checks (#335)
Compensate for some additional variance in directory names found from new samples, in lieu of a more "advanced" check
2024-11-02 19:42:00 -04:00
Matt Nadareski
3c4381049b Minor leftover cleanup 2024-10-31 23:11:11 -04:00
Matt Nadareski
3188c6e922 Further reduce awkward framework gating 2024-10-31 23:08:05 -04:00
Matt Nadareski
1bfb6cda08 Use CheckDictionary helper type 2024-10-31 22:52:20 -04:00
Matt Nadareski
86feb930a8 Add CheckDictionary (unused) 2024-10-31 22:49:57 -04:00
Matt Nadareski
5587c79ac5 Reduce use of generic PathMatch 2024-10-31 22:42:20 -04:00
Matt Nadareski
dc2a2e10de Add summary to ProtectionDictionary 2024-10-31 22:25:11 -04:00
Matt Nadareski
a2fdcb4f6f Remove remaining unncessary Concurrent usings 2024-10-31 22:22:52 -04:00
Matt Nadareski
a355670af9 Use semantic versioning for var names 2024-10-31 22:16:51 -04:00
Matt Nadareski
3489c67e2b Make CheckDirectoryPath signature easier 2024-10-31 22:15:30 -04:00
Matt Nadareski
99a64942ea Reduce per-framework complexity 2024-10-31 21:46:40 -04:00
Matt Nadareski
5eab12946f Fix accidental change 2024-10-31 21:13:09 -04:00
Matt Nadareski
683cfb6306 Start using ProtectionDictionary 2024-10-31 21:10:06 -04:00
Matt Nadareski
9a3fde0518 Add ProtectionDictionary type (unused) 2024-10-31 20:54:36 -04:00
Matt Nadareski
26d19aab37 Fix very strange formatting 2024-10-31 20:38:15 -04:00
Matt Nadareski
08564ed607 Remove end-of-program pauses 2024-10-31 20:36:40 -04:00
Matt Nadareski
0f6378cd2c Update packages 2024-10-31 16:05:11 -04:00
TheRogueArchivist
34a78fc4b9 Minor SafeCast additions (#333)
Adds a text check for SafeCast, along with adding a new confirmed version. Also add notes for a few known programs that used SafeCast, a few TODOs, and a semi-related note about stxt sections.
2024-10-30 07:28:21 -04:00
Matt Nadareski
c9ee45c1d2 Count not Count() 2024-10-27 20:24:24 -04:00
HeroponRikiBestest
13f5b4f79b Improve Copy-X Light detection with additional folder check. (#332)
* Improve Copy-X Light detection with additional folder check.

* Add requested changes to additional copy-X light folder check.

* Cleaned up changes.

* One final comment cleanup.
2024-10-27 20:20:19 -04:00
HeroponRikiBestest
e5d0c5bdc4 Replace tivola with copy-x. (#331) 2024-10-27 00:19:41 -04:00
Matt Nadareski
6220382531 Clarify switch expression use 2024-10-27 00:12:21 -04:00
Matt Nadareski
165896e335 Add note about first-person comments 2024-10-27 00:04:11 -04:00
Matt Nadareski
284d0ea108 Clear out old info from the coding guide 2024-10-27 00:01:22 -04:00
Matt Nadareski
b04feab5da Minor cleanup 2024-10-26 23:54:54 -04:00
HeroponRikiBestest
4e0442d526 Add preliminary copy-X protection checking (#328)
* Add preliminary copy-X protection checking

* Fixed formatting.

* Removed some unecessary lines of code.

* Added debatably sufficient documentation.

* Fixed formatting, hopefully

* Finalize formatting and PR.

* Fleshes out checks after more samples. Fixes some but not all of the change requests.

* Fix ordering.

* Fixes pex check, fixes redump id formatting.

* Added copy-X info to readme.

* Revert "Added copy-X info to readme."

This reverts commit 77349aa8de.

* Add copy-X info to readme, for real this time.

* Replaced some code in byte check with BoS helper function.

* Remove first person.

* Source is no longer just trust me (to some degree)

* Fix typo

* WIP figuring out enumerable (fails to build)

* WIP 2 figuring out getfirstmatch (compiles, but breaks detection)

* Pass 1 of suggested changes.

* Removed debug match.

* Pass 2 of suggested changes.

* Added line.

* Added line for real.

* Added todo

* Improved comments.

* Finished todo.

* Redid change.

* Fixes more comments.

* double double and make it trouble
2024-10-26 23:53:17 -04:00
TheRogueArchivist
d8aa4d230d Fix WTM false positive (#327)
"imp.dat" isn't exactly a very distinctive file name.
2024-10-26 20:31:25 -04:00
TheRogueArchivist
07a7fd05d2 Add new SafeCast version (#329) 2024-10-26 20:30:07 -04:00
Matt Nadareski
671e1ee2b6 Update Matching to 1.3.3 2024-10-26 19:46:34 -04:00
Matt Nadareski
d627e8a4c9 Be consistent with naming 2024-10-25 12:01:08 -04:00
Matt Nadareski
6ee90b28cd Be consistent with naming 2024-10-25 11:57:51 -04:00
Matt Nadareski
8dc2b019b6 Update packages 2024-10-24 17:32:26 -04:00
TheRogueArchivist
f151563e28 Move Armadillo to Protection and add notes (#326)
Armadillo has packer and protection features, meaning it should be move to be a protection. Also add additional notes, including about an alternate later name, "SoftwarePassport".
2024-10-23 00:38:53 -04:00
Matt Nadareski
edbbbb011d Renmae MediaMax CD-3 to be more accurate 2024-10-21 21:59:15 -04:00
TheRogueArchivist
e3fd44134b Add initial .NET Reactor support (#325)
* Add initial .NET Reactor support

It's minimal, but is much better than nothing. A few notes on how it can be realistically improved have been added as well.

* Fix missing using

* 7-zip SFX is extractable now
2024-10-04 23:56:52 -04:00
Matt Nadareski
71fb7318e3 Better handling of Windows libraries 2024-10-03 14:57:14 -04:00
Matt Nadareski
aba4395139 Enable Windows libraries on .NET Framework 4.0 2024-10-03 14:46:35 -04:00
Matt Nadareski
1fd69f101f Remove last two this qualifiers 2024-10-03 13:02:23 -04:00
Matt Nadareski
aa4c72fb90 Old .NET really doesn't like readonly 2024-10-03 12:55:38 -04:00
Matt Nadareski
150b9a0d67 Remove more this qualifiers 2024-10-03 12:53:43 -04:00
Matt Nadareski
b08921a94a Use readonly instead of private set 2024-10-03 12:52:27 -04:00
Matt Nadareski
3406f3c4b3 Remove this qualifiers 2024-10-03 12:51:49 -04:00
Matt Nadareski
ffca156209 Remove init variants :( 2024-10-03 12:51:30 -04:00
Matt Nadareski
b842599006 Update packages 2024-10-03 12:01:08 -04:00
TheRogueArchivist
86b639b04f Add Kalypso Launcher support (#324)
* Add Kalypso Launcher support

* Small changes to Kalypso Launcher

* More minor Kalypso Launcher changes
2024-10-03 10:42:39 -04:00
Matt Nadareski
570602aac6 Remove unused package 2024-10-01 10:45:12 -04:00
112 changed files with 1403 additions and 1875 deletions

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Assembly Properties -->
@@ -11,7 +11,7 @@
<Nullable>enable</Nullable>
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Version>3.1.14</Version>
<Version>3.1.15</Version>
<!-- Mostly added due to external libraries -->
<WarningsNotAsErrors>CS0162;CS0612;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8618;CS8625;CS8634;CS8765;IL3000;NU5100</WarningsNotAsErrors>
@@ -31,7 +31,7 @@
<DefineConstants>$(DefineConstants);WIN</DefineConstants>
</PropertyGroup>
<!-- Exclude certain parts of external modules for .NET Framework 4.5.2 and above -->
<!-- Exclude certain parts of external modules for by default -->
<PropertyGroup>
<DefaultItemExcludes>
$(DefaultItemExcludes);
@@ -44,8 +44,16 @@
</DefaultItemExcludes>
</PropertyGroup>
<!-- Exclude all external modules for .NET Framework 2.0, .NET Framework 3.5, .NET Framework 4.0 or non-Windows builds -->
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net40`)) OR !$(RuntimeIdentifier.StartsWith(`win-`))">
<!-- Exclude all StormLibSharp for .NET Framework 4.0 -->
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net40`))">
<DefaultItemExcludes>
$(DefaultItemExcludes);
_EXTERNAL\stormlibsharp\src\**
</DefaultItemExcludes>
</PropertyGroup>
<!-- Exclude all external modules for .NET Framework 2.0, .NET Framework 3.5, or non-Windows builds -->
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR !$(RuntimeIdentifier.StartsWith(`win-x86`))">
<DefaultItemExcludes>
$(DefaultItemExcludes);
_EXTERNAL\**
@@ -53,7 +61,7 @@
</PropertyGroup>
<!-- These are needed for dealing with native Windows DLLs -->
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND $(RuntimeIdentifier.StartsWith(`win-x86`))">
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND $(RuntimeIdentifier.StartsWith(`win-x86`))">
<Content Include="*.dll">
<Pack>true</Pack>
<PackagePath>contentFiles;content</PackagePath>
@@ -69,7 +77,6 @@
<!-- Support for old .NET versions -->
<ItemGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net40`))">
<PackageReference Include="MinThreadingBridge" Version="0.11.4" />
<PackageReference Include="MinTasksExtensionsBridge" Version="0.3.4" />
</ItemGroup>
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`))">
<PackageReference Include="OpenMcdf" Version="2.3.1" />
@@ -83,14 +90,14 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="SabreTools.Compression" Version="0.5.1" />
<PackageReference Include="SabreTools.Hashing" Version="1.2.0" />
<PackageReference Include="SabreTools.IO" Version="1.4.11" />
<PackageReference Include="SabreTools.Matching" Version="1.3.1" />
<PackageReference Include="SabreTools.Models" Version="1.4.8" />
<PackageReference Include="SabreTools.Serialization" Version="1.6.7" />
<PackageReference Include="UnshieldSharp" Version="1.8.3" />
<PackageReference Include="WiseUnpacker" Version="1.4.2" />
<PackageReference Include="SabreTools.Compression" Version="0.5.2" />
<PackageReference Include="SabreTools.Hashing" Version="1.2.2" />
<PackageReference Include="SabreTools.IO" Version="1.4.13" />
<PackageReference Include="SabreTools.Matching" Version="1.3.3" />
<PackageReference Include="SabreTools.Models" Version="1.4.11" />
<PackageReference Include="SabreTools.Serialization" Version="1.6.9" />
<PackageReference Include="UnshieldSharp" Version="1.8.5" />
<PackageReference Include="WiseUnpacker" Version="1.4.4" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,26 @@
namespace BinaryObjectScanner
{
/// <summary>
/// Represents a mapping from checker to detected protection
/// </summary>
#if NET20 || NET35
public class CheckDictionary<T> : System.Collections.Generic.Dictionary<T, string> where T : notnull
#else
public class CheckDictionary<T> : System.Collections.Concurrent.ConcurrentDictionary<T, string> where T : notnull
#endif
{
/// <inheritdoc cref="System.Collections.Generic.Dictionary{TKey, TValue}.Add(TKey, TValue)"/>
/// <remarks>Handles the proper Add implementation</remarks>
public void Append(T key, string? value)
{
if (value == null)
return;
#if NET20 || NET35
this[key] = value;
#else
TryAdd(key, value);
#endif
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
namespace BinaryObjectScanner
{
internal static class EnumerableExtensions
{
/// <summary>
/// Wrap iterating through an enumerable with an action
/// </summary>
/// <remarks>
/// .NET Frameworks 2.0 and 3.5 process in series.
/// .NET Frameworks 4.0 onward process in parallel.
/// </remarks>
public static void IterateWithAction<T>(this IEnumerable<T> source, Action<T> action)
{
#if NET20 || NET35
foreach (var item in source)
{
action(item);
}
#else
System.Threading.Tasks.Parallel.ForEach(source, action);
#endif
}
}
}

View File

@@ -10,22 +10,22 @@ namespace BinaryObjectScanner
/// </summary>
public static IDetectable? CreateDetectable(WrapperType fileType)
{
switch (fileType)
return fileType switch
{
case WrapperType.AACSMediaKeyBlock: return new FileType.AACSMediaKeyBlock();
case WrapperType.BDPlusSVM: return new FileType.BDPlusSVM();
//case WrapperType.CIA: return new FileType.CIA();
case WrapperType.Executable: return new FileType.Executable();
case WrapperType.LDSCRYPT: return new FileType.LDSCRYPT();
//case WrapperType.N3DS: return new FileType.N3DS();
//case WrapperType.Nitro: return new FileType.Nitro();
case WrapperType.PlayJAudioFile: return new FileType.PLJ();
case WrapperType.RealArcadeInstaller: return new FileType.RealArcadeInstaller();
case WrapperType.RealArcadeMezzanine: return new FileType.RealArcadeMezzanine();
case WrapperType.SFFS: return new FileType.SFFS();
case WrapperType.Textfile: return new FileType.Textfile();
default: return null;
}
WrapperType.AACSMediaKeyBlock => new FileType.AACSMediaKeyBlock(),
WrapperType.BDPlusSVM => new FileType.BDPlusSVM(),
//WrapperType.CIA => new FileType.CIA(),
WrapperType.Executable => new FileType.Executable(),
WrapperType.LDSCRYPT => new FileType.LDSCRYPT(),
//WrapperType.N3DS => new FileType.N3DS(),
//WrapperType.Nitro => new FileType.Nitro(),
WrapperType.PlayJAudioFile => new FileType.PLJ(),
WrapperType.RealArcadeInstaller => new FileType.RealArcadeInstaller(),
WrapperType.RealArcadeMezzanine => new FileType.RealArcadeMezzanine(),
WrapperType.SFFS => new FileType.SFFS(),
WrapperType.Textfile => new FileType.Textfile(),
_ => null,
};
}
/// <summary>
@@ -33,40 +33,40 @@ namespace BinaryObjectScanner
/// </summary>
public static IExtractable? CreateExtractable(WrapperType fileType)
{
switch (fileType)
return fileType switch
{
case WrapperType.BFPK: return new FileType.BFPK();
case WrapperType.BSP: return new FileType.BSP();
case WrapperType.BZip2: return new FileType.BZip2();
case WrapperType.CFB: return new FileType.CFB();
//case WrapperType.CIA: return new FileType.CIA();
case WrapperType.GCF: return new FileType.GCF();
case WrapperType.GZIP: return new FileType.GZIP();
case WrapperType.InstallShieldArchiveV3: return new FileType.InstallShieldArchiveV3();
case WrapperType.InstallShieldCAB: return new FileType.InstallShieldCAB();
case WrapperType.MicrosoftCAB: return new FileType.MicrosoftCAB();
case WrapperType.MicrosoftLZ: return new FileType.MicrosoftLZ();
case WrapperType.MoPaQ: return new FileType.MPQ();
//case WrapperType.N3DS: return new FileType.N3DS();
//case WrapperType.NCF: return new FileType.NCF();
//case WrapperType.Nitro: return new FileType.Nitro();
case WrapperType.PAK: return new FileType.PAK();
case WrapperType.PFF: return new FileType.PFF();
case WrapperType.PKZIP: return new FileType.PKZIP();
//case WrapperType.PlayJAudioFile: return new FileType.PLJ();
//case WrapperType.Quantum: return new FileType.Quantum();
case WrapperType.RAR: return new FileType.RAR();
case WrapperType.SevenZip: return new FileType.SevenZip();
case WrapperType.SFFS: return new FileType.SFFS();
case WrapperType.SGA: return new FileType.SGA();
case WrapperType.TapeArchive: return new FileType.TapeArchive();
case WrapperType.VBSP: return new FileType.VBSP();
case WrapperType.VPK: return new FileType.VPK();
case WrapperType.WAD: return new FileType.WAD();
case WrapperType.XZ: return new FileType.XZ();
case WrapperType.XZP: return new FileType.XZP();
default: return null;
}
WrapperType.BFPK => new FileType.BFPK(),
WrapperType.BSP => new FileType.BSP(),
WrapperType.BZip2 => new FileType.BZip2(),
WrapperType.CFB => new FileType.CFB(),
//WrapperType.CIA => new FileType.CIA(),
WrapperType.GCF => new FileType.GCF(),
WrapperType.GZIP => new FileType.GZIP(),
WrapperType.InstallShieldArchiveV3 => new FileType.InstallShieldArchiveV3(),
WrapperType.InstallShieldCAB => new FileType.InstallShieldCAB(),
WrapperType.MicrosoftCAB => new FileType.MicrosoftCAB(),
WrapperType.MicrosoftLZ => new FileType.MicrosoftLZ(),
WrapperType.MoPaQ => new FileType.MPQ(),
//WrapperType.N3DS => new FileType.N3DS(),
//WrapperType.NCF => new FileType.NCF(),
//WrapperType.Nitro => new FileType.Nitro(),
WrapperType.PAK => new FileType.PAK(),
WrapperType.PFF => new FileType.PFF(),
WrapperType.PKZIP => new FileType.PKZIP(),
//WrapperType.PlayJAudioFile => new FileType.PLJ(),
//WrapperType.Quantum => new FileType.Quantum(),
WrapperType.RAR => new FileType.RAR(),
WrapperType.SevenZip => new FileType.SevenZip(),
WrapperType.SFFS => new FileType.SFFS(),
WrapperType.SGA => new FileType.SGA(),
WrapperType.TapeArchive => new FileType.TapeArchive(),
WrapperType.VBSP => new FileType.VBSP(),
WrapperType.VPK => new FileType.VPK(),
WrapperType.WAD => new FileType.WAD(),
WrapperType.XZ => new FileType.XZ(),
WrapperType.XZP => new FileType.XZP(),
_ => null,
};
}
}
}

View File

@@ -1,17 +1,10 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
#if NET40_OR_GREATER || NETCOREAPP
using System.Threading.Tasks;
#endif
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Utilities;
using SabreTools.IO.Extensions;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.FileType
@@ -146,44 +139,40 @@ namespace BinaryObjectScanner.FileType
if (wrapper == null)
return null;
// Create the internal queue
#if NET20 || NET35
var protections = new Queue<string>();
#else
var protections = new ConcurrentQueue<string>();
#endif
// Create the internal list
var protections = new List<string>();
// Only use generic content checks if we're in debug mode
if (includeDebug)
{
var subProtections = RunContentChecks(file, stream, includeDebug);
if (subProtections != null)
protections.AddRange(subProtections.Values.ToArray());
protections.AddRange(subProtections.Values);
}
if (wrapper is MSDOS mz)
{
var subProtections = RunMSDOSExecutableChecks(file, stream, mz, includeDebug);
if (subProtections != null)
protections.AddRange(subProtections.Values.ToArray());
protections.AddRange(subProtections.Values);
}
else if (wrapper is LinearExecutable lex)
{
var subProtections = RunLinearExecutableChecks(file, stream, lex, includeDebug);
if (subProtections != null)
protections.AddRange(subProtections.Values.ToArray());
protections.AddRange(subProtections.Values);
}
else if (wrapper is NewExecutable nex)
{
var subProtections = RunNewExecutableChecks(file, stream, nex, includeDebug);
if (subProtections != null)
protections.AddRange(subProtections.Values.ToArray());
protections.AddRange(subProtections.Values);
}
else if (wrapper is PortableExecutable pex)
{
var subProtections = RunPortableExecutableChecks(file, stream, pex, includeDebug);
if (subProtections != null)
protections.AddRange(subProtections.Values.ToArray());
protections.AddRange(subProtections.Values);
}
return string.Join(";", [.. protections]);
@@ -198,11 +187,7 @@ namespace BinaryObjectScanner.FileType
/// <param name="stream">Stream to scan the contents of</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public Dictionary<IContentCheck, string>? RunContentChecks(string? file, Stream stream, bool includeDebug)
#else
public ConcurrentDictionary<IContentCheck, string>? RunContentChecks(string? file, Stream stream, bool includeDebug)
#endif
public IDictionary<IContentCheck, string>? RunContentChecks(string? file, Stream stream, bool includeDebug)
{
// If we have an invalid file
if (string.IsNullOrEmpty(file))
@@ -214,12 +199,7 @@ namespace BinaryObjectScanner.FileType
byte[] fileContent = [];
try
{
#if NET20 || NET35 || NET40
using var br = new BinaryReader(stream, Encoding.Default);
#else
using var br = new BinaryReader(stream, Encoding.Default, true);
#endif
fileContent = br.ReadBytes((int)stream.Length);
fileContent = stream.ReadBytes((int)stream.Length);
if (fileContent == null)
return null;
}
@@ -230,51 +210,26 @@ namespace BinaryObjectScanner.FileType
}
// Create the output dictionary
#if NET20 || NET35
var protections = new Dictionary<IContentCheck, string>();
#else
var protections = new ConcurrentDictionary<IContentCheck, string>();
#endif
var protections = new CheckDictionary<IContentCheck>();
// Iterate through all checks
#if NET20 || NET35
foreach (var checkClass in ContentCheckClasses)
#else
Parallel.ForEach(ContentCheckClasses, checkClass =>
#endif
ContentCheckClasses.IterateWithAction(checkClass =>
{
// Get the protection for the class, if possible
var protection = checkClass.CheckContents(file!, fileContent, includeDebug);
if (string.IsNullOrEmpty(protection))
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on game engines
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on packers
if (CheckIfPacker(checkClass) && !IncludePackers)
#if NET20 || NET35
continue;
#else
return;
#endif
#if NET20 || NET35
protections[checkClass] = protection!;
}
#else
protections.TryAdd(checkClass, protection!);
protections.Append(checkClass, protection);
});
#endif
return protections;
}
@@ -286,58 +241,29 @@ namespace BinaryObjectScanner.FileType
/// <param name="lex">Executable to scan</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public Dictionary<ILinearExecutableCheck, string> RunLinearExecutableChecks(string file, Stream stream, LinearExecutable lex, bool includeDebug)
#else
public ConcurrentDictionary<ILinearExecutableCheck, string> RunLinearExecutableChecks(string file, Stream stream, LinearExecutable lex, bool includeDebug)
#endif
public IDictionary<ILinearExecutableCheck, string> RunLinearExecutableChecks(string file, Stream stream, LinearExecutable lex, bool includeDebug)
{
// Create the output dictionary
#if NET20 || NET35
var protections = new Dictionary<ILinearExecutableCheck, string>();
#else
var protections = new ConcurrentDictionary<ILinearExecutableCheck, string>();
#endif
var protections = new CheckDictionary<ILinearExecutableCheck>();
// Iterate through all checks
#if NET20 || NET35
foreach (var checkClass in LinearExecutableCheckClasses)
#else
Parallel.ForEach(LinearExecutableCheckClasses, checkClass =>
#endif
LinearExecutableCheckClasses.IterateWithAction(checkClass =>
{
// Get the protection for the class, if possible
var protection = checkClass.CheckLinearExecutable(file, lex, includeDebug);
if (string.IsNullOrEmpty(protection))
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on game engines
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on packers
if (CheckIfPacker(checkClass) && !IncludePackers)
#if NET20 || NET35
continue;
#else
return;
#endif
#if NET20 || NET35
protections[checkClass] = protection!;
}
#else
protections.TryAdd(checkClass, protection!);
protections.Append(checkClass, protection);
});
#endif
return protections;
}
@@ -349,58 +275,29 @@ namespace BinaryObjectScanner.FileType
/// <param name="mz">Executable to scan</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public Dictionary<IMSDOSExecutableCheck, string> RunMSDOSExecutableChecks(string file, Stream stream, MSDOS mz, bool includeDebug)
#else
public ConcurrentDictionary<IMSDOSExecutableCheck, string> RunMSDOSExecutableChecks(string file, Stream stream, MSDOS mz, bool includeDebug)
#endif
public IDictionary<IMSDOSExecutableCheck, string> RunMSDOSExecutableChecks(string file, Stream stream, MSDOS mz, bool includeDebug)
{
// Create the output dictionary
#if NET20 || NET35
var protections = new Dictionary<IMSDOSExecutableCheck, string>();
#else
var protections = new ConcurrentDictionary<IMSDOSExecutableCheck, string>();
#endif
var protections = new CheckDictionary<IMSDOSExecutableCheck>();
// Iterate through all checks
#if NET20 || NET35
foreach (var checkClass in MSDOSExecutableCheckClasses)
#else
Parallel.ForEach(MSDOSExecutableCheckClasses, checkClass =>
#endif
MSDOSExecutableCheckClasses.IterateWithAction(checkClass =>
{
// Get the protection for the class, if possible
var protection = checkClass.CheckMSDOSExecutable(file, mz, includeDebug);
if (string.IsNullOrEmpty(protection))
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on game engines
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on packers
if (CheckIfPacker(checkClass) && !IncludePackers)
#if NET20 || NET35
continue;
#else
return;
#endif
#if NET20 || NET35
protections[checkClass] = protection!;
}
#else
protections.TryAdd(checkClass, protection!);
protections.Append(checkClass, protection);
});
#endif
return protections;
}
@@ -412,58 +309,29 @@ namespace BinaryObjectScanner.FileType
/// <param name="nex">Executable to scan</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public Dictionary<INewExecutableCheck, string> RunNewExecutableChecks(string file, Stream stream, NewExecutable nex, bool includeDebug)
#else
public ConcurrentDictionary<INewExecutableCheck, string> RunNewExecutableChecks(string file, Stream stream, NewExecutable nex, bool includeDebug)
#endif
public IDictionary<INewExecutableCheck, string> RunNewExecutableChecks(string file, Stream stream, NewExecutable nex, bool includeDebug)
{
// Create the output dictionary
#if NET20 || NET35
var protections = new Dictionary<INewExecutableCheck, string>();
#else
var protections = new ConcurrentDictionary<INewExecutableCheck, string>();
#endif
var protections = new CheckDictionary<INewExecutableCheck>();
// Iterate through all checks
#if NET20 || NET35
foreach (var checkClass in NewExecutableCheckClasses)
#else
Parallel.ForEach(NewExecutableCheckClasses, checkClass =>
#endif
NewExecutableCheckClasses.IterateWithAction(checkClass =>
{
// Get the protection for the class, if possible
var protection = checkClass.CheckNewExecutable(file, nex, includeDebug);
if (string.IsNullOrEmpty(protection))
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on game engines
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on packers
if (CheckIfPacker(checkClass) && !IncludePackers)
#if NET20 || NET35
continue;
#else
return;
#endif
#if NET20 || NET35
protections[checkClass] = protection!;
}
#else
protections.TryAdd(checkClass, protection!);
protections.Append(checkClass, protection);
});
#endif
return protections;
}
@@ -475,58 +343,29 @@ namespace BinaryObjectScanner.FileType
/// <param name="pex">Executable to scan</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public Dictionary<IPortableExecutableCheck, string> RunPortableExecutableChecks(string file, Stream stream, PortableExecutable pex, bool includeDebug)
#else
public ConcurrentDictionary<IPortableExecutableCheck, string> RunPortableExecutableChecks(string file, Stream stream, PortableExecutable pex, bool includeDebug)
#endif
public IDictionary<IPortableExecutableCheck, string> RunPortableExecutableChecks(string file, Stream stream, PortableExecutable pex, bool includeDebug)
{
// Create the output dictionary
#if NET20 || NET35
var protections = new Dictionary<IPortableExecutableCheck, string>();
#else
var protections = new ConcurrentDictionary<IPortableExecutableCheck, string>();
#endif
var protections = new CheckDictionary<IPortableExecutableCheck>();
// Iterate through all checks
#if NET20 || NET35
foreach (var checkClass in PortableExecutableCheckClasses)
#else
Parallel.ForEach(PortableExecutableCheckClasses, checkClass =>
#endif
PortableExecutableCheckClasses.IterateWithAction(checkClass =>
{
// Get the protection for the class, if possible
var protection = checkClass.CheckPortableExecutable(file, pex, includeDebug);
if (string.IsNullOrEmpty(protection))
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on game engines
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
#if NET20 || NET35
continue;
#else
return;
#endif
// If we are filtering on packers
if (CheckIfPacker(checkClass) && !IncludePackers)
#if NET20 || NET35
continue;
#else
return;
#endif
#if NET20 || NET35
protections[checkClass] = protection!;
}
#else
protections.TryAdd(checkClass, protection!);
protections.Append(checkClass, protection);
});
#endif
return protections;
}

View File

@@ -38,7 +38,7 @@ namespace BinaryObjectScanner.FileType
if (directoryName != null && !Directory.Exists(directoryName))
Directory.CreateDirectory(directoryName);
(byte[]? fileContents, string? error) = archive.Extract(cfile.Key);
byte[]? fileContents = archive.Extract(cfile.Key, out string? error);
if (fileContents == null || !string.IsNullOrEmpty(error))
continue;

View File

@@ -1,7 +1,6 @@
using System;
using System.IO;
using System.IO;
using BinaryObjectScanner.Interfaces;
#if ((NETFRAMEWORK && !NET20 && !NET35 && !NET40) || NETCOREAPP) && WIN
#if (NET452_OR_GREATER || NETCOREAPP) && WIN
using StormLibSharp;
#endif
@@ -34,7 +33,7 @@ namespace BinaryObjectScanner.FileType
try
{
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
string tempPath = Path.Combine(Path.GetTempPath(), System.Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (var mpqArchive = new MpqArchive(file, FileAccess.Read))
@@ -65,18 +64,18 @@ namespace BinaryObjectScanner.FileType
Directory.CreateDirectory(Path.GetDirectoryName(tempFile));
mpqArchive.ExtractFile(sub, tempFile);
}
catch (Exception ex)
catch (System.Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
if (includeDebug) System.Console.WriteLine(ex);
}
}
}
return tempPath;
}
catch (Exception ex)
catch (System.Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
if (includeDebug) System.Console.WriteLine(ex);
return null;
}
#endif

View File

@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO;
using BinaryObjectScanner.Interfaces;
#if ((NETFRAMEWORK && !NET20 && !NET35 && !NET40) || NETCOREAPP) && WIN
#if (NET40_OR_GREATER || NETCOREAPP) && WIN
using LibMSPackN;
#endif
@@ -28,7 +26,7 @@ namespace BinaryObjectScanner.FileType
/// <inheritdoc/>
public string? Extract(Stream? stream, string file, bool includeDebug)
{
#if NET20 || NET35 || NET40 || !WIN
#if NET20 || NET35 || !WIN
// Not supported for old .NET due to feature requirements
// Not supported in non-Windows builds due to DLL requirements
return null;
@@ -36,7 +34,7 @@ namespace BinaryObjectScanner.FileType
try
{
// Create a temp output directory
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
string tempPath = Path.Combine(Path.GetTempPath(), System.Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (var cabArchive = new MSCabinet(file))
@@ -50,18 +48,18 @@ namespace BinaryObjectScanner.FileType
Directory.CreateDirectory(Path.GetDirectoryName(tempFile));
compressedFile.ExtractTo(tempFile);
}
catch (Exception ex)
catch (System.Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
if (includeDebug) System.Console.WriteLine(ex);
}
}
}
return tempPath;
}
catch (Exception ex)
catch (System.Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
if (includeDebug) System.Console.WriteLine(ex);
return null;
}
#endif

View File

@@ -131,6 +131,11 @@ namespace BinaryObjectScanner.FileType
if (fileContent.Contains("Sentinel Driver Disk"))
protections.Add("Rainbow Sentinel");
// SafeCast
// Found in "AdlmLog.xml" in IA item game-programming-in-c-start-to-finish-2006 after installing "3dsMax8_Demo.zip".
if (fileContent.Contains("<NAME>SAFECAST</NAME>"))
protections.Add("SafeCast");
// SafeDisc
// TODO: Add better version parsing.
// Found in "Info.plist" in Redump entries 23983, 42762, 72713, 73070, and 89603.

View File

@@ -1,16 +1,10 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Utilities;
using SabreTools.Serialization.Wrappers;
using static BinaryObjectScanner.Utilities.Dictionary;
namespace BinaryObjectScanner
{
@@ -49,37 +43,21 @@ namespace BinaryObjectScanner
/// <param name="path">Path of the file or directory to check</param>
/// <param name="scanner">Scanner object to use for options and scanning</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public static Dictionary<string, Queue<string>> HandlePathChecks(string path, IEnumerable<string>? files)
#else
public static ConcurrentDictionary<string, ConcurrentQueue<string>> HandlePathChecks(string path, IEnumerable<string>? files)
#endif
public static ProtectionDictionary HandlePathChecks(string path, IEnumerable<string>? files)
{
// Create the output dictionary
#if NET20 || NET35
var protections = new Dictionary<string, Queue<string>>();
#else
var protections = new ConcurrentDictionary<string, ConcurrentQueue<string>>();
#endif
var protections = new ProtectionDictionary();
// Preprocess the list of files
files = files?.Select(f => f.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar))?.ToList();
// Iterate through all checks
#if NET20 || NET35
foreach (var checkClass in PathCheckClasses)
#else
Parallel.ForEach(PathCheckClasses, checkClass =>
#endif
PathCheckClasses.IterateWithAction(checkClass =>
{
var subProtections = checkClass?.PerformCheck(path, files);
if (subProtections != null)
AppendToDictionary(protections, path, subProtections);
#if NET20 || NET35
}
#else
protections.Append(path, subProtections);
});
#endif
return protections;
}
@@ -96,11 +74,7 @@ namespace BinaryObjectScanner
/// <param name="stream">Stream to scan the contents of</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public static Queue<string>? HandleDetectable(IDetectable impl, string fileName, Stream stream, bool includeDebug)
#else
public static ConcurrentQueue<string>? HandleDetectable(IDetectable impl, string fileName, Stream stream, bool includeDebug)
#endif
public static List<string>? HandleDetectable(IDetectable impl, string fileName, Stream stream, bool includeDebug)
{
var protection = impl.Detect(stream, fileName, includeDebug);
return ProcessProtectionString(protection);
@@ -114,11 +88,7 @@ namespace BinaryObjectScanner
/// <param name="stream">Stream to scan the contents of</param>
/// <param name="scanner">Scanner object to use on extractable contents</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public static Dictionary<string, Queue<string>>? HandleExtractable(IExtractable impl, string fileName, Stream? stream, Scanner scanner)
#else
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractable impl, string fileName, Stream? stream, Scanner scanner)
#endif
public static ProtectionDictionary? HandleExtractable(IExtractable impl, string fileName, Stream? stream, Scanner scanner)
{
// If the extractable file itself fails
try
@@ -142,8 +112,8 @@ namespace BinaryObjectScanner
}
// Prepare the returned protections
StripFromKeys(subProtections, tempPath);
PrependToKeys(subProtections, fileName);
subProtections?.StripFromKeys(tempPath);
subProtections?.PrependToKeys(fileName);
return subProtections;
}
catch (Exception ex)
@@ -162,11 +132,7 @@ namespace BinaryObjectScanner
/// <param name="mz">MSDOS to scan the contents of</param>
/// <param name="scanner">Scanner object to use on extractable contents</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public static Dictionary<string, Queue<string>>? HandleExtractable(IExtractableMSDOSExecutable impl, string fileName, MSDOS mz, Scanner scanner)
#else
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractableMSDOSExecutable impl, string fileName, MSDOS mz, Scanner scanner)
#endif
public static ProtectionDictionary? HandleExtractable(IExtractableMSDOSExecutable impl, string fileName, MSDOS mz, Scanner scanner)
{
// If the extractable file itself fails
try
@@ -190,8 +156,8 @@ namespace BinaryObjectScanner
}
// Prepare the returned protections
StripFromKeys(subProtections, tempPath);
PrependToKeys(subProtections, fileName);
subProtections?.StripFromKeys(tempPath);
subProtections?.PrependToKeys(fileName);
return subProtections;
}
catch (Exception ex)
@@ -210,11 +176,7 @@ namespace BinaryObjectScanner
/// <param name="lex">LinearExecutable to scan the contents of</param>
/// <param name="scanner">Scanner object to use on extractable contents</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public static Dictionary<string, Queue<string>>? HandleExtractable(IExtractableLinearExecutable impl, string fileName, LinearExecutable lex, Scanner scanner)
#else
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractableLinearExecutable impl, string fileName, LinearExecutable lex, Scanner scanner)
#endif
public static ProtectionDictionary? HandleExtractable(IExtractableLinearExecutable impl, string fileName, LinearExecutable lex, Scanner scanner)
{
// If the extractable file itself fails
try
@@ -238,8 +200,8 @@ namespace BinaryObjectScanner
}
// Prepare the returned protections
StripFromKeys(subProtections, tempPath);
PrependToKeys(subProtections, fileName);
subProtections?.StripFromKeys(tempPath);
subProtections?.PrependToKeys(fileName);
return subProtections;
}
catch (Exception ex)
@@ -258,11 +220,7 @@ namespace BinaryObjectScanner
/// <param name="nex">NewExecutable to scan the contents of</param>
/// <param name="scanner">Scanner object to use on extractable contents</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public static Dictionary<string, Queue<string>>? HandleExtractable(IExtractableNewExecutable impl, string fileName, NewExecutable nex, Scanner scanner)
#else
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractableNewExecutable impl, string fileName, NewExecutable nex, Scanner scanner)
#endif
public static ProtectionDictionary? HandleExtractable(IExtractableNewExecutable impl, string fileName, NewExecutable nex, Scanner scanner)
{
// If the extractable file itself fails
try
@@ -286,8 +244,8 @@ namespace BinaryObjectScanner
}
// Prepare the returned protections
StripFromKeys(subProtections, tempPath);
PrependToKeys(subProtections, fileName);
subProtections?.StripFromKeys(tempPath);
subProtections?.PrependToKeys(fileName);
return subProtections;
}
catch (Exception ex)
@@ -306,11 +264,7 @@ namespace BinaryObjectScanner
/// <param name="pex">PortableExecutable to scan the contents of</param>
/// <param name="scanner">Scanner object to use on extractable contents</param>
/// <returns>Set of protections in file, null on error</returns>
#if NET20 || NET35
public static Dictionary<string, Queue<string>>? HandleExtractable(IExtractablePortableExecutable impl, string fileName, PortableExecutable pex, Scanner scanner)
#else
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractablePortableExecutable impl, string fileName, PortableExecutable pex, Scanner scanner)
#endif
public static ProtectionDictionary? HandleExtractable(IExtractablePortableExecutable impl, string fileName, PortableExecutable pex, Scanner scanner)
{
// If the extractable file itself fails
try
@@ -334,8 +288,8 @@ namespace BinaryObjectScanner
}
// Prepare the returned protections
StripFromKeys(subProtections, tempPath);
PrependToKeys(subProtections, fileName);
subProtections?.StripFromKeys(tempPath);
subProtections?.PrependToKeys(fileName);
return subProtections;
}
catch (Exception ex)
@@ -352,22 +306,14 @@ namespace BinaryObjectScanner
/// <param name="impl">IPathCheck class representing the file type</param>
/// <param name="path">Path of the file or directory to check</param>
/// <returns>Set of protections in path, null on error</returns>
#if NET20 || NET35
private static Queue<string>? PerformCheck(this IPathCheck impl, string? path, IEnumerable<string>? files)
#else
private static ConcurrentQueue<string>? PerformCheck(this IPathCheck impl, string? path, IEnumerable<string>? files)
#endif
private static List<string>? PerformCheck(this IPathCheck impl, string? path, IEnumerable<string>? files)
{
// If we have an invalid path
if (string.IsNullOrEmpty(path))
return null;
// Setup the output dictionary
#if NET20 || NET35
var protections = new Queue<string>();
#else
var protections = new ConcurrentQueue<string>();
#endif
// Setup the list
var protections = new List<string>();
// If we have a file path
if (File.Exists(path))
@@ -442,22 +388,14 @@ namespace BinaryObjectScanner
/// </summary>
/// <param name="protection">Protection string to process</param>
/// <returns>Set of protections parsed, null on error</returns>
#if NET20 || NET35
private static Queue<string>? ProcessProtectionString(string? protection)
#else
private static ConcurrentQueue<string>? ProcessProtectionString(string? protection)
#endif
private static List<string>? ProcessProtectionString(string? protection)
{
// If we have an invalid protection string
if (string.IsNullOrEmpty(protection))
return null;
// Setup the output queue
#if NET20 || NET35
var protections = new Queue<string>();
#else
var protections = new ConcurrentQueue<string>();
#endif
var protections = new List<string>();
// If we have an indicator of multiple protections
if (protection!.Contains(";"))
@@ -467,7 +405,7 @@ namespace BinaryObjectScanner
}
else
{
protections.Enqueue(protection);
protections.Add(protection);
}
return protections;

View File

@@ -1,7 +1,4 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
namespace BinaryObjectScanner.Interfaces
{
@@ -19,11 +16,7 @@ namespace BinaryObjectScanner.Interfaces
/// <param name="path">Path to check for protection indicators</param>
/// <param name="files">Enumerable of strings representing files in a directory</param>
/// <remarks>This can do some limited content checking as well, but it's suggested to use a content check instead, if possible</remarks>
#if NET20 || NET35
Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files);
#else
ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files);
#endif
IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files);
/// <summary>
/// Check a file path for protections based on path name

View File

@@ -2,6 +2,7 @@ using System.Collections.Generic;
using System.Text;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer

View File

@@ -5,6 +5,7 @@ using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Compression.zlib;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer

View File

@@ -5,7 +5,7 @@ using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
public class dotFuscator : IExtractablePortableExecutable, IPortableExecutableCheck
public class DotFuscator : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)

View File

@@ -0,0 +1,106 @@
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
using System.Collections.Generic;
using SabreTools.Matching;
using SabreTools.Matching.Content;
namespace BinaryObjectScanner.Packer
{
/// <summary>
/// .NET Reactor is a .NET obfuscator that was original released in 2004. https://web.archive.org/web/20040828162124/http://eziriz.com:80/
/// It is currently still being updated and supported. https://www.eziriz.com/dotnet_reactor.htm
/// While ProtectionID does detect .NET Reactor, it's currently unknown exactly how.
/// It seems to simply check for the string "<PrivateImplementationDetails>" in specific, and currently unknown, conditions but appears to be prone to false positives.
/// A "Demo/Nag Screen" version is available for free, and may be able to be used to make samples to improve detections. https://www.eziriz.com/reactor_download.htm
///
/// Resource that could be useful for extraction: https://github.com/SychicBoy/NETReactorSlayer
/// </summary>
public class DotNetReactor : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// TODO: Detect version
// TODO: Further refine checks using https://github.com/horsicq/Detect-It-Easy/blob/075a70b1484d1d84d1dc37c86aac16188d5a84e7/db/PE/NetReactor.2.sg and https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// Get the .text section, if it exists
if (pex.ContainsSection(".text"))
{
var textData = pex.GetFirstSectionData(".text");
if (textData != null)
{
var matchers = new List<ContentMatchSet>
{
// Adapted from https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar and confirmed to work with "KalypsoLauncher.dll" from Redump entry 95617.
// <PrivateImplementationDetails>{[8]-[4]-[4]-[4]-[12]}
new(new byte?[]
{
0x3C, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65,
0x49, 0x6D, 0x70, 0x6C, 0x65, 0x6D, 0x65, 0x6E,
0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 0x65,
0x74, 0x61, 0x69, 0x6C, 0x73, 0x3E, 0x7B, null,
null, null, null, null, null, null, null, 0x2D,
null, null, null, null, 0x2D, null, null, null,
null, 0x2D, null, null, null, null, 0x2D, null,
null, null, null, null, null, null, null, null,
null, null, null, 0x7D
}, ".NET Reactor"),
// Modified from the previous detection to detect a presumably newer version of .NET Reactor found in "KalypsoLauncher.dll" version 2.0.4.2.
// TODO: Check if this can/should be made more specific.
// <PrivateImplementationDetails>.RSA
new(new byte?[]
{
0x3C, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65,
0x49, 0x6D, 0x70, 0x6C, 0x65, 0x6D, 0x65, 0x6E,
0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 0x65,
0x74, 0x61, 0x69, 0x6C, 0x73, 0x3E, 0x00, 0x52,
0x53, 0x41
}, ".NET Reactor"),
// Adapted from https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar and confirmed to work with "KalypsoLauncher.dll" from Redump entry 95617.
// 3{.[9].-.[9].-.[9].}
new(new byte?[]
{
0x33, 0x7B, 0x00, null, null, null, null, null,
null, null, null, null, 0x00, 0x2D, 0x00, null,
null, null, null, null, null, null, null, null,
0x00, 0x2D, 0x00, null, null, null, null, null,
null, null, null, null, 0x00, 0x2D, 0x00, null,
null, null, null, null, null, null, null, null,
0x00, 0x7D, 0x00
}, ".NET Reactor (Unconfirmed - Please report to us on GitHub)"),
// Adapted from https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar and confirmed to work with "KalypsoLauncher.dll" from Redump entry 95617.
// <Module>{[8]-[4]-[4]-[4]-[12]}
new(new byte?[]
{
0x3C, 0x4D, 0x6F, 0x64, 0x75, 0x6C, 0x65, 0x3E,
0x7B, null, null, null, null, null, null, null,
null, 0x2D, null, null, null, null, 0x2D, null,
null, null, null, 0x2D, null, null, null, null,
0x2D, null, null, null, null, null, null, null,
null, null, null, null, null, 0x7D
}, ".NET Reactor (Unconfirmed - Please report to us on GitHub)")
};
return MatchUtil.GetFirstMatch(file, textData, matchers, includeDebug);
}
}
return null;
}
/// <inheritdoc/>
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
{
// TODO: Add extraction
return null;
}
}
}

View File

@@ -1,6 +1,7 @@
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer

View File

@@ -2,6 +2,7 @@
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer

View File

@@ -1,5 +1,4 @@
using System.IO;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer

View File

@@ -5,6 +5,7 @@ using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.IO.Extensions;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Serialization.Wrappers;
using WiseUnpacker;
using WiseUnpacker.EWISE;

View File

@@ -3,6 +3,7 @@ using System.Linq;
using System.Text;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection

View File

@@ -1,10 +1,9 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -69,11 +68,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,9 +1,7 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
namespace BinaryObjectScanner.Protection
{
@@ -18,11 +16,7 @@ namespace BinaryObjectScanner.Protection
public class AlphaDVD : IPathCheck
{
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;

View File

@@ -2,11 +2,22 @@
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Packer
{
namespace BinaryObjectScanner.Protection
{
/// <summary>
/// Armadillo was a license manager, packer, and DRM by "The Silicon Realm Toolworks": https://web.archive.org/web/20030203101931/http://www.siliconrealms.com/armadillo.shtml
/// They were later bought by Digital River, and updated their website: https://web.archive.org/web/20031203021152/http://www.siliconrealms.com/armadillo.shtml
/// A new updated version named "SoftwarePassport" was released: https://web.archive.org/web/20040423044529/http://siliconrealms.com/softwarepassport/popup.shtml
/// Later copy of the website, with SoftwarePassport being named instead of Armadillo: https://web.archive.org/web/20040804032608/http://www.siliconrealms.com/armadillo.shtml
/// It appears as though both Armadillo and SoftwarePassport were being released at the same time, possibly with Armadillo acting as the core component and SoftwarePassport being supplementary: https://web.archive.org/web/20050619013312/http://siliconrealms.com/srt-news.shtml
/// Digital River itself also advertised Armadillo at first: https://web.archive.org/web/20040116043029/http://www.digitalriver.com:80/corporate/solutions06.shtml
/// But then only advertised SoftwarePassport once it was released: https://web.archive.org/web/20040604065907/http://www.digitalriver.com/corporate/solutions06.shtml
/// </summary>
// TODO: Add extraction
// TODO: Add version checking, if possible
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class Armadillo : IExtractablePortableExecutable, IPortableExecutableCheck
{
/// <inheritdoc/>

View File

@@ -1,9 +1,7 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
namespace BinaryObjectScanner.Protection
{
@@ -15,11 +13,7 @@ namespace BinaryObjectScanner.Protection
public class Bitpool : IPathCheck
{
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
@@ -31,13 +25,13 @@ namespace BinaryObjectScanner.Protection
// A set of 4 identically sized (within the same game, not between games), corrupted/padded files present in several games (Redump entries 31782 and 35476).
// Both examples with only having the first letter uppercase and as the whole file name being uppercase have been seen.
new(new List<PathMatch>
{
new(
[
new FilePathMatch("Crc_a"),
new FilePathMatch("Crc_b"),
new FilePathMatch("Crc_c"),
new FilePathMatch("Crc_d"),
}, "Bitpool"),
], "Bitpool"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);

View File

@@ -1,10 +1,8 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -132,11 +130,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
// TODO: Investigate reference to "bbz650.tmp" in "Byteshield.dll" (Redump entry 6236)
// Files with the ".bbz" extension are associated with ByteShield, but the extenstion is known to be used in other places as well.

View File

@@ -1,13 +1,11 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Models.PortableExecutable;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -184,11 +182,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
// TODO: Original had "CDCOPS.DLL" required and all the rest in a combined OR
var matchers = new List<PathMatchSet>
@@ -197,7 +191,7 @@ namespace BinaryObjectScanner.Protection
// Presumably used to increase the amount of data written to the disc to allow DPM checking to be used for the protection. It's unknown if this file is used on any other protected discs.
// Found in Redump entry 84517.
new(new PathMatch("CDCOPS.DLL", useEndsWith: true), "CD-Cops"),
new(new FilePathMatch("CDCOPS.DLL"), "CD-Cops"),
new(new PathMatch(".W_X", matchExact: true, useEndsWith: true), "CD/DVD-Cops"),
new(new PathMatch(".QZ_", matchExact: true, useEndsWith: true), "CD/DVD-Cops"),
@@ -217,7 +211,7 @@ namespace BinaryObjectScanner.Protection
// Presumably used to increase the amount of data written to the disc to allow DPM checking to be used for the protection. It's unknown if this file is used on any other protected discs.
// Found in Redump entry 84517.
new(new PathMatch("CDCOPS.DLL", useEndsWith: true), "CD-Cops"),
new(new FilePathMatch("CDCOPS.DLL"), "CD-Cops"),
new(new PathMatch(".W_X", matchExact: true, useEndsWith: true), "CD/DVD-Cops"),
new(new PathMatch(".QZ_", matchExact: true, useEndsWith: true), "CD/DVD-Cops"),

View File

@@ -1,11 +1,9 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -57,11 +55,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,9 +1,8 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -63,18 +62,14 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// TODO: Determine if there's any consistency in the naming of the additional AFP files.
// Found in every confirmed sample of CD-Lock, generally (but not always) appears to include markers relating to the additional AFP files present (Redump entries 24287 and 31615).
new(new PathMatch("CONFIG.AFP", useEndsWith: true), "CD-Lock"),
new(new FilePathMatch("CONFIG.AFP"), "CD-Lock"),
// There is also a "$$$$$$$$.$$$" file present on some discs, but it isn't known if this is directly related to CD-Lock (Redump entries 37788 and 43221).
};
@@ -90,7 +85,7 @@ namespace BinaryObjectScanner.Protection
// TODO: Determine if there's any consistency in the naming of the additional AFP files.
// Found in every confirmed sample of CD-Lock, generally (but not always) appears to include markers relating to the additional AFP files present (Redump entries 24287 and 31615).
new(new PathMatch("CONFIG.AFP", useEndsWith: true), "CD-Lock"),
new(new FilePathMatch("CONFIG.AFP"), "CD-Lock"),
// There is also a "$$$$$$$$.$$$" file present on some discs, but it isn't known if this is directly related to CD-Lock (Redump entries 37788 and 43221).
};

View File

@@ -1,9 +1,7 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
namespace BinaryObjectScanner.Protection
{
@@ -19,11 +17,7 @@ namespace BinaryObjectScanner.Protection
public class CDProtector : IPathCheck
{
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;

View File

@@ -1,9 +1,7 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
namespace BinaryObjectScanner.Protection
{
@@ -14,11 +12,7 @@ namespace BinaryObjectScanner.Protection
public class CDX : IPathCheck
{
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
// TODO: Verify if these are OR or AND
var matchers = new List<PathMatchSet>

View File

@@ -2,6 +2,7 @@
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
namespace BinaryObjectScanner.Protection
{

View File

@@ -1,10 +1,8 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -55,11 +53,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,10 +1,8 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -63,11 +61,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,11 +1,9 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -56,11 +54,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,10 +1,8 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -38,11 +36,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
// Previous versions of BOS noted to look at ".PFF" files as possible indicators of CopyKiller, but those files seem unrelated.
// TODO: Figure out why this doesn't work.
@@ -51,8 +45,8 @@ namespace BinaryObjectScanner.Protection
new(new FilePathMatch("CopyKillerV3"), "CopyKiller V3.62-3.64"),
new(new FilePathMatch("CopyKillerV4"), "CopyKiller V3.99-3.99a"),
new(new List<PathMatch>
{
new(
[
new FilePathMatch("ACK3900.ckt"),
new FilePathMatch("ACK3999.ckt"),
new FilePathMatch("CK100.wzc"),
@@ -62,10 +56,10 @@ namespace BinaryObjectScanner.Protection
new FilePathMatch("P261XP.tcck"),
new FilePathMatch("WZ200.rwzc"),
new FilePathMatch("XCK3900.ck2"),
}, "CopyKiller V3.99+"),
], "CopyKiller V3.99+"),
new(new List<PathMatch>
{
new(
[
new FilePathMatch("ACK3900.ckt"),
new FilePathMatch("CK100.wzc"),
new FilePathMatch("CK2500.ck"),
@@ -74,13 +68,13 @@ namespace BinaryObjectScanner.Protection
new FilePathMatch("P261XP.tcck"),
new FilePathMatch("WZ200.rwzc"),
new FilePathMatch("XCK3900.ck2"),
}, "CopyKiller V3.64+"),
], "CopyKiller V3.64+"),
new(new List<PathMatch>
{
new(
[
new FilePathMatch("CK100.wzc"),
new FilePathMatch("Engine.wzc"),
}, "CopyKiller V3.62+"),
], "CopyKiller V3.62+"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);

View File

@@ -0,0 +1,194 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.IO.Extensions;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
{
// TODO: Technically not necessary, but just check for light/pro first and only if it isn't found look for the other.
// It should be an Or situation and not an And situation.
// TODO: Figure out if Light and Professional are what designate rings and rings+disccheck
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.
// No samples of Trial are known at the moment, so it can't be checked for either.
// There are two kinds of copy-X generally observed; those with only rings, and those with rings and a disc check.
// These comments assume with 0 evidence that the former is Light and the latter is Professional.
// Because there is no evidence, only copy-X is being returned for now. This check has pre-emptively separated
// the two, just for when a designation can be applied for sure.
// Overall:
// Whenever these comments state "at the end of" or "at the start of" pertaining to the filesystem, they refer
// to alphabetical order, because this is how copy-X images seem to be mastered usually (not always, but w/e).
// 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 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 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
// SoftICE-Test. It is not currently known if this is specifically part of copy-X, or if it's an external
// solution employed by both copy-X and also other companies. If it's the latter, it should have its own check.
// It has none here since it wouldn't be necessary.
// Light:
// 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.
// Find a viable way to check the last directory alphabetically and not just ZDAT*
/// <inheritdoc/>
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Checks for Professional
// PEX checks intentionally only detect Professional
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
if (pex.OverlayStrings != null)
{
// Checks if main executable contains reference to optgraph.dll.
// This might be better removed later, as Redump ID 82475 is a false positive, and also doesn't actually
// contain the actual optgraph.dll file.
// TODO: Find a way to check for situations like Redump ID 48393, where the string is spaced out with
// 0x00 between letters and does not show up on string checks.
// TODO: This might need to check every single section. Unsure until more samples are acquired.
// TODO: TKKG also has an NE 3.1x executable with a reference. This can be added later.
// Samples: Redump ID 108150
if (pex.OverlayStrings.Any(s => s.Contains("optgraph.dll")))
return "copy-X [Check disc for physical ring]";
}
var strs = pex.GetFirstSectionStrings(".rdata");
if (strs != null)
{
// Samples: Redump ID 82475, German Emergency 2 Deluxe, Redump ID 48393
if (strs.Any(s => s.Contains("optgraph.dll")))
return "copy-X [Check disc for physical ring]";
}
return null;
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var protections = new List<string>();
if (files == null)
return protections;
// Checks for Light
// Directory checks intentionally only detect Light
// Excludes files with .x64 extension to avoid flagging Professional files.
// Sorts list of files in ZDAT* so just the first file gets pulled, later ones have a chance of the ring
// intersecting the start of the file.
// Kenny's Adventure uses System instead of ZDAT.
string[] dirs = ["ZDAT", "ZDATA", "ZZDAT", "ZZDATA", "ZYDAT", "ZYDATA", "System"];
List<string>? 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)
{
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
{
using var stream = File.OpenRead(lightFiles[0]);
byte[] block = stream.ReadBytes(1024);
var matchers = new List<ContentMatchSet>
{
// Checks if the file contains 0x00
// Samples: Redump ID 81628
new(Enumerable.Repeat<byte?>(0x00, 1024).ToArray(), "copy-X"),
// Checks for whatever this data is.
// Samples: Redump ID 84759, Redump ID 107929. Professional discs also have this data, hence the exclusion check.
new(
[
0x02, 0xFE, 0x4A, 0x4F, 0x52, 0x4B, 0x1C, 0xE0,
0x79, 0x8C, 0x7F, 0x85, 0x04, 0x00, 0x46, 0x46,
0x49, 0x46, 0x07, 0xF9, 0x9F, 0xA0, 0xA1, 0x9D,
0xDA, 0xB6, 0x2C, 0x2D, 0x2D, 0x2C, 0xFF, 0x00,
0x6F, 0x6E, 0x71, 0x6A, 0xFC, 0x06, 0x64, 0x62,
0x65, 0x5F, 0xFB, 0x06, 0x31, 0x31, 0x31, 0x31,
0x00, 0x00, 0x1D, 0x1D, 0x1F, 0x1D, 0xFE, 0xFD,
0x51, 0x57, 0x56, 0x51, 0xFB, 0x06, 0x33, 0x34,
], "copy-X [Check disc for physical ring]"),
};
var match = MatchUtil.GetFirstMatch(lightFiles[0], block, matchers, false);
if (!string.IsNullOrEmpty(match))
protections.Add(match!);
}
catch { }
}
return protections;
}
/// <inheritdoc/>
public string? CheckFilePath(string path)
{
// Checks for Professional
// File Path checks intentionally only detect Professional
var matchers = new List<PathMatchSet>
{
// Samples: Redump ID 108150, Redump ID 48393
// File responsible for disc check
new(new FilePathMatch("optgraph.dll"), "copy-X [Check disc for physical ring]"),
// Seemingly comorbid file, referenced in above file
new(new FilePathMatch("iofile.x64"), "copy-X [Check disc for physical ring]"),
// Seemingly comorbid file
new(new FilePathMatch("sound.x64"), "copy-X [Check disc for physical ring]"),
// Seemingly comorbid file
// Check commented out until implementation can be decided
// At least one disc seen online calls it mov_05.x64
// new(new FilePathMatch("gov_*.x64"), "copy-X [Check disc for physical ring]"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
}
}

View File

@@ -1,10 +1,8 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -76,11 +74,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,6 +1,7 @@
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection

View File

@@ -1,20 +1,14 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
namespace BinaryObjectScanner.Protection
{
public class DVDCrypt : IPathCheck
{
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,7 +1,4 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
@@ -12,17 +9,9 @@ namespace BinaryObjectScanner.Protection
public class DVDMoviePROTECT : IPathCheck
{
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
#if NET20 || NET35
var protections = new Queue<string>();
#else
var protections = new ConcurrentQueue<string>();
#endif
var protections = new List<string>();
if (files == null)
return protections;
@@ -38,7 +27,7 @@ namespace BinaryObjectScanner.Protection
var ifofile = new FileInfo(Path.Combine(bupfile.DirectoryName, bupfile.Name.Substring(0, bupfile.Name.Length - bupfile.Extension.Length) + ".ifo"));
if (bupfile.Length != ifofile.Length)
{
protections.Enqueue("DVD-Movie-PROTECT (Unconfirmed - Please report to us on Github)");
protections.Add("DVD-Movie-PROTECT (Unconfirmed - Please report to us on Github)");
break;
}
}

View File

@@ -1,10 +1,9 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -28,7 +27,6 @@ namespace BinaryObjectScanner.Protection
public class Denuvo : IPathCheck, IPortableExecutableCheck
{
// TODO: Investigate possible filename checks for Denuvo Anti-Tamper.
// https://www.pcgamingwiki.com/wiki/Denuvo#Redeem.exe
@@ -265,32 +263,28 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// Found in Doom Eternal Update 1 (Steam Depot 782332, Manifest 7064393210727378308).
// These files are automatically installed into an "Denuvo Anti-Cheat" folder when the game is installed.
new(new PathMatch("denuvo-anti-cheat.sys", useEndsWith: true), "Denuvo Anti-Cheat"),
new(new PathMatch("denuvo-anti-cheat-update-service.exe", useEndsWith: true), "Denuvo Anti-Cheat"),
new(new PathMatch("denuvo-anti-cheat-runtime.dll", useEndsWith: true), "Denuvo Anti-Cheat"),
new(new FilePathMatch("denuvo-anti-cheat.sys"), "Denuvo Anti-Cheat"),
new(new FilePathMatch("denuvo-anti-cheat-update-service.exe"), "Denuvo Anti-Cheat"),
new(new FilePathMatch("denuvo-anti-cheat-runtime.dll"), "Denuvo Anti-Cheat"),
// This file is a renamed copy of "denuvo-anti-cheat-update-service.exe" which is only seen in the folder of the main game executable after it has been run, but before Denuvo Anti-Cheat is finished installing.
new(new PathMatch("Denuvo Anti-Cheat Installer.exe", useEndsWith: true), "Denuvo Anti-Cheat"),
new(new FilePathMatch("Denuvo Anti-Cheat Installer.exe"), "Denuvo Anti-Cheat"),
// Found in the Denuvo Anti-Cheat installer on their support website. (https://web.archive.org/web/20240130142033/https://support.codefusion.technology/anti-cheat/?l=ja&s=ac&e=2009)
new(new PathMatch("denuvo-anti-cheat-installer.zip", useEndsWith: true), "Denuvo Anti-Cheat"),
new(new FilePathMatch("denuvo-anti-cheat-installer.zip"), "Denuvo Anti-Cheat"),
// Found in "denuvo-anti-cheat-installer.zip".
new(new PathMatch("Denuvo-Anti-Cheat_install_run_as_Admin.bat", useEndsWith: true), "Denuvo Anti-Cheat"),
new(new PathMatch("denuvo-anti-cheat-crash-report.exe", useEndsWith: true), "Denuvo Anti-Cheat"),
new(new PathMatch("denuvo-anti-cheat-crash-report.exe.config", useEndsWith: true), "Denuvo Anti-Cheat"),
new(new PathMatch("denuvo-anti-cheat-update-service-launcher.dll", useEndsWith: true), "Denuvo Anti-Cheat"),
new(new FilePathMatch("Denuvo-Anti-Cheat_install_run_as_Admin.bat"), "Denuvo Anti-Cheat"),
new(new FilePathMatch("denuvo-anti-cheat-crash-report.exe"), "Denuvo Anti-Cheat"),
new(new FilePathMatch("denuvo-anti-cheat-crash-report.exe.config"), "Denuvo Anti-Cheat"),
new(new FilePathMatch("denuvo-anti-cheat-update-service-launcher.dll"), "Denuvo Anti-Cheat"),
};
return MatchUtil.GetAllMatches(files, matchers, any: false);
@@ -304,21 +298,21 @@ namespace BinaryObjectScanner.Protection
// Found in Doom Eternal Update 1 (Steam Depot 782332, Manifest 7064393210727378308).
// These files are automatically installed into an "Denuvo Anti-Cheat" folder when the game is installed.
new(new PathMatch("denuvo-anti-cheat.sys", useEndsWith: true), "Denuvo Anti-Cheat"),
new(new PathMatch("denuvo-anti-cheat-update-service.exe", useEndsWith: true), "Denuvo Anti-Cheat"),
new(new PathMatch("denuvo-anti-cheat-runtime.dll", useEndsWith: true), "Denuvo Anti-Cheat"),
new(new FilePathMatch("denuvo-anti-cheat.sys"), "Denuvo Anti-Cheat"),
new(new FilePathMatch("denuvo-anti-cheat-update-service.exe"), "Denuvo Anti-Cheat"),
new(new FilePathMatch("denuvo-anti-cheat-runtime.dll"), "Denuvo Anti-Cheat"),
// This file is a renamed copy of "denuvo-anti-cheat-update-service.exe" which is only seen in the folder of the main game executable after it has been run, but before Denuvo Anti-Cheat is finished installing.
new(new PathMatch("Denuvo Anti-Cheat Installer.exe", useEndsWith: true), "Denuvo Anti-Cheat"),
new(new FilePathMatch("Denuvo Anti-Cheat Installer.exe"), "Denuvo Anti-Cheat"),
// Found in the Denuvo Anti-Cheat installer on their support website. (https://web.archive.org/web/20240130142033/https://support.codefusion.technology/anti-cheat/?l=ja&s=ac&e=2009)
new(new PathMatch("denuvo-anti-cheat-installer.zip", useEndsWith: true), "Denuvo Anti-Cheat"),
new(new FilePathMatch("denuvo-anti-cheat-installer.zip"), "Denuvo Anti-Cheat"),
// Found in "denuvo-anti-cheat-installer.zip".
new(new PathMatch("Denuvo-Anti-Cheat_install_run_as_Admin.bat", useEndsWith: true), "Denuvo Anti-Cheat"),
new(new PathMatch("denuvo-anti-cheat-crash-report.exe", useEndsWith: true), "Denuvo Anti-Cheat"),
new(new PathMatch("denuvo-anti-cheat-crash-report.exe.config", useEndsWith: true), "Denuvo Anti-Cheat"),
new(new PathMatch("denuvo-anti-cheat-update-service-launcher.dll", useEndsWith: true), "Denuvo Anti-Cheat"),
new(new FilePathMatch("Denuvo-Anti-Cheat_install_run_as_Admin.bat"), "Denuvo Anti-Cheat"),
new(new FilePathMatch("denuvo-anti-cheat-crash-report.exe"), "Denuvo Anti-Cheat"),
new(new FilePathMatch("denuvo-anti-cheat-crash-report.exe.config"), "Denuvo Anti-Cheat"),
new(new FilePathMatch("denuvo-anti-cheat-update-service-launcher.dll"), "Denuvo Anti-Cheat"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);

View File

@@ -1,10 +1,7 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -55,11 +52,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,10 +1,8 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
namespace BinaryObjectScanner.Protection
{
@@ -24,24 +22,20 @@ namespace BinaryObjectScanner.Protection
// https://www.gamecopyworld.com/games/pc_pc_calcio_2000.shtml
// https://www.gamecopyworld.com/games/pc_pc_futbol_2000.shtml
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// Many more checks are likely possible based on the sources, but only ones that have been personally verified are getting added.
// Uncopyable files found in at least http://redump.org/disc/70531/, and likely in multiple others.
new(new PathMatch(Path.Combine("XCONTROL", "COMPPLAY._01").Replace("\\", "/"), useEndsWith: true), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new PathMatch(Path.Combine("XCONTROL", "LANDER.DA0").Replace("\\", "/"), useEndsWith: true), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new PathMatch(Path.Combine("XCONTROL", "XSMGOP.DAP").Replace("\\", "/"), useEndsWith: true), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new PathMatch(Path.Combine("XCONTROL", "XSMGOP.VBX").Replace("\\", "/"), useEndsWith: true), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new FilePathMatch(Path.Combine("XCONTROL", "COMPPLAY._01")), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new FilePathMatch(Path.Combine("XCONTROL", "LANDER.DA0")), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new FilePathMatch(Path.Combine("XCONTROL", "XSMGOP.DAP")), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new FilePathMatch(Path.Combine("XCONTROL", "XSMGOP.VBX")), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
// Copyable file found in http://redump.org/disc/70531/ that seems to be exclusively associated with the protection and other files that are part of the protection.
new(new PathMatch(Path.Combine("XCONTROL", "COMPSCO._01").Replace("\\", "/"), useEndsWith: true), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new FilePathMatch(Path.Combine("XCONTROL", "COMPSCO._01")), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
@@ -55,15 +49,15 @@ namespace BinaryObjectScanner.Protection
// Many more checks are likely possible based on the sources, but only ones that have been personally verified are getting added.
// Uncopyable files found in at least http://redump.org/disc/70531/, and likely in multiple others.
new(new PathMatch("2kscore.sc0", useEndsWith: true), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new PathMatch("arrcalc.obj", useEndsWith: true), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new PathMatch("bdrvisa.drv", useEndsWith: true), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new PathMatch("gprinter.dll", useEndsWith: true), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new PathMatch("hstadium.ipx", useEndsWith: true), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new PathMatch("omanager.odl", useEndsWith: true), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new PathMatch("opublic.001", useEndsWith: true), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new PathMatch("spland.sc0", useEndsWith: true), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new PathMatch("uqprime.ipx", useEndsWith: true), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new FilePathMatch("2kscore.sc0"), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new FilePathMatch("arrcalc.obj"), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new FilePathMatch("bdrvisa.drv"), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new FilePathMatch("gprinter.dll"), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new FilePathMatch("hstadium.ipx"), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new FilePathMatch("omanager.odl"), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new FilePathMatch("opublic.001"), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new FilePathMatch("spland.sc0"), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
new(new FilePathMatch("uqprime.ipx"), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);

View File

@@ -1,12 +1,11 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -139,34 +138,30 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// Found together in seemingly every DiscGuard game (Redump entries 31914, 46743, 46961, 79284, and 79374).
new(new List<PathMatch>
{
new(
[
new FilePathMatch("IOSLINK.VXD"),
new FilePathMatch("IOSLINK.SYS"),
}, "DiscGuard"),
], "DiscGuard"),
// Found together in one DiscGuard game (Redump entry 31914).
new(new List<PathMatch>
{
new(
[
new FilePathMatch("TTR1.DLL"),
new FilePathMatch("TTR2.DLL"),
}, "DiscGuard"),
], "DiscGuard"),
// Found together in most DiscGuard games (Redump entries 46743, 46961, 79284, and 79374).
new(new List<PathMatch>
{
new(
[
new FilePathMatch("T111.DLL"),
new FilePathMatch("T222.DLL"),
}, "DiscGuard"),
], "DiscGuard"),
};
return MatchUtil.GetAllMatches(files, matchers, any: false);
@@ -189,7 +184,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
private string GetVersion(PortableExecutable pex)
private static string GetVersion(PortableExecutable pex)
{
// Check the internal versions
var version = pex.GetInternalVersion();
@@ -214,7 +209,7 @@ namespace BinaryObjectScanner.Protection
return string.Empty;
}
private string GetInternalVersion(string firstMatchedString)
private static string GetInternalVersion(string firstMatchedString)
{
try
{

View File

@@ -1,9 +1,7 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -48,11 +46,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,9 +1,7 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -82,11 +80,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
// TODO: Search for the presence of the folder "EasyAntiCheat" specifically, which is present in every checked version so far.
var matchers = new List<PathMatchSet>

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;

View File

@@ -1,11 +1,9 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -53,11 +51,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,9 +1,7 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
namespace BinaryObjectScanner.Protection
{
@@ -17,11 +15,7 @@ namespace BinaryObjectScanner.Protection
// TODO: Add an MS-DOS executable check for "FREELOCK.EXE".
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
@@ -47,11 +41,11 @@ namespace BinaryObjectScanner.Protection
new(new FilePathMatch("FREELOCK.13"), "Freelock 1.3"),
// Found in "FREELOCK.IMG" From Freelock 1.3.
new(new List<PathMatch>
{
new(
[
new FilePathMatch("FREELOCK.13"),
new FilePathMatch("FL.DAT"),
}, "Freelock 1.3"),
], "Freelock 1.3"),
};
return MatchUtil.GetAllMatches(files, matchers, any: false);

View File

@@ -1,14 +1,12 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.ProtectionType
namespace BinaryObjectScanner.Protection
{
public class GFWL : IPathCheck, IPortableExecutableCheck
{
@@ -38,11 +36,7 @@ namespace BinaryObjectScanner.ProtectionType
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,10 +1,8 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -41,11 +39,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,11 +1,9 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -70,39 +68,35 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// "Start_Here.exe" is the default name used in HexaLock AutoLock 4.5.
new(new List<PathMatch>
{
new(
[
new FilePathMatch("Start_Here.exe"),
new FilePathMatch("MFINT.DLL"),
new FilePathMatch("MFIMP.DLL"),
}, "Hexalock AutoLock 4.5"),
], "Hexalock AutoLock 4.5"),
// Used for PDF protection in HexaLock AutoLock 4.7. "Start.exe" likely has some internal strings that can be checked.
new(new List<PathMatch>
{
new(
[
new FilePathMatch("kleft.ipf"),
new FilePathMatch("ReadPFile.exe"),
new FilePathMatch("Start.exe"),
}, "HexaLock AutoLock 4.7 PDF DRM"),
], "HexaLock AutoLock 4.7 PDF DRM"),
// Should be present in all known versions.
new(new List<PathMatch>
{
new(
[
new FilePathMatch("MFINT.DLL"),
new FilePathMatch("MFIMP.DLL"),
}, "HexaLock AutoLock"),
], "HexaLock AutoLock"),
// Found inside the file typically named "Start_Here.exe" in version 4.5.
new(new PathMatch("HCPSMng.exe"), "HexaLock AutoLock 4.5"),
new(new FilePathMatch("HCPSMng.exe"), "HexaLock AutoLock 4.5"),
};
return MatchUtil.GetAllMatches(files, matchers, any: false);

View File

@@ -1,11 +1,9 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -56,11 +54,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,9 +1,7 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
namespace BinaryObjectScanner.Protection
{
@@ -14,11 +12,7 @@ namespace BinaryObjectScanner.Protection
public class IndyVCD : IPathCheck
{
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
// TODO: Verify if these are OR or AND
var matchers = new List<PathMatchSet>

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection

View File

@@ -0,0 +1,83 @@
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
{
/// <summary>
/// Kalypso Launcher is a launcher used by Kalypso Media games. It is responsible for game activation via product keys.
/// Several Kalypso developed games are available on Steam, but the launcher isn't able to be (officially) disabled: https://www.reddit.com/r/RailwayEmpire/comments/nktojh/skip_kalypso_launcher_from_steam/
/// Assumed to be present on all Kalypso Media games on PC since at least 2011 (as it is present in Redump entry 95617), though this needs to be confirmed.
/// The internal name of the Kalypso Launcher may be "Styx", as it is present as the File Description and Product Name in various versions of "KalypsoLauncher.dll".
/// Kalypso FAQ, which includes information about Kalypso Launcher: https://www.kalypsomedia.com/us/frequently-asked-questions
/// It was introduced in or before January 2011, based on this forum post introducing it: https://web.archive.org/web/20120524150700/http://forum.kalypsomedia.com/showthread.php?tid=7909
///
/// Known versions:
/// 1.2.0.12: Found in Redump entry 95617.
/// 2.0.4.2: Newest version as of 3/10/2024, downloaded from updating the installed game from Redump entry 95617.
/// </summary>
public class KalypsoLauncher : IPathCheck, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
// TODO: Investigate if there are any viable checks for the game EXE itself.
// "Styx" is found as the File Description and Product Name in "KalypsoLauncher.dll", but checks aren't included due to the risk of false positives.
var name = pex.InternalName;
// Found in "KalypsoLauncher.dll" in Redump entry 95617.
if (name?.Contains("KalypsoLauncher.dll") == true)
return $"Kalypso Launcher {pex.GetInternalVersion()}";
name = pex.OriginalFilename;
// Found in "KalypsoLauncher.dll" in Redump entry 95617.
if (name?.Contains("KalypsoLauncher.dll") == true)
return $"Kalypso Launcher {pex.GetInternalVersion()}";
// Get the .text section strings, if they exist
var strs = pex.GetFirstSectionStrings(".rdata");
if (strs != null)
{
// Found in "TFT.exe" in Redump entry 95617.
if (strs.Any(s => s.Contains("@KalypsoLauncherXml")))
return "Kalypso Launcher";
}
return null;
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// Found in Redump entry 95617.
new(new FilePathMatch("KalypsoLauncher.dll"), "Kalypso Launcher"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string? CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
// Found in Redump entry 95617.
new(new FilePathMatch("KalypsoLauncher.dll"), "Kalypso Launcher"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
}
}

View File

@@ -1,6 +1,7 @@
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
namespace BinaryObjectScanner.Protection
{

View File

@@ -1,12 +1,10 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -51,33 +49,29 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// All found to be present on at multiple albums with LabelGate CD2 (Redump entry 95010 and product ID SVWC-7185), the original version of LabelGate still needs to be investigated.
new(new List<PathMatch>
{
new(
[
#if NET20 || NET35
new(Path.Combine(Path.Combine("BIN", "WIN32"), "MQ2SETUP.EXE")),
new(Path.Combine(Path.Combine("BIN", "WIN32"), "MQSTART.EXE")),
new FilePathMatch(Path.Combine(Path.Combine("BIN", "WIN32"), "MQ2SETUP.EXE")),
new FilePathMatch(Path.Combine(Path.Combine("BIN", "WIN32"), "MQSTART.EXE")),
#else
new(Path.Combine("BIN", "WIN32", "MQ2SETUP.EXE")),
new(Path.Combine("BIN", "WIN32", "MQSTART.EXE")),
new FilePathMatch(Path.Combine("BIN", "WIN32", "MQ2SETUP.EXE")),
new FilePathMatch(Path.Combine("BIN", "WIN32", "MQSTART.EXE")),
#endif
}, "LabelGate CD2 Media Player"),
], "LabelGate CD2 Media Player"),
// All of these are also found present on all known LabelGate CD2 releases, though an additional file "RESERVED.DAT" is found in the same directory in at least one release (Product ID SVWC-7185)
new(new List<PathMatch>
{
new(Path.Combine("MQDISC", "LICENSE.TXT")),
new(Path.Combine("MQDISC", "MQDISC.INI")),
new(Path.Combine("MQDISC", "START.INI")),
}, "LabelGate CD2"),
new(
[
new FilePathMatch(Path.Combine("MQDISC", "LICENSE.TXT")),
new FilePathMatch(Path.Combine("MQDISC", "MQDISC.INI")),
new FilePathMatch(Path.Combine("MQDISC", "START.INI")),
], "LabelGate CD2"),
};
return MatchUtil.GetAllMatches(files, matchers, any: false);

View File

@@ -1,12 +1,10 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -113,11 +111,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
@@ -126,12 +120,12 @@ namespace BinaryObjectScanner.Protection
// TODO: Verify if these are OR or AND
new(new FilePathMatch("NOMOUSE.SP"), GetVersion16Bit, "LaserLok [Check disc for physical ring]"),
new(new FilePathMatch("NOMOUSE.COM"), "LaserLok [Check disc for physical ring]"),
new(new PathMatch("l16dll.dll", useEndsWith: true), "LaserLok [Check disc for physical ring]"),
new(new PathMatch("laserlok.in", useEndsWith: true), "LaserLok [Check disc for physical ring]"),
new(new PathMatch("laserlok.o10", useEndsWith: true), "LaserLok [Check disc for physical ring]"),
new(new PathMatch("laserlok.o11", useEndsWith: true), "LaserLok [Check disc for physical ring]"),
new(new PathMatch("laserlok.o12", useEndsWith: true), "LaserLok [Check disc for physical ring]"),
new(new PathMatch("laserlok.out", useEndsWith: true), "LaserLok [Check disc for physical ring]"),
new(new FilePathMatch("l16dll.dll"), "LaserLok [Check disc for physical ring]"),
new(new FilePathMatch("laserlok.in"), "LaserLok [Check disc for physical ring]"),
new(new FilePathMatch("laserlok.o10"), "LaserLok [Check disc for physical ring]"),
new(new FilePathMatch("laserlok.o11"), "LaserLok [Check disc for physical ring]"),
new(new FilePathMatch("laserlok.o12"), "LaserLok [Check disc for physical ring]"),
new(new FilePathMatch("laserlok.out"), "LaserLok [Check disc for physical ring]"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
@@ -146,12 +140,12 @@ namespace BinaryObjectScanner.Protection
// TODO: Verify if these are OR or AND
new(new FilePathMatch("NOMOUSE.COM"), "LaserLok [Check disc for physical ring]"),
new(new PathMatch("l16dll.dll", useEndsWith: true), "LaserLok [Check disc for physical ring]"),
new(new PathMatch("laserlok.in", useEndsWith: true), "LaserLok [Check disc for physical ring]"),
new(new PathMatch("laserlok.o10", useEndsWith: true), "LaserLok [Check disc for physical ring]"),
new(new PathMatch("laserlok.o11", useEndsWith: true), "LaserLok [Check disc for physical ring]"),
new(new PathMatch("laserlok.o12", useEndsWith: true), "LaserLok [Check disc for physical ring]"),
new(new PathMatch("laserlok.out", useEndsWith: true), "LaserLok [Check disc for physical ring]"),
new(new FilePathMatch("l16dll.dll"), "LaserLok [Check disc for physical ring]"),
new(new FilePathMatch("laserlok.in"), "LaserLok [Check disc for physical ring]"),
new(new FilePathMatch("laserlok.o10"), "LaserLok [Check disc for physical ring]"),
new(new FilePathMatch("laserlok.o11"), "LaserLok [Check disc for physical ring]"),
new(new FilePathMatch("laserlok.o12"), "LaserLok [Check disc for physical ring]"),
new(new FilePathMatch("laserlok.out"), "LaserLok [Check disc for physical ring]"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);

View File

@@ -1,10 +1,8 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -150,11 +148,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, IEnumerable{string})"/>
#if NET20 || NET35
internal Queue<string> CDillaCheckDirectoryPath(string path, IEnumerable<string>? files)
#else
internal ConcurrentQueue<string> CDillaCheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
internal IEnumerable<string> CDillaCheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,12 +1,10 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -66,11 +64,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, IEnumerable{string})"/>
#if NET20 || NET35
internal Queue<string> CactusDataShieldCheckDirectoryPath(string path, IEnumerable<string>? files)
#else
internal ConcurrentQueue<string> CactusDataShieldCheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
internal IEnumerable<string> CactusDataShieldCheckDirectoryPath(string path, IEnumerable<string>? files)
{
// TODO: Verify if these are OR or AND
var matchers = new List<PathMatchSet>

View File

@@ -1,11 +1,8 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -72,24 +69,20 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, IEnumerable{string})"/>
#if NET20 || NET35
internal Queue<string> FLEXNetCheckDirectoryPath(string path, IEnumerable<string>? files)
#else
internal ConcurrentQueue<string> FLEXNetDirectoryPath(string path, IEnumerable<string>? files)
#endif
internal IEnumerable<string> FLEXNetCheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// Found in IA item "prog-17_202403".
new(new PathMatch("FlexLM-6.1F", useEndsWith: true), "FlexLM 6.1f"),
new(new PathMatch("FlexLM", useEndsWith: true), "FlexLM"),
new(new PathMatch("FLexLM_Licensing.wri", useEndsWith: true), "FlexLM"),
new(new PathMatch("LMGR326B.DLL", useEndsWith: true), "FlexLM"),
new(new PathMatch("FLEXLM.CPL", useEndsWith: true), "FlexLM"),
new(new PathMatch("LMGRD.EXE", useEndsWith: true), "FlexLM"),
new(new PathMatch("LMGRD95.EXE", useEndsWith: true), "FlexLM"),
new(new PathMatch("LMUTIL.EXE", useEndsWith: true), "FlexLM"),
new(new PathMatch("READFLEX.WRI", useEndsWith: true), "FlexLM"),
new(new FilePathMatch("FlexLM-6.1F"), "FlexLM 6.1f"),
new(new FilePathMatch("FlexLM"), "FlexLM"),
new(new FilePathMatch("FLexLM_Licensing.wri"), "FlexLM"),
new(new FilePathMatch("LMGR326B.DLL"), "FlexLM"),
new(new FilePathMatch("FLEXLM.CPL"), "FlexLM"),
new(new FilePathMatch("LMGRD.EXE"), "FlexLM"),
new(new FilePathMatch("LMGRD95.EXE"), "FlexLM"),
new(new FilePathMatch("LMUTIL.EXE"), "FlexLM"),
new(new FilePathMatch("READFLEX.WRI"), "FlexLM"),
};
return MatchUtil.GetAllMatches(files, matchers, any: false);
@@ -101,15 +94,15 @@ namespace BinaryObjectScanner.Protection
var matchers = new List<PathMatchSet>
{
// Found in IA item "prog-17_202403".
new(new PathMatch("FlexLM-6.1F", useEndsWith: true), "FlexLM 6.1f"),
new(new PathMatch("FlexLM", useEndsWith: true), "FlexLM"),
new(new PathMatch("FLexLM_Licensing.wri", useEndsWith: true), "FlexLM"),
new(new PathMatch("LMGR326B.DLL", useEndsWith: true), "FlexLM"),
new(new PathMatch("FLEXLM.CPL", useEndsWith: true), "FlexLM"),
new(new PathMatch("LMGRD.EXE", useEndsWith: true), "FlexLM"),
new(new PathMatch("LMGRD95.EXE", useEndsWith: true), "FlexLM"),
new(new PathMatch("LMUTIL.EXE", useEndsWith: true), "FlexLM"),
new(new PathMatch("READFLEX.WRI", useEndsWith: true), "FlexLM"),
new(new FilePathMatch("FlexLM-6.1F"), "FlexLM 6.1f"),
new(new FilePathMatch("FlexLM"), "FlexLM"),
new(new FilePathMatch("FLexLM_Licensing.wri"), "FlexLM"),
new(new FilePathMatch("LMGR326B.DLL"), "FlexLM"),
new(new FilePathMatch("FLEXLM.CPL"), "FlexLM"),
new(new FilePathMatch("LMGRD.EXE"), "FlexLM"),
new(new FilePathMatch("LMGRD95.EXE"), "FlexLM"),
new(new FilePathMatch("LMUTIL.EXE"), "FlexLM"),
new(new FilePathMatch("READFLEX.WRI"), "FlexLM"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);

View File

@@ -1,11 +1,9 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.IO;
using SabreTools.Hashing;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -61,20 +59,16 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, IEnumerable{string})"/>
#if NET20 || NET35
internal Queue<string> RipGuardCheckDirectoryPath(string path, IEnumerable<string>? files)
#else
internal ConcurrentQueue<string> RipGuardCheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
internal IEnumerable<string> RipGuardCheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// Found in the Black Lagoon Season 1 DVD steelbook box set (Geneon ID 12970).
new(new PathMatch("G23YHWO1.EXE", useEndsWith: true), "RipGuard"),
new(new PathMatch("RGASDEV.SYS", useEndsWith: true), "RipGuard"),
new(new FilePathMatch("G23YHWO1.EXE"), "RipGuard"),
new(new FilePathMatch("RGASDEV.SYS"), "RipGuard"),
// Mentioned online in https://forum.redfox.bz/threads/resolved-one-on-one-with-tony-horton-vol2-disc3.33901/.
new(new PathMatch("9KMJ9G4I.EXE", useEndsWith: true), "RipGuard (Unconfirmed - Please report to us on GitHub)"),
new(new FilePathMatch("9KMJ9G4I.EXE"), "RipGuard (Unconfirmed - Please report to us on GitHub)"),
};
return MatchUtil.GetAllMatches(files, matchers, any: false);
@@ -86,11 +80,11 @@ namespace BinaryObjectScanner.Protection
var matchers = new List<PathMatchSet>
{
// Found in the Black Lagoon Season 1 DVD steelbook box set (Geneon ID 12970).
new(new PathMatch("G23YHWO1.EXE", useEndsWith: true), "RipGuard"),
new(new PathMatch("RGASDEV.SYS", useEndsWith: true), "RipGuard"),
new(new FilePathMatch("G23YHWO1.EXE"), "RipGuard"),
new(new FilePathMatch("RGASDEV.SYS"), "RipGuard"),
// Mentioned online in https://forum.redfox.bz/threads/resolved-one-on-one-with-tony-horton-vol2-disc3.33901/.
new(new PathMatch("9KMJ9G4I.EXE", useEndsWith: true), "RipGuard (Unconfirmed - Please report to us on GitHub)"),
new(new FilePathMatch("9KMJ9G4I.EXE"), "RipGuard (Unconfirmed - Please report to us on GitHub)"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);

View File

@@ -1,11 +1,10 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -13,6 +12,8 @@ namespace BinaryObjectScanner.Protection
/// <summary>
/// SafeCast is in the same family of protections as SafeDisc, and appears to mainly be for license management, and doesn't appear to affect the mastering of the disc in any way.
/// 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).
/// SafeCast has been confirmed to be present on some programs, such as AutoDesk 3ds Max (IA items CMCD0204 and game-programming-in-c-start-to-finish-2006), Photoshop CS2 (IA item ccd0605), and Boonty Box (IA items PC_Gamer_Disc_7.55_July_2005 and cdrom-pcgamercd7.58).
/// TODO: Check Boonty Box samples closer for new possible detections, there are at least more checks for FlexLM possible.
/// 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
@@ -78,6 +79,7 @@ namespace BinaryObjectScanner.Protection
// TODO: Investigate import hint/name table entry "CdaSysInstall"
// TODO: Investigate string table entries: "CDWP02DG", "CDWP02DG", "CDWS02DG"
// TODO: Invesitgate if the "AdobeLM.dll" file (along with mentions of "AdobeLM" in executables) uniquely identifies SafeCast, or if it can be used with different DRM. (Found in IA item ccd0605)
// Get the import directory table, if it exists
if (pex.Model.ImportTable?.ImportDirectoryTable != null)
@@ -146,11 +148,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, IEnumerable{string})"/>
#if NET20 || NET35
internal Queue<string> SafeCastCheckDirectoryPath(string path, IEnumerable<string>? files)
#else
internal ConcurrentQueue<string> SafeCastCheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
internal IEnumerable<string> SafeCastCheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,12 +1,10 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SabreTools.Hashing;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -129,55 +127,51 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, IEnumerable{string})"/>
#if NET20 || NET35
internal Queue<string> SafeDiscCheckDirectoryPath(string path, IEnumerable<string>? files)
#else
internal ConcurrentQueue<string> SafeDiscCheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
internal IEnumerable<string> SafeDiscCheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
new(new List<PathMatch>
{
new(
[
new FilePathMatch("CLCD16.DLL"),
new FilePathMatch("CLCD32.DLL"),
new FilePathMatch("CLOKSPL.EXE"),
new(".icd", useEndsWith: true),
}, "SafeDisc 1/Lite"),
new PathMatch(".icd", useEndsWith: true),
], "SafeDisc 1/Lite"),
// Check for the original filename used for the SafeDisc splash-screens, new file names are used in later versions.
new(new List<PathMatch>
{
new(
[
new FilePathMatch("00000001.TMP"),
new FilePathMatch("SPLSH16.BMP"),
new FilePathMatch("SPLSH256.BMP"),
}, "SafeDisc 1.00.025-1.01.044"),
], "SafeDisc 1.00.025-1.01.044"),
new(new List<PathMatch>
{
new(
[
new FilePathMatch("00000001.TMP"),
// The .016 and .256 files are banners stored in the BMP image format. The 016 and 256 refers to the color depth of the BMP.
// There are common file names used, such as 00000407.XXX and 00000409.XXX. Further investigation is needed to determine the consistency of these names.
new(".016", useEndsWith: true),
new(".256", useEndsWith: true),
}, "SafeDisc 1.06.000-3.20.024"),
new PathMatch(".016", useEndsWith: true),
new PathMatch(".256", useEndsWith: true),
], "SafeDisc 1.06.000-3.20.024"),
new(new List<PathMatch>
{
new(
[
new FilePathMatch("00000001.TMP"),
// The .016 files stop being used as of 4.00.000, while the .256 remain in fairly consistent use.
new(".256", useEndsWith: true),
}, "SafeDisc 1.06.000+"),
new PathMatch(".256", useEndsWith: true),
], "SafeDisc 1.06.000+"),
// The file "mcp.dll" is known to only be used in a specific version range for SafeDisc, but is currently only used in a grouped file name check with other SafeDisc files to prevent false positives.
// Found in Redump entries 28810, 30555, 55078, and 62935.
new(new List<PathMatch>
{
new(
[
new FilePathMatch("00000001.TMP"),
new FilePathMatch("drvmgt.dll"),
new FilePathMatch("mcp.dll"),
new FilePathMatch("secdrv.sys"),
}, "SafeDisc 1.45.011-1.50.020"),
], "SafeDisc 1.45.011-1.50.020"),
// Search for the splash screen files known to sometimes contain a generic SafeDisc splash-screen.
new(new FilePathMatch("00000000.016"), GetSafeDiscSplshVersion, "SafeDisc"),

View File

@@ -1,14 +1,12 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Utilities;
using SabreTools.IO.Extensions;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -69,6 +67,9 @@ namespace BinaryObjectScanner.Protection
// 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.
// Almost every single sample known has both sections, though one only contains the "stxt371" section. It is unknown if this is intentional, or if the game functions without it.
// It is present in the "Texas HoldEm!" game in "boontybox_PCGamer_DVD.exe" in IA items PC_Gamer_Disc_7.55_July_2005 and cdrom-pcgamercd7.58.
// Other games in this set also aren't functional despite having the normal layout of stxt sections, and the primary program doesn't install at all due to activation servers being down.
bool stxt371Section = pex.ContainsSection("stxt371", exact: true);
bool stxt774Section = pex.ContainsSection("stxt774", exact: true);
if (stxt371Section || stxt774Section)
@@ -164,80 +165,44 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
#if NET20 || NET35
var results = new Queue<string>();
#else
var results = new ConcurrentQueue<string>();
#endif
var results = new List<string>();
// Run Macrovision directory checks
var macrovision = MacrovisionCheckDirectoryPath(path, files);
#if NET20 || NET35
if (macrovision != null && macrovision.Count > 0)
#else
if (macrovision != null && !macrovision.IsEmpty)
#endif
if (macrovision != null)
results.AddRange(macrovision);
// Run Cactus Data Shield directory checks
var cactusDataShield = CactusDataShieldCheckDirectoryPath(path, files);
#if NET20 || NET35
if (cactusDataShield != null && cactusDataShield.Count > 0)
#else
if (cactusDataShield != null && !cactusDataShield.IsEmpty)
#endif
if (cactusDataShield != null)
results.AddRange(cactusDataShield);
// Run C-Dilla directory checks
var cDilla = CDillaCheckDirectoryPath(path, files);
#if NET20 || NET35
if (cDilla != null && cDilla.Count > 0)
#else
if (cDilla != null && !cDilla.IsEmpty)
#endif
if (cDilla != null)
results.AddRange(cDilla);
// Run RipGuard directory checks
var ripGuard = RipGuardCheckDirectoryPath(path, files);
#if NET20 || NET35
if (ripGuard != null && ripGuard.Count > 0)
#else
if (ripGuard != null && !ripGuard.IsEmpty)
#endif
if (ripGuard != null)
results.AddRange(ripGuard);
// Run SafeCast directory checks
var safeCast = SafeCastCheckDirectoryPath(path, files);
#if NET20 || NET35
if (safeCast != null && safeCast.Count > 0)
#else
if (safeCast != null && !safeCast.IsEmpty)
#endif
if (safeCast != null)
results.AddRange(safeCast);
// Run SafeDisc directory checks
var safeDisc = SafeDiscCheckDirectoryPath(path, files);
#if NET20 || NET35
if (safeDisc != null && safeDisc.Count > 0)
#else
if (safeDisc != null && !safeDisc.IsEmpty)
#endif
if (safeDisc != null)
results.AddRange(safeDisc);
if (results != null && results.Count > 0)
return results;
#if NET20 || NET35
return new Queue<string>();
#else
return new ConcurrentQueue<string>();
#endif
return [];
}
/// <inheritdoc/>
@@ -284,15 +249,11 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc cref="IPathCheck.CheckDirectoryPath(string, IEnumerable{string})"/>
#if NET20 || NET35
internal Queue<string> MacrovisionCheckDirectoryPath(string path, IEnumerable<string>? files)
#else
internal ConcurrentQueue<string> MacrovisionCheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
internal IEnumerable<string> MacrovisionCheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
new(new PathMatch("00000001.TMP", useEndsWith: true), Get00000001TMPVersion, string.Empty),
new(new FilePathMatch("00000001.TMP"), Get00000001TMPVersion, string.Empty),
new(new FilePathMatch("secdrv.sys"), GetSecdrvFileSizeVersion, "Macrovision Security Driver"),
};
@@ -304,7 +265,7 @@ namespace BinaryObjectScanner.Protection
{
var matchers = new List<PathMatchSet>
{
new(new PathMatch("00000001.TMP", useEndsWith: true), Get00000001TMPVersion, string.Empty),
new(new FilePathMatch("00000001.TMP"), Get00000001TMPVersion, string.Empty),
new(new FilePathMatch("secdrv.sys"), GetSecdrvFileSizeVersion, "Macrovision Security Driver"),
};
@@ -431,7 +392,7 @@ namespace BinaryObjectScanner.Protection
}
// TODO: Combine with filesize version checks if possible.
private string GetSecDrvExecutableVersion(PortableExecutable pex)
private static 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.
@@ -473,7 +434,7 @@ namespace BinaryObjectScanner.Protection
return "Unknown Version (Report this to us on GitHub)";
}
private string? CheckSectionForProtection(string file, bool includeDebug, List<string>? sectionStrings, byte[]? sectionRaw, bool newVersion)
private static string? CheckSectionForProtection(string file, bool includeDebug, List<string>? sectionStrings, byte[]? sectionRaw, bool newVersion)
{
// Get the section strings, if they exist
if (sectionStrings != null)
@@ -561,11 +522,19 @@ namespace BinaryObjectScanner.Protection
or "2.11.060"
or "2.16.050"
// Found in IA item CMCD0204 (Software/Demo/3DSMax/3dsmax6.exe).
or "2.20.030"
// Found in Redump entry 90157 / IA item microsoft-software-jukebox-usa-hp-oem.
or "2.41.000"
// Source not documented.
or "2.60.030"
// Found in IA item game-programming-in-c-start-to-finish-2006 (tools_install/3dsMax8_Demo.zip).
or "2.66.000"
// Found in Photoshop CS2 in IA item ccd0605.
or "2.67.010" => "SafeCast",
// SafeCast (Unconfirmed)

View File

@@ -1,10 +1,8 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -39,18 +37,14 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// The file "sunncomm.ico" was a previously used file check, but since it's just an icon of the SunnComm logo, it seems too likely to result in false positives.
// Found on "Charley Pride - A Tribute to Jim Reeves" (barcode "7 816190222-2 4").
new(new PathMatch("scvfy.exe", useEndsWith: true), "MediaCloQ"),
new(new FilePathMatch("scvfy.exe"), "MediaCloQ"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
@@ -64,7 +58,7 @@ namespace BinaryObjectScanner.Protection
// The file "sunncomm.ico" was a previously used file check, but since it's just an icon of the SunnComm logo, it seems too likely to result in false positives.
// Found on "Charley Pride - A Tribute to Jim Reeves" (barcode "7 816190222-2 4").
new(new PathMatch("scvfy.exe", useEndsWith: true), "MediaCloQ"),
new(new FilePathMatch("scvfy.exe"), "MediaCloQ"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);

View File

@@ -1,22 +1,20 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
{
/// <summary>
/// MediaMax CD-3 is a copy protection for audio CDs created by SunnComm, which once installed, restricted users by only allowing a limited number of copies to be made, and only using Windows Media Player.
/// MediaMax is a copy protection for audio CDs created by SunnComm, which once installed, restricted users by only allowing a limited number of copies to be made, and only using Windows Media Player.
/// It appears to accomplish this using the official Windows Media Data Session Toolkit.
/// List of discs known to contain MediaMax CD-3: https://en.wikipedia.org/wiki/List_of_compact_discs_sold_with_MediaMax_CD-3
/// TODO: Add support for detecting the Mac version, which is present on "All That I Am" by Santana (Barcode 8 2876-59773-2 6)
/// </summary>
public class MediaMaxCD3 : IPathCheck, IPortableExecutableCheck
public class MediaMax : IPathCheck, IPortableExecutableCheck
{
/// <inheritdoc/>
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
@@ -65,11 +63,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,9 +1,7 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -52,11 +50,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,9 +1,7 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -27,7 +25,7 @@ namespace BinaryObjectScanner.Protection
/// https://nprotect.com/nprotect_pdf/nProtect_KeyCryptV.pdf
/// https://nprotect.com/nprotect_pdf/nProtect_KeyCrypt.pdf
/// </summary>
public class nProtect : IPathCheck, IPortableExecutableCheck
public class NProtect : IPathCheck, IPortableExecutableCheck
{
// TODO: Add LE checks for "npkcrypt.vxd" in Redump entry 90526.
// TODO: Add text check for the string mentioned in https://github.com/mnadareski/BinaryObjectScanner/issues/154.
@@ -82,11 +80,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -2,7 +2,7 @@
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.ProtectionType
namespace BinaryObjectScanner.Protection
{
public class OnlineRegistration : IPortableExecutableCheck
{

View File

@@ -1,11 +1,9 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.IO;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -66,31 +64,27 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// So far found in every known release that uses OpenMG ("Touch" by Amerie, Redump entry 95010, and product ID SVWC-7185).
// Files with the extension ".OMA" in the directory "OMGAUDIO" are the encrypted audio files, and files with in the directory "OMGEXTRA" the extension ".000" are bonus content.
// TODO: Investigate the consistency of "\OMGEXTRA\INDX0000.XML" and "\OMGEXTRA\INDX0001.XML", they seem to only appear when bonus content is present ("Touch" by Amerie).
new(new List<PathMatch>
{
new(Path.Combine("OMGAUDIO", "00AUDTOC.DAT")),
new(Path.Combine("OMGAUDIO", "01AUDSTR.DAT")),
new(Path.Combine("OMGAUDIO", "05SRPCDS.DAT")),
new(Path.Combine("OMGEXTRA", "OMGSVC.DAT")),
}, "OpenMG"),
new(
[
new FilePathMatch(Path.Combine("OMGAUDIO", "00AUDTOC.DAT")),
new FilePathMatch(Path.Combine("OMGAUDIO", "01AUDSTR.DAT")),
new FilePathMatch(Path.Combine("OMGAUDIO", "05SRPCDS.DAT")),
new FilePathMatch(Path.Combine("OMGEXTRA", "OMGSVC.DAT")),
], "OpenMG"),
// Always found together on OpenMG releases ("Touch" by Amerie, Redump entry 95010, and product ID SVWC-7185).
new(new List<PathMatch>
{
new(
[
new FilePathMatch("SDKHM.DLL"),
new FilePathMatch("SDKHM.EXE"),
}, "OpenMG"),
], "OpenMG"),
};
return MatchUtil.GetAllMatches(files, matchers, any: false);

View File

@@ -1,10 +1,8 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -31,11 +29,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,6 +1,7 @@
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
namespace BinaryObjectScanner.Protection
{

View File

@@ -1,10 +1,8 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -42,11 +40,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,7 +1,4 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
@@ -12,17 +9,9 @@ namespace BinaryObjectScanner.Protection
public class ProtectDVDVideo : IPathCheck
{
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
#if NET20 || NET35
var protections = new Queue<string>();
#else
var protections = new ConcurrentQueue<string>();
#endif
var protections = new List<string>();
if (files == null)
return protections;
@@ -34,7 +23,7 @@ namespace BinaryObjectScanner.Protection
var ifofile = new FileInfo(ifofiles[i]);
if (ifofile.Length == 0)
{
protections.Enqueue("Protect DVD-Video (Unconfirmed - Please report to us on Github)");
protections.Add("Protect DVD-Video (Unconfirmed - Please report to us on Github)");
break;
}
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection

View File

@@ -1,12 +1,11 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -288,11 +287,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,11 +1,8 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -45,11 +42,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,9 +1,8 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
namespace BinaryObjectScanner.Protection
{
@@ -36,16 +35,12 @@ namespace BinaryObjectScanner.Protection
// TODO: Confirm if these checks are only for ProRing or if they are also for older Ring PROTECH
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// Found in Redump entry 94161
new(new PathMatch("protect.pro", useEndsWith: true), "Ring PROTECH / ProRing [Check disc for physical ring]"),
new(new FilePathMatch("protect.pro"), "Ring PROTECH / ProRing [Check disc for physical ring]"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
@@ -57,7 +52,7 @@ namespace BinaryObjectScanner.Protection
var matchers = new List<PathMatchSet>
{
// Found in Redump entry 94161
new(new PathMatch("protect.pro", useEndsWith: true), "Ring PROTECH / ProRing [Check disc for physical ring]"),
new(new FilePathMatch("protect.pro"), "Ring PROTECH / ProRing [Check disc for physical ring]"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);

View File

@@ -1,11 +1,8 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -64,11 +61,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,9 +1,7 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -92,11 +90,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,9 +1,7 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
namespace BinaryObjectScanner.Protection
{
@@ -22,11 +20,7 @@ namespace BinaryObjectScanner.Protection
public class SafeLock : IPathCheck
{
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
// Technically all need to exist but some might be renamed
var matchers = new List<PathMatchSet>

View File

@@ -1,12 +1,11 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -119,11 +118,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
@@ -177,21 +172,21 @@ namespace BinaryObjectScanner.Protection
private static string GetV4Version(PortableExecutable pex)
{
int index = 8; // Begin reading after "AddD"
char version = (char)pex.OverlayData![index];
char major = (char)pex.OverlayData![index];
index += 2;
string subVersion = Encoding.ASCII.GetString(pex.OverlayData, index, 2);
string minor = Encoding.ASCII.GetString(pex.OverlayData, index, 2);
index += 3;
string subSubVersion = Encoding.ASCII.GetString(pex.OverlayData, index, 2);
string patch = Encoding.ASCII.GetString(pex.OverlayData, index, 2);
index += 3;
string subSubSubVersion = Encoding.ASCII.GetString(pex.OverlayData, index, 4);
string revision = Encoding.ASCII.GetString(pex.OverlayData, index, 4);
if (!char.IsNumber(version))
if (!char.IsNumber(major))
return "(very old, v3 or less)";
return $"{version}.{subVersion}.{subSubVersion}.{subSubSubVersion}";
return $"{major}.{minor}.{patch}.{revision}";
}
public static string? GetV5Version(string file, byte[]? fileContent, List<int> positions)
@@ -201,34 +196,34 @@ namespace BinaryObjectScanner.Protection
return null;
int index = positions[0] + 8; // Begin reading after "ÊÝݬ"
byte version = (byte)(fileContent[index] & 0x0F);
byte major = (byte)(fileContent[index] & 0x0F);
index += 2;
byte[] subVersion = new byte[2];
subVersion[0] = (byte)(fileContent[index] ^ 36);
byte[] minor = new byte[2];
minor[0] = (byte)(fileContent[index] ^ 36);
index++;
subVersion[1] = (byte)(fileContent[index] ^ 28);
minor[1] = (byte)(fileContent[index] ^ 28);
index += 2;
byte[] subSubVersion = new byte[2];
subSubVersion[0] = (byte)(fileContent[index] ^ 42);
byte[] patch = new byte[2];
patch[0] = (byte)(fileContent[index] ^ 42);
index++;
subSubVersion[1] = (byte)(fileContent[index] ^ 8);
patch[1] = (byte)(fileContent[index] ^ 8);
index += 2;
byte[] subSubSubVersion = new byte[4];
subSubSubVersion[0] = (byte)(fileContent[index] ^ 16);
byte[] revision = new byte[4];
revision[0] = (byte)(fileContent[index] ^ 16);
index++;
subSubSubVersion[1] = (byte)(fileContent[index] ^ 116);
revision[1] = (byte)(fileContent[index] ^ 116);
index++;
subSubSubVersion[2] = (byte)(fileContent[index] ^ 34);
revision[2] = (byte)(fileContent[index] ^ 34);
index++;
subSubSubVersion[3] = (byte)(fileContent[index] ^ 22);
revision[3] = (byte)(fileContent[index] ^ 22);
if (version == 0 || version > 9)
if (major == 0 || major > 9)
return string.Empty;
return $"{version}.{subVersion[0]}{subVersion[1]}.{subSubVersion[0]}{subSubVersion[1]}.{subSubSubVersion[0]}{subSubSubVersion[1]}{subSubSubVersion[2]}{subSubSubVersion[3]}";
return $"{major}.{minor[0]}{minor[1]}.{patch[0]}{patch[1]}.{revision[0]}{revision[1]}{revision[2]}{revision[3]}";
}
// These live in the MS-DOS stub, for some reason
@@ -289,10 +284,10 @@ namespace BinaryObjectScanner.Protection
0x82, 0xD8, 0x0C, 0xAC
]);
(bool success, int position) = matcher.Match(dataSectionRaw);
int position = matcher.Match(dataSectionRaw);
// If we can't find the string, we default to generic
if (!success)
if (position < 0)
return "8";
#if NETFRAMEWORK

View File

@@ -1,10 +1,8 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -31,11 +29,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,10 +1,8 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -84,11 +82,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,14 +1,13 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.ProtectionType
namespace BinaryObjectScanner.Protection
{
// TODO: Not matching all SolidShield Wrapper v1 (See JackKeane)
// TODO: Not matching all SolidShield Wrapper v1 (See NFS11)
@@ -111,23 +110,19 @@ namespace BinaryObjectScanner.ProtectionType
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// Found in Redump entry 68166.
new(new FilePathMatch("tdvm.dll"), "SolidShield"),
new(new FilePathMatch("tdvm.vds"), "SolidShield"),
new(new PathMatch("vfs20.dll", useEndsWith: true), "SolidShield"),
new(new FilePathMatch("vfs20.dll"), "SolidShield"),
new(new FilePathMatch("dvm.dll"), "SolidShield"),
new(new FilePathMatch("hc.dll"), "SolidShield"),
new(new PathMatch("solidshield-cd.dll", useEndsWith: true), "SolidShield"),
new(new PathMatch("c11prot.dll", useEndsWith: true), "SolidShield"),
new(new FilePathMatch("solidshield-cd.dll"), "SolidShield"),
new(new FilePathMatch("c11prot.dll"), "SolidShield"),
};
// TODO: Verify if these are OR or AND
@@ -139,10 +134,15 @@ namespace BinaryObjectScanner.ProtectionType
{
var matchers = new List<PathMatchSet>
{
// Found in Redump entry 68166.
new(new FilePathMatch("tdvm.dll"), "SolidShield"),
new(new FilePathMatch("tdvm.vds"), "SolidShield"),
new(new FilePathMatch("vfs20.dll"), "SolidShield"),
new(new FilePathMatch("dvm.dll"), "SolidShield"),
new(new FilePathMatch("hc.dll"), "SolidShield"),
new(new PathMatch("solidshield-cd.dll", useEndsWith: true), "SolidShield"),
new(new PathMatch("c11prot.dll", useEndsWith: true), "SolidShield"),
new(new FilePathMatch("solidshield-cd.dll"), "SolidShield"),
new(new FilePathMatch("c11prot.dll"), "SolidShield"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);

View File

@@ -1,11 +1,9 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -106,11 +104,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,9 +1,7 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -43,11 +41,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,9 +1,7 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
namespace BinaryObjectScanner.Protection
{
@@ -55,11 +53,7 @@ namespace BinaryObjectScanner.Protection
public class TZCopyProtection : IPathCheck
{
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,14 +1,13 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.IO;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.ProtectionType
namespace BinaryObjectScanner.Protection
{
public class TAGES : IPathCheck, IPortableExecutableCheck
{
@@ -64,22 +63,18 @@ namespace BinaryObjectScanner.ProtectionType
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// So far, only known to exist in early versions of "Moto Racer 3" (Redump entries 31578 and 34669).
new(new List<PathMatch>
{
new(
[
// d37f70489207014d7d0fbaa43b081a93e8030498
new(Path.Combine("Sys", "Devx.sys")),
new FilePathMatch(Path.Combine("Sys", "Devx.sys")),
// a0acbc2f8e321e4f30c913c095e28af444058249
new(Path.Combine("Sys", "VtPr.sys")),
new FilePathMatch(Path.Combine("Sys", "VtPr.sys")),
// SHA-1 is variable, file size is 81,920 bytes
new FilePathMatch("Wave.aif"),
@@ -92,52 +87,52 @@ namespace BinaryObjectScanner.ProtectionType
// SHA-1 is variable, file size is 61,440 bytes
new FilePathMatch("Wave.axt"),
}, "TAGES"),
], "TAGES"),
// Currently only found in "Robocop" (Redump entry 35932).
// Found in a directory named "System", with an executable named "Setup.exe".
new(new List<PathMatch>
{
new(
[
// f82339d797be6da92f5d9dadeae9025385159057
new(Path.Combine("9x", "Tamlx.alf")),
new FilePathMatch(Path.Combine("9x", "Tamlx.alf")),
// 933c004d3043863f019f5ffaf63402a30e65026c
new(Path.Combine("9x", "Tamlx.apt")),
new FilePathMatch(Path.Combine("9x", "Tamlx.apt")),
// d45745fa6b0d23fe0ee12e330ab85d5bf4e0e776
new(Path.Combine("NT", "enodpl.sys")),
new FilePathMatch(Path.Combine("NT", "enodpl.sys")),
// f111eba05ca6e9061c557547420847d7fdee657d
new(Path.Combine("NT", "litdpl.sys")),
}, "TAGES"),
new FilePathMatch(Path.Combine("NT", "litdpl.sys")),
], "TAGES"),
// Currently only known to exist in "XIII" and "Beyond Good & Evil" (Redump entries 8774-8776, 45940-45941, 18690-18693, and presumably 21320, 21321, 21323, and 36124).
new(new List<PathMatch>
{
new(
[
new FilePathMatch("enodpl.sys"),
new FilePathMatch("ENODPL.VXD"),
new FilePathMatch("tandpl.sys"),
new FilePathMatch("TANDPL.VXD"),
}, "TAGES"),
], "TAGES"),
// The directory of these files has been seen to be named two different things, with two different accompanying executables in the root of the directory.
// In the example where the directory is named "Drivers", the executable is named "Silent.exe" (Redump entry 51763).
// In the example where the directory is named "ELBdrivers", the executable is name "ELBDrivers.exe" (Redump entry 91090).
// The name and file size of the included executable vary, but there should always be one here.
new(new List<PathMatch>
{
new(
[
// 40826e95f3ad8031b6debe15aca052c701288e04
new(Path.Combine("9x", "hwpsgt.vxd")),
new FilePathMatch(Path.Combine("9x", "hwpsgt.vxd")),
// f82339d797be6da92f5d9dadeae9025385159057
new(Path.Combine("9x", "lemsgt.vxd")),
new FilePathMatch(Path.Combine("9x", "lemsgt.vxd")),
// 43f407ecdc0d87a3713126b757ccaad07ade285f
new(Path.Combine("NT", "hwpsgt.sys")),
new FilePathMatch(Path.Combine("NT", "hwpsgt.sys")),
// 548dd6359abbcc8c84ce346d078664eeedc716f7
new(Path.Combine("NT", "lemsgt.sys")),
}, "TAGES"),
new FilePathMatch(Path.Combine("NT", "lemsgt.sys")),
], "TAGES"),
// The following files are supposed to only be found inside the driver setup executables, and are present in at least version 5.2.0.1 (Redump entry 15976).
new(new FilePathMatch("ithsgt.sys"), "TAGES Driver"),
@@ -216,7 +211,7 @@ namespace BinaryObjectScanner.ProtectionType
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
private string GetVersion(PortableExecutable pex)
private static string GetVersion(PortableExecutable pex)
{
// Check the internal versions
var version = pex.GetInternalVersion();

View File

@@ -1,42 +0,0 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.IO;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
namespace BinaryObjectScanner.Protection
{
/// <remarks>
/// This protection needs far more research
/// </remarks>
public class TivolaRingProtection : IPathCheck
{
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
{
var matchers = new List<PathMatchSet>
{
new(Path.Combine("ZDAT", "webmast.dxx"), "Tivola Ring Protection [Check disc for physical ring]"),
};
return MatchUtil.GetAllMatches(files, matchers, any: true);
}
/// <inheritdoc/>
public string? CheckFilePath(string path)
{
var matchers = new List<PathMatchSet>
{
new(Path.Combine("ZDAT", "webmast.dxx"), "Tivola Ring Protection [Check disc for physical ring]"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
}
}

View File

@@ -1,9 +1,7 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -46,11 +44,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,11 +1,9 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -45,21 +43,17 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// Found on "All That I Am" by Santana (Barcode 8 2876-59773-2 6) and "Contraband" by Velvet Revolver (Barcode 8 28766 05242 8), "Touch" by Amerie, likely among others.
new(new List<PathMatch>
{
new(
[
// These files always appear to be present together.
new FilePathMatch("WMDS.dll"),
new FilePathMatch("WMDS.ini"),
}, "Windows Media Data Session DRM"),
], "Windows Media Data Session DRM"),
};
return MatchUtil.GetAllMatches(files, matchers, any: false);

View File

@@ -1,14 +1,13 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
{
// TODO: Document and implement support for this better, including version detection.
public class WTMCDProtect : IPathCheck, IPortableExecutableCheck
{
/// <inheritdoc/>
@@ -53,19 +52,15 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
new(new List<PathMatch>
{
new(
[
new FilePathMatch("wtmfiles.dat"),
new FilePathMatch("Viewer.exe"),
}, "WTM Protection Viewer"),
], "WTM Protection Viewer"),
};
return MatchUtil.GetAllMatches(files, matchers, any: false);
@@ -79,7 +74,8 @@ namespace BinaryObjectScanner.Protection
{
new(new FilePathMatch("Image.imp"), "WTM CD Protect"),
new(new FilePathMatch("Image1.imp"), "WTM CD Protect"),
new(new FilePathMatch("imp.dat"), "WTM CD Protect"),
// Disabled due to false positives.
// new(new FilePathMatch("imp.dat"), "WTM CD Protect"),
new(new FilePathMatch("wtmfiles.dat"), "WTM Protection Viewer"),
};

View File

@@ -1,9 +1,7 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
namespace BinaryObjectScanner.Protection
{
@@ -21,11 +19,7 @@ namespace BinaryObjectScanner.Protection
public class WinLock : IPathCheck
{
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,7 +1,4 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -43,17 +40,9 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
#if NET20 || NET35
var protections = new Queue<string>();
#else
var protections = new ConcurrentQueue<string>();
#endif
var protections = new List<string>();
if (files == null)
return protections;
@@ -66,11 +55,11 @@ namespace BinaryObjectScanner.Protection
{
var xcpVersion = GetDatVersion(versionDatPath);
if (!string.IsNullOrEmpty(xcpVersion))
protections.Enqueue(xcpVersion!);
protections.Add(xcpVersion!);
}
else
{
protections.Enqueue("XCP");
protections.Add("XCP");
}
}

View File

@@ -1,10 +1,8 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.IO;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
namespace BinaryObjectScanner.Protection
{
@@ -12,11 +10,7 @@ namespace BinaryObjectScanner.Protection
public class Zzxzz : IPathCheck
{
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
@@ -36,7 +30,7 @@ namespace BinaryObjectScanner.Protection
{
var matchers = new List<PathMatchSet>
{
new(new PathMatch("Zzz.aze", useEndsWith: true), "Zzxzz"),
new(new FilePathMatch("Zzz.aze"), "Zzxzz"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);

Some files were not shown because too many files have changed in this diff Show More