mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-02-04 13:45:28 +00:00
Compare commits
135 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5dc66b140 | ||
|
|
41e10a4150 | ||
|
|
3c4381049b | ||
|
|
3188c6e922 | ||
|
|
1bfb6cda08 | ||
|
|
86feb930a8 | ||
|
|
5587c79ac5 | ||
|
|
dc2a2e10de | ||
|
|
a2fdcb4f6f | ||
|
|
a355670af9 | ||
|
|
3489c67e2b | ||
|
|
99a64942ea | ||
|
|
5eab12946f | ||
|
|
683cfb6306 | ||
|
|
9a3fde0518 | ||
|
|
26d19aab37 | ||
|
|
08564ed607 | ||
|
|
0f6378cd2c | ||
|
|
34a78fc4b9 | ||
|
|
c9ee45c1d2 | ||
|
|
13f5b4f79b | ||
|
|
e5d0c5bdc4 | ||
|
|
6220382531 | ||
|
|
165896e335 | ||
|
|
284d0ea108 | ||
|
|
b04feab5da | ||
|
|
4e0442d526 | ||
|
|
d8aa4d230d | ||
|
|
07a7fd05d2 | ||
|
|
671e1ee2b6 | ||
|
|
d627e8a4c9 | ||
|
|
6ee90b28cd | ||
|
|
8dc2b019b6 | ||
|
|
f151563e28 | ||
|
|
edbbbb011d | ||
|
|
e3fd44134b | ||
|
|
71fb7318e3 | ||
|
|
aba4395139 | ||
|
|
1fd69f101f | ||
|
|
aa4c72fb90 | ||
|
|
150b9a0d67 | ||
|
|
b08921a94a | ||
|
|
3406f3c4b3 | ||
|
|
ffca156209 | ||
|
|
b842599006 | ||
|
|
86b639b04f | ||
|
|
570602aac6 | ||
|
|
4989956a91 | ||
|
|
14849f45da | ||
|
|
28ebc14fe1 | ||
|
|
54cb996fce | ||
|
|
8df58fa4d4 | ||
|
|
422add9827 | ||
|
|
59435903eb | ||
|
|
95ee417e00 | ||
|
|
df913372bf | ||
|
|
2f1c76b7f9 | ||
|
|
18e57c8182 | ||
|
|
b4e2117c4b | ||
|
|
1bb5ff9e18 | ||
|
|
a46cae469d | ||
|
|
b564ff214d | ||
|
|
0744a10de0 | ||
|
|
343ca9497e | ||
|
|
861958527d | ||
|
|
a6b9dca291 | ||
|
|
18c05cb49d | ||
|
|
ed3e58af6c | ||
|
|
e3eed76826 | ||
|
|
7eb86b223f | ||
|
|
a4ee4529ca | ||
|
|
abc68d8503 | ||
|
|
aaff4bad1b | ||
|
|
d5c81857c3 | ||
|
|
c2594cdd2d | ||
|
|
2412042cef | ||
|
|
1f5c1a8100 | ||
|
|
78cc67f30e | ||
|
|
5b78ba5621 | ||
|
|
c4734cfc3d | ||
|
|
dd45384226 | ||
|
|
3e75d9fa3b | ||
|
|
aa690ab602 | ||
|
|
7432100139 | ||
|
|
29fabb44eb | ||
|
|
ad776d4189 | ||
|
|
4cf12c76a8 | ||
|
|
39185f5ddd | ||
|
|
03477327c4 | ||
|
|
29fa0d1ac7 | ||
|
|
7eca23a7f3 | ||
|
|
f0c90bb332 | ||
|
|
0af67e5802 | ||
|
|
6ab9f730f9 | ||
|
|
258238bcc0 | ||
|
|
3936a15ef7 | ||
|
|
f6dbb349c4 | ||
|
|
3c69e02cfc | ||
|
|
531e634e62 | ||
|
|
f9c0c42b26 | ||
|
|
83aebbbfbd | ||
|
|
3847e5e9dc | ||
|
|
a72bb7e332 | ||
|
|
839791f467 | ||
|
|
469356e8c1 | ||
|
|
66e8eb985c | ||
|
|
90223e6c94 | ||
|
|
2f2cf76d7b | ||
|
|
558fee2200 | ||
|
|
a82abc05ec | ||
|
|
74df37597a | ||
|
|
1581023c01 | ||
|
|
c0d1260656 | ||
|
|
969d103c2c | ||
|
|
e5e3f3e3ef | ||
|
|
c1ee399262 | ||
|
|
74ee9932a7 | ||
|
|
e70f8d7220 | ||
|
|
ceba351372 | ||
|
|
ad4082c531 | ||
|
|
115ea02822 | ||
|
|
f876a4e4a6 | ||
|
|
be114f60d3 | ||
|
|
b2594f8148 | ||
|
|
f58ada3dde | ||
|
|
bc4f07970d | ||
|
|
25d6822283 | ||
|
|
3b22262c21 | ||
|
|
314fc1e3fc | ||
|
|
5742749dec | ||
|
|
c55fffeb7b | ||
|
|
e469dc38bf | ||
|
|
553703c30e | ||
|
|
3fd093f9b4 | ||
|
|
4946d4e7ff |
2
.github/workflows/build_test.yml
vendored
2
.github/workflows/build_test.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
project: [Test]
|
||||
runtime: [win-x86, win-x64, linux-x64, osx-x64] #[win-x86, win-x64, win-arm64, linux-x64, linux-arm64, osx-x64]
|
||||
runtime: [win-x86, win-x64, win-arm64, linux-x64, linux-arm64, osx-x64]
|
||||
framework: [net8.0] #[net20, net35, net40, net452, net472, net48, netcoreapp3.1, net5.0, net6.0, net7.0, net8.0]
|
||||
conf: [Release, Debug]
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
@@ -10,8 +10,10 @@
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<!-- <TreatWarningsAsErrors>true</TreatWarningsAsErrors> --> <!-- Can't be enabled because of external code -->
|
||||
<Version>3.1.3</Version>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<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>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
@@ -29,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);
|
||||
@@ -42,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\**
|
||||
@@ -51,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`))">
|
||||
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND $(RuntimeIdentifier.StartsWith(`win-x86`))">
|
||||
<Content Include="*.dll">
|
||||
<Pack>true</Pack>
|
||||
<PackagePath>contentFiles;content</PackagePath>
|
||||
@@ -67,13 +77,12 @@
|
||||
<!-- 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" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))">
|
||||
<PackageReference Include="SharpCompress" Version="0.36.0" />
|
||||
<PackageReference Include="SharpCompress" Version="0.38.0" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net4`)) AND !$(TargetFramework.StartsWith(`net40`))">
|
||||
@@ -81,14 +90,14 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.Compression" Version="0.4.0" />
|
||||
<PackageReference Include="SabreTools.Hashing" Version="1.2.0" />
|
||||
<PackageReference Include="SabreTools.IO" Version="1.3.2" />
|
||||
<PackageReference Include="SabreTools.Matching" Version="1.3.1" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.4.0" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.4.1" />
|
||||
<PackageReference Include="UnshieldSharp" Version="1.7.3" />
|
||||
<PackageReference Include="WiseUnpacker" Version="1.3.1" />
|
||||
<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>
|
||||
|
||||
26
BinaryObjectScanner/CheckDictionary.cs
Normal file
26
BinaryObjectScanner/CheckDictionary.cs
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
27
BinaryObjectScanner/EnumerableExtensions.cs
Normal file
27
BinaryObjectScanner/EnumerableExtensions.cs
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Utilities;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner
|
||||
{
|
||||
@@ -8,63 +8,65 @@ namespace BinaryObjectScanner
|
||||
/// <summary>
|
||||
/// Create an instance of a detectable based on file type
|
||||
/// </summary>
|
||||
public static IDetectable? CreateDetectable(SupportedFileType fileType)
|
||||
public static IDetectable? CreateDetectable(WrapperType fileType)
|
||||
{
|
||||
switch (fileType)
|
||||
return fileType switch
|
||||
{
|
||||
case SupportedFileType.AACSMediaKeyBlock: return new FileType.AACSMediaKeyBlock();
|
||||
case SupportedFileType.BDPlusSVM: return new FileType.BDPlusSVM();
|
||||
//case SupportedFileType.CIA: return new FileType.CIA();
|
||||
case SupportedFileType.Executable: return new FileType.Executable();
|
||||
case SupportedFileType.LDSCRYPT: return new FileType.LDSCRYPT();
|
||||
//case SupportedFileType.N3DS: return new FileType.N3DS();
|
||||
//case SupportedFileType.Nitro: return new FileType.Nitro();
|
||||
case SupportedFileType.PLJ: return new FileType.PLJ();
|
||||
case SupportedFileType.SFFS: return new FileType.SFFS();
|
||||
case SupportedFileType.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>
|
||||
/// Create an instance of an extractable based on file type
|
||||
/// </summary>
|
||||
public static IExtractable? CreateExtractable(SupportedFileType fileType)
|
||||
public static IExtractable? CreateExtractable(WrapperType fileType)
|
||||
{
|
||||
switch (fileType)
|
||||
return fileType switch
|
||||
{
|
||||
case SupportedFileType.BFPK: return new FileType.BFPK();
|
||||
case SupportedFileType.BSP: return new FileType.BSP();
|
||||
case SupportedFileType.BZip2: return new FileType.BZip2();
|
||||
case SupportedFileType.CFB: return new FileType.CFB();
|
||||
//case SupportedFileType.CIA: return new FileType.CIA();
|
||||
case SupportedFileType.GCF: return new FileType.GCF();
|
||||
case SupportedFileType.GZIP: return new FileType.GZIP();
|
||||
case SupportedFileType.InstallShieldArchiveV3: return new FileType.InstallShieldArchiveV3();
|
||||
case SupportedFileType.InstallShieldCAB: return new FileType.InstallShieldCAB();
|
||||
case SupportedFileType.MicrosoftCAB: return new FileType.MicrosoftCAB();
|
||||
case SupportedFileType.MicrosoftLZ: return new FileType.MicrosoftLZ();
|
||||
case SupportedFileType.MPQ: return new FileType.MPQ();
|
||||
//case SupportedFileType.N3DS: return new FileType.N3DS();
|
||||
//case SupportedFileType.NCF: return new FileType.NCF();
|
||||
//case SupportedFileType.Nitro: return new FileType.Nitro();
|
||||
case SupportedFileType.PAK: return new FileType.PAK();
|
||||
case SupportedFileType.PFF: return new FileType.PFF();
|
||||
case SupportedFileType.PKZIP: return new FileType.PKZIP();
|
||||
//case SupportedFileType.PLJ: return new FileType.PLJ();
|
||||
//case SupportedFileType.Quantum: return new FileType.Quantum();
|
||||
case SupportedFileType.RAR: return new FileType.RAR();
|
||||
case SupportedFileType.SevenZip: return new FileType.SevenZip();
|
||||
case SupportedFileType.SFFS: return new FileType.SFFS();
|
||||
case SupportedFileType.SGA: return new FileType.SGA();
|
||||
case SupportedFileType.TapeArchive: return new FileType.TapeArchive();
|
||||
case SupportedFileType.VBSP: return new FileType.VBSP();
|
||||
case SupportedFileType.VPK: return new FileType.VPK();
|
||||
case SupportedFileType.WAD: return new FileType.WAD();
|
||||
case SupportedFileType.XZ: return new FileType.XZ();
|
||||
case SupportedFileType.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,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +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;
|
||||
using System.Threading.Tasks;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Utilities;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
@@ -144,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]);
|
||||
@@ -196,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))
|
||||
@@ -212,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;
|
||||
}
|
||||
@@ -228,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;
|
||||
}
|
||||
@@ -284,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;
|
||||
}
|
||||
@@ -347,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;
|
||||
}
|
||||
@@ -410,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;
|
||||
}
|
||||
@@ -473,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;
|
||||
}
|
||||
|
||||
@@ -42,10 +42,14 @@ namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using UnshieldSharp.Archive;
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
@@ -31,16 +29,16 @@ namespace BinaryObjectScanner.FileType
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
UnshieldSharp.Archive.InstallShieldArchiveV3 archive = new UnshieldSharp.Archive.InstallShieldArchiveV3(file);
|
||||
foreach (CompressedFile cfile in archive.Files.Select(kvp => kvp.Value))
|
||||
foreach (var cfile in archive.Files)
|
||||
{
|
||||
try
|
||||
{
|
||||
string tempFile = Path.Combine(tempPath, cfile.FullPath!);
|
||||
string tempFile = Path.Combine(tempPath, cfile.Key);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
(byte[]? fileContents, string? error) = archive.Extract(cfile.FullPath!);
|
||||
byte[]? fileContents = archive.Extract(cfile.Key, out string? error);
|
||||
if (fileContents == null || !string.IsNullOrEmpty(error))
|
||||
continue;
|
||||
|
||||
|
||||
@@ -59,21 +59,21 @@ namespace BinaryObjectScanner.FileType
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
var cabfile = InstallShieldCabinet.Open(file);
|
||||
if (cabfile == null)
|
||||
if (cabfile?.HeaderList == null)
|
||||
return null;
|
||||
|
||||
for (int i = 0; i < cabfile.FileCount; i++)
|
||||
for (int i = 0; i < cabfile.HeaderList.FileCount; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Check if the file is valid first
|
||||
if (!cabfile.FileIsValid(i))
|
||||
if (!cabfile.HeaderList.FileIsValid(i))
|
||||
continue;
|
||||
|
||||
string tempFile;
|
||||
try
|
||||
{
|
||||
string? filename = cabfile.FileName(i);
|
||||
string? filename = cabfile.HeaderList.GetFileName(i);
|
||||
tempFile = Path.Combine(tempPath, filename ?? string.Empty);
|
||||
}
|
||||
catch
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -42,10 +42,18 @@ namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
|
||||
// If the entry is partial due to an incomplete multi-part archive, skip it
|
||||
if (!entry.IsComplete)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
|
||||
@@ -42,11 +42,22 @@ namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
|
||||
// If we have a partial entry due to an incomplete multi-part archive, skip it
|
||||
if (!entry.IsComplete)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
48
BinaryObjectScanner/FileType/RealArcadeInstaller.cs
Normal file
48
BinaryObjectScanner/FileType/RealArcadeInstaller.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
/// <summary>
|
||||
/// RealArcade Installer. Known to use the ".rgs" file extension.
|
||||
///
|
||||
/// TODO: Add further parsing, game ID and name should be possible to parse.
|
||||
/// </summary>
|
||||
public class RealArcadeInstaller : IDetectable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Detect(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Detect(Stream stream, string file, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] magic = new byte[16];
|
||||
stream.Read(magic, 0, 16);
|
||||
|
||||
// RASGI2.0
|
||||
// Found in the ".rgs" files in IA item "Nova_RealArcadeCD_USA".
|
||||
if (magic.StartsWith(new byte?[] { 0x52, 0x41, 0x53, 0x47, 0x49, 0x32, 0x2E, 0x30 }))
|
||||
return "RealArcade Installer";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
48
BinaryObjectScanner/FileType/RealArcadeMezzanine.cs
Normal file
48
BinaryObjectScanner/FileType/RealArcadeMezzanine.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
/// <summary>
|
||||
/// RealArcade Mezzanine files, which contain metadata. Known to use the ".mez" file extension.
|
||||
///
|
||||
/// TODO: Add further parsing, game ID should be possible to parse.
|
||||
/// </summary>
|
||||
public class RealArcadeMezzanine : IDetectable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Detect(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Detect(Stream stream, string file, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] magic = new byte[16];
|
||||
stream.Read(magic, 0, 16);
|
||||
|
||||
// XZip2.0
|
||||
// Found in the ".mez" files in IA item "Nova_RealArcadeCD_USA".
|
||||
if (magic.StartsWith(new byte?[] { 0x58, 0x5A, 0x69, 0x70, 0x32, 0x2E, 0x30 }))
|
||||
return "RealArcade Mezzanine";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,9 @@ namespace BinaryObjectScanner.FileType
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
{
|
||||
if (stream == null)
|
||||
return null;
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
@@ -39,11 +42,22 @@ namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
|
||||
// If we have a partial entry due to an incomplete multi-part archive, skip it
|
||||
if (!entry.IsComplete)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -42,11 +42,23 @@ namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
|
||||
// If we have a partial entry due to an incomplete multi-part archive, skip it
|
||||
if (!entry.IsComplete)
|
||||
continue;
|
||||
|
||||
// TODO: Fix bug with extracting folders from tar.
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -54,6 +54,14 @@ namespace BinaryObjectScanner.FileType
|
||||
else if (fileContent.Contains("Please enter a valid registration number"))
|
||||
protections.Add("CD-Key / Serial");
|
||||
|
||||
// Channelware
|
||||
// Found in "README.TXT" in Redump entry 116358.
|
||||
if (fileContent.Contains("This application is a Channelware-activated product."))
|
||||
protections.Add("Channelware");
|
||||
// Found in "Swr.dat" in the "TOYSTORY" installation folder from Redump entry 12354.
|
||||
if (fileContent.Contains("cwsw.com/authts"))
|
||||
protections.Add("Channelware");
|
||||
|
||||
// CopyKiller
|
||||
// Found in "autorun.dat" in CopyKiller versions 3.62 and 3.64.
|
||||
if (fileContent.Contains("CopyKiller CD-Protection V3.6x"))
|
||||
@@ -100,18 +108,34 @@ namespace BinaryObjectScanner.FileType
|
||||
protections.Add("MediaMax CD-3");
|
||||
|
||||
// phenoProtect
|
||||
// Found in Redump entry 84082.
|
||||
if (fileContent.Contains("phenoProtect"))
|
||||
protections.Add("phenoProtect");
|
||||
// Additional check to minimize overmatching.
|
||||
if (fileContent.Contains("InstallSHIELD Software Coporation"))
|
||||
// Found in Redump entry 102493.
|
||||
if (fileContent.Contains("COPYPROTECTION_FAILEDR"))
|
||||
protections.Add("phenoProtect");
|
||||
|
||||
// Rainbow Sentinel
|
||||
// Found in "SENTW95.HLP" and "SENTINEL.HLP" in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]".
|
||||
if (fileContent.Contains("Rainbow Sentinel Driver Help"))
|
||||
protections.Add("Rainbow Sentinel");
|
||||
// Found in "\disc4\cad\sdcc_200.zip\DISK1\_USER1.HDR\Language_Independent_Intel_32_Files\SNTNLUSB.INF" in "CICA 32 For Windows CD-ROM (Walnut Creek) (October 1999) (Disc 4).iso" in IA item "CICA_32_For_Windows_CD-ROM_Walnut_Creek_October_1999".
|
||||
if (fileContent.Contains("SNTNLUSB.SvcDesc=\"Rainbow Security Device\""))
|
||||
protections.Add("Rainbow Sentinel USB Driver");
|
||||
if (fileContent.Contains("SntUsb95.SvcDesc=\"Rainbow Security Device\""))
|
||||
protections.Add("Rainbow Sentinel USB Driver");
|
||||
|
||||
// Found in "OEMSETUP.INF" in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]".
|
||||
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.
|
||||
|
||||
@@ -2,7 +2,7 @@ using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.IO;
|
||||
using SabreTools.IO.Extensions;
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
106
BinaryObjectScanner/Packer/DotNetReactor.cs
Normal file
106
BinaryObjectScanner/Packer/DotNetReactor.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -33,6 +33,10 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
try
|
||||
{
|
||||
// If there are no resources
|
||||
if (pex.ResourceData == null)
|
||||
return null;
|
||||
|
||||
// Get the resources that have an executable signature
|
||||
var resources = pex.ResourceData
|
||||
.Where(kvp => kvp.Value != null && kvp.Value is byte[])
|
||||
@@ -57,11 +61,8 @@ namespace BinaryObjectScanner.Packer
|
||||
tempFile = Path.Combine(tempPath, tempFile);
|
||||
|
||||
// Write the resource data to a temp file
|
||||
using (var tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
|
||||
{
|
||||
if (tempStream != null)
|
||||
tempStream.Write(data, 0, data.Length);
|
||||
}
|
||||
using var tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
|
||||
tempStream?.Write(data, 0, data.Length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.SevenZip;
|
||||
using SharpCompress.Readers;
|
||||
#endif
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
public class SevenZipSFX : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
@@ -47,7 +53,57 @@ namespace BinaryObjectScanner.Packer
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (SevenZipArchive sevenZipFile = SevenZipArchive.Open(file, new ReaderOptions() { LookForHeader = true }))
|
||||
{
|
||||
foreach (var entry in sevenZipFile.Entries)
|
||||
{
|
||||
try
|
||||
{
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
|
||||
// If we have a partial entry due to an incomplete multi-part archive, skip it
|
||||
if (!entry.IsComplete)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,23 +39,34 @@ namespace BinaryObjectScanner.Packer
|
||||
try
|
||||
{
|
||||
// Should be using stream instead of file, but stream fails to extract anything. My guess is that the executable portion of the archive is causing stream to fail, but not file.
|
||||
using (RarArchive zipFile = RarArchive.Open(file, new ReaderOptions() { LookForHeader = true }))
|
||||
using (RarArchive rarFile = RarArchive.Open(file, new ReaderOptions() { LookForHeader = true }))
|
||||
{
|
||||
if (!zipFile.IsComplete)
|
||||
if (!rarFile.IsComplete)
|
||||
return null;
|
||||
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
foreach (var entry in zipFile.Entries)
|
||||
foreach (var entry in rarFile.Entries)
|
||||
{
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
|
||||
// If we have a partial entry due to an incomplete multi-part archive, skip it
|
||||
if (!entry.IsComplete)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -20,10 +20,13 @@ namespace BinaryObjectScanner.Packer
|
||||
if (nex.Model.ResidentNameTable == null)
|
||||
return null;
|
||||
|
||||
// Check for the WinZip name string
|
||||
// Check for the WinZip name strings
|
||||
bool winZipNameFound = nex.Model.ResidentNameTable
|
||||
.Select(rnte => rnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(rnte.NameString))
|
||||
.Any(s => s.Contains("WZ-SE-01"));
|
||||
winZipNameFound |= nex.Model.NonResidentNameTable?
|
||||
.Select(nrnte => nrnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(nrnte.NameString))
|
||||
.Any(s => s.Contains("WinZip(R) Self-Extractor")) ?? false;
|
||||
|
||||
// If we didn't find it
|
||||
if (!winZipNameFound)
|
||||
@@ -73,29 +76,37 @@ namespace BinaryObjectScanner.Packer
|
||||
/// <summary>
|
||||
/// Handle common extraction between executable types
|
||||
/// </summary>
|
||||
private static string? Extract(string file, bool includeDebug)
|
||||
public static string? Extract(string file, bool includeDebug)
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
// Should be using stream instead of file, but stream fails to extract anything. My guess is that the executable portion of the archive is causing stream to fail, but not file.
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (ZipArchive zipFile = ZipArchive.Open(file))
|
||||
{
|
||||
if (!zipFile.IsComplete)
|
||||
return null;
|
||||
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
foreach (var entry in zipFile.Entries)
|
||||
{
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
|
||||
// If we have a partial entry due to an incomplete multi-part archive, skip it
|
||||
if (!entry.IsComplete)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -103,9 +114,9 @@ namespace BinaryObjectScanner.Packer
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -3,10 +3,12 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.IO;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
using Wise = WiseUnpacker.WiseUnpacker;
|
||||
using WiseUnpacker;
|
||||
using WiseUnpacker.EWISE;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
@@ -81,8 +83,7 @@ namespace BinaryObjectScanner.Packer
|
||||
try
|
||||
{
|
||||
// TODO: Try to find where the file data lives and how to get it
|
||||
var unpacker = new Wise();
|
||||
if (!unpacker.ExtractTo(file, tempPath))
|
||||
if (!Extractor.ExtractTo(file, tempPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -151,14 +152,14 @@ namespace BinaryObjectScanner.Packer
|
||||
// Ensure that we have an archive end
|
||||
if (format.ArchiveEnd > 0)
|
||||
{
|
||||
overlayOffset = dataStart + format.ArchiveEnd;
|
||||
overlayOffset = (int)(dataStart + format.ArchiveEnd);
|
||||
int archiveEndLoaded = overlayData.ReadInt32(ref overlayOffset);
|
||||
if (archiveEndLoaded != 0)
|
||||
format.ArchiveEnd = archiveEndLoaded;
|
||||
}
|
||||
|
||||
// Skip to the start of the archive
|
||||
overlayOffset = dataStart + format.ArchiveStart;
|
||||
overlayOffset = (int)(dataStart + format.ArchiveStart);
|
||||
|
||||
// Skip over the initialization text, if we expect it
|
||||
if (format.InitText)
|
||||
@@ -190,8 +191,7 @@ namespace BinaryObjectScanner.Packer
|
||||
// If we have DEFLATE -- TODO: Port implementation here or use DeflateStream
|
||||
else
|
||||
{
|
||||
Wise unpacker = new Wise();
|
||||
if (!unpacker.ExtractTo(file, tempPath))
|
||||
if (!Extractor.ExtractTo(file, tempPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -316,47 +316,5 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class representing the properties of each recognized Wise installer format
|
||||
/// </summary>
|
||||
/// TODO: Requires all fields to be writable in package before replacement
|
||||
private class FormatProperty
|
||||
{
|
||||
/// <summary>
|
||||
/// Offset to the executable data
|
||||
/// </summary>
|
||||
public int ExecutableOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if this format includes a DLL at the start or not
|
||||
/// </summary>
|
||||
public bool Dll { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Offset within the data where the archive starts
|
||||
/// </summary>
|
||||
public int ArchiveStart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Position in the archive head of the archive end
|
||||
/// </summary>
|
||||
public int ArchiveEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Format includes initialization text
|
||||
/// </summary>
|
||||
public bool InitText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Position of the filename within the data
|
||||
/// </summary>
|
||||
public int FilenamePosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Format does not include a CRC
|
||||
/// </summary>
|
||||
public bool NoCrc { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace System
|
||||
public class Progress<T> : IProgress<T> where T : EventArgs
|
||||
{
|
||||
/// <summary>The synchronization context captured upon construction. This will never be null.</summary>
|
||||
private readonly SynchronizationContext _synchronizationContext;
|
||||
private readonly SynchronizationContext? _synchronizationContext;
|
||||
/// <summary>The handler specified to the constructor. This may be null.</summary>
|
||||
private readonly Action<T>? _handler;
|
||||
/// <summary>A cached delegate used to post invocation to the synchronization context.</summary>
|
||||
@@ -73,7 +73,7 @@ namespace System
|
||||
{
|
||||
// Post the processing to the sync context.
|
||||
// (If T is a value type, it will get boxed here.)
|
||||
_synchronizationContext.Post(_invokeHandlers, value);
|
||||
_synchronizationContext?.Post(_invokeHandlers, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
@@ -71,6 +70,12 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
if (strs.Any(s => s.Contains("This Game is Japan Only")))
|
||||
return "Alpha-ROM";
|
||||
// Found in "Filechk.exe" in Redump entry 115358.
|
||||
if (strs.Any(s => s.Contains("AlphaCheck.exe")))
|
||||
return "Alpha-ROM";
|
||||
// Found in "Uninstall.exe" in Redump entry 115358.
|
||||
if (strs.Any(s => s.Contains("AlphaCheck.dat")))
|
||||
return "Alpha-ROM";
|
||||
}
|
||||
|
||||
// Get the overlay data, if it exists
|
||||
|
||||
@@ -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/>
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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"),
|
||||
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -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).
|
||||
};
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
115
BinaryObjectScanner/Protection/Channelware.cs
Normal file
115
BinaryObjectScanner/Protection/Channelware.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Paths;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
/// <summary>
|
||||
/// Channelware was an online activation DRM.
|
||||
///
|
||||
/// Official websites:
|
||||
///
|
||||
/// https://web.archive.org/web/19980212121046/http://www.channelware.com/index.html
|
||||
/// https://web.archive.org/web/20021002225705/http://cwsw.com/Home/default.asp
|
||||
/// https://web.archive.org/web/20040101180929/http://www.netactive.com/Home/
|
||||
///
|
||||
/// TODO:
|
||||
/// Add version detection. Redump entry 116358 is version 1.x and Redump entry 12354 is 2.x, but the file versions are inconsistent.
|
||||
/// Investigate "NetActive Reach", which is is either a newer version of this DRM, or a new DRM created by the same company. (https://web.archive.org/web/20040101162921/http://www.netactive.com/Products/)
|
||||
/// </summary>
|
||||
public class Channelware : 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;
|
||||
|
||||
// Found in "AbeWincw.dll" in Redump entry 116358 and in "TOYSGMcw.dll" in the "TOYSTORY" installation folder from Redump entry 12354.
|
||||
var name = pex.ProductName;
|
||||
if (name?.Equals("ChannelWare Utilities") == true)
|
||||
return "Channelware";
|
||||
|
||||
// Found in "cwbrowse.exe" in the "Channelware" folder installed from Redump entry 12354.
|
||||
if (name?.Equals("Channelware Browser Launcher") == true)
|
||||
return "Channelware";
|
||||
|
||||
// Found in "cwuninst.exe" in the "Channelware" folder installed from Redump entry 12354.
|
||||
if (name?.Equals("Channelware Launcher Uninstall Application") == true)
|
||||
return "Channelware";
|
||||
|
||||
// Found in "cwbrowse.exe" in the "Channelware\CWBrowse" folder installed from Redump entry 116358.
|
||||
if (name?.Equals("Channelware Authorization Server Browser Launcher") == true)
|
||||
return "Channelware";
|
||||
|
||||
name = pex.FileDescription;
|
||||
// Found in "cwuninst.exe" in the "Channelware" folder installed from Redump entry 12354.
|
||||
if (name?.Equals("Channelware Launcher Uninstall") == true)
|
||||
return "Channelware";
|
||||
|
||||
name = pex.LegalTrademarks;
|
||||
// Found in "CWAuto.dll" and "Upgrader.exe" in the "TOYSTORY" installation folder from Redump entry 12354.
|
||||
if (name?.Equals("Channelware") == true)
|
||||
return "Channelware";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// Found in Redump entries 12354 and 116358.
|
||||
new(new FilePathMatch("cwlaunch.hlp"), "Channelware"),
|
||||
|
||||
// Found in the "Channelware\CWBrowse" folder installed from Redump entry 116358, and in the "Channelware" folder installed from Redump entry 12354.
|
||||
new(new FilePathMatch("cwbrowse.exe"), "Channelware"),
|
||||
|
||||
// Found in the "Channelware" folder installed from Redump entry 12354.
|
||||
new(new FilePathMatch("cwuninst.exe"), "Channelware"),
|
||||
new(new FilePathMatch("chanwr.ini"), "Channelware"),
|
||||
new(new FilePathMatch("CWAuto.dll"), "Channelware"),
|
||||
|
||||
// Found in Redump entry 116358.
|
||||
new(Path.Combine("CWare", "install.exe"), "Channelware"),
|
||||
|
||||
// Found in Redump entry 12354.
|
||||
new(Path.Combine("cware", "Install.exe"), "Channelware"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? CheckFilePath(string path)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// Found in Redump entries 12354 and 116358.
|
||||
new(new FilePathMatch("cwlaunch.hlp"), "Channelware"),
|
||||
|
||||
// Found in the "Channelware\CWBrowse" folder installed from Redump entry 116358, and in the "Channelware" folder installed from Redump entry 12354.
|
||||
new(new FilePathMatch("cwbrowse.exe"), "Channelware"),
|
||||
|
||||
// Found in the "Channelware" folder installed from Redump entry 12354.
|
||||
new(new FilePathMatch("cwuninst.exe"), "Channelware"),
|
||||
new(new FilePathMatch("chanwr.ini"), "Channelware"),
|
||||
new(new FilePathMatch("CWAuto.dll"), "Channelware"),
|
||||
|
||||
// Found in Redump entry 116358.
|
||||
new(Path.Combine("CWare", "install.exe"), "Channelware"),
|
||||
|
||||
// Found in Redump entry 12354.
|
||||
new(Path.Combine("cware", "Install.exe"), "Channelware"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(path, matchers, any: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
194
BinaryObjectScanner/Protection/CopyX.cs
Normal file
194
BinaryObjectScanner/Protection/CopyX.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
82
BinaryObjectScanner/Protection/EAAntiCheat.cs
Normal file
82
BinaryObjectScanner/Protection/EAAntiCheat.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using System.Collections.Generic;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Paths;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
/// <summary>
|
||||
/// EA Anti Cheat is a kernel-level anti-cheat developed and used by EA. (https://www.ea.com/security/news/eaac-deep-dive).
|
||||
/// List of games that contain EA Anti Cheat on Steam: https://steamdb.info/tech/AntiCheat/EA_AntiCheat/
|
||||
///
|
||||
/// An EasyAntiCheat installer is present in the file "EAAntiCheat.Installer.Tool.exe" found in "Plants vs. Zombies: Battle for Neighborville" (Steam Depot 1262241, Manifest 8124759833120741594).
|
||||
/// This could indicate that EasyAntiCheat is directly integrated into EA Anti Cheat.
|
||||
///
|
||||
/// The internal name appears to be "skyfall", as this is the Internal Name set to several EA Anti Cheat files, and the string "C:\dev\gitlab-runner\builds\r5uPUG7E\0\anticheat\skyfall\Build\Retail\EAAntiCheat.Installer.pdb" is present in "EAAntiCheat.Installer.Tool.exe".
|
||||
/// </summary>
|
||||
public class EAAntiCheat : IPathCheck, IPortableExecutableCheck
|
||||
{
|
||||
// TODO: Add support for detecting older versions, especially versions made before Easy Anti-Cheat was purchased by Epic Games.
|
||||
/// <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;
|
||||
|
||||
var name = pex.FileDescription;
|
||||
// Found in "EAAntiCheat.GameServiceLauncher.exe" and "EAAntiCheat.Installer.exe" in "Plants vs. Zombies: Battle for Neighborville" (Steam Depot 1262241, Manifest 8124759833120741594).
|
||||
if (!string.IsNullOrEmpty(name) && name!.Contains("EA Anticheat"))
|
||||
return "EA Anti Cheat";
|
||||
|
||||
name = pex.ProductName;
|
||||
// Found in "EAAntiCheat.GameServiceLauncher.exe" and "EAAntiCheat.Installer.exe" in "Plants vs. Zombies: Battle for Neighborville" (Steam Depot 1262241, Manifest 8124759833120741594).
|
||||
if (!string.IsNullOrEmpty(name) && name!.Contains("EA Anticheat"))
|
||||
return "EA Anti Cheat";
|
||||
|
||||
name = pex.InternalName;
|
||||
// Found in "EAAntiCheat.GameServiceLauncher.exe" and "EAAntiCheat.Installer.exe" in "Plants vs. Zombies: Battle for Neighborville" (Steam Depot 1262241, Manifest 8124759833120741594).
|
||||
if (!string.IsNullOrEmpty(name) && name!.Equals("skyfall"))
|
||||
return "EA Anti Cheat";
|
||||
|
||||
// TODO: Add check for "EA SPEAR AntiCheat Engineering" in ASN.1 certificate data. Found in files "EAAntiCheat.GameServiceLauncher.dll", "EAAntiCheat.GameServiceLauncher.exe", "EAAntiCheat.Installer.exe", and "preloader_l.dll".
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// Found in "Plants vs. Zombies: Battle for Neighborville" (Steam Depot 1262241, Manifest 8124759833120741594).
|
||||
new(new FilePathMatch("EAAntiCheat.cfg"), "EA Anti Cheat"),
|
||||
new(new FilePathMatch("EAAntiCheat.GameServiceLauncher.dll"), "EA Anti Cheat"),
|
||||
new(new FilePathMatch("EAAntiCheat.GameServiceLauncher.exe"), "EA Anti Cheat"),
|
||||
new(new FilePathMatch("EAAntiCheat.splash.png"), "EA Anti Cheat"),
|
||||
new(new FilePathMatch("EAAntiCheat.Installer.exe"), "EA Anti Cheat"),
|
||||
new(new FilePathMatch("EAAntiCheat.Installer.Tool.exe"), "EA Anti Cheat"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? CheckFilePath(string path)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// Found in "Plants vs. Zombies: Battle for Neighborville" (Steam Depot 1262241, Manifest 8124759833120741594).
|
||||
new(new FilePathMatch("EAAntiCheat.cfg"), "EA Anti Cheat"),
|
||||
new(new FilePathMatch("EAAntiCheat.GameServiceLauncher.dll"), "EA Anti Cheat"),
|
||||
new(new FilePathMatch("EAAntiCheat.GameServiceLauncher.exe"), "EA Anti Cheat"),
|
||||
new(new FilePathMatch("EAAntiCheat.splash.png"), "EA Anti Cheat"),
|
||||
new(new FilePathMatch("EAAntiCheat.Installer.exe"), "EA Anti Cheat"),
|
||||
new(new FilePathMatch("EAAntiCheat.Installer.Tool.exe"), "EA Anti Cheat"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(path, matchers, any: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
83
BinaryObjectScanner/Protection/KalypsoLauncher.cs
Normal file
83
BinaryObjectScanner/Protection/KalypsoLauncher.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
|
||||
@@ -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").Replace("\\", "/"), useEndsWith: true),
|
||||
new(Path.Combine(Path.Combine("BIN", "WIN32"), "MQSTART.EXE").Replace("\\", "/"), useEndsWith: true),
|
||||
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").Replace("\\", "/"), useEndsWith: true),
|
||||
new(Path.Combine("BIN", "WIN32", "MQSTART.EXE").Replace("\\", "/"), useEndsWith: true),
|
||||
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").Replace("\\", "/"), useEndsWith: true),
|
||||
new(Path.Combine("MQDISC", "MQDISC.INI").Replace("\\", "/"), useEndsWith: true),
|
||||
new(Path.Combine("MQDISC", "START.INI").Replace("\\", "/"), useEndsWith: true),
|
||||
}, "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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -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
|
||||
@@ -72,6 +70,10 @@ namespace BinaryObjectScanner.Protection
|
||||
return "SafeDisc Lite";
|
||||
if (strs.Any(s => s.Contains("LTDLL_Unwrap")))
|
||||
return "SafeDisc Lite";
|
||||
|
||||
// Present in "Setup.exe" from the earlier "safedisc.exe" driver update provided by Macrovision.
|
||||
if (strs.Any(s => s.Contains("Failed to get the DRVMGT.DLL Setup API address")))
|
||||
return "Macrovision SecDrv Update Installer";
|
||||
}
|
||||
|
||||
var name = pex.FileDescription;
|
||||
@@ -79,14 +81,23 @@ namespace BinaryObjectScanner.Protection
|
||||
if (name?.Equals("SafeDisc SRV Tool APP", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return $"SafeDisc SRV Tool APP {GetSafeDiscDiagExecutableVersion(pex)}";
|
||||
|
||||
// Present in "Setup.exe" from the later "safedisc.exe" driver update provided by Macrovision.
|
||||
if (name?.Equals("Macrovision SecDrv Update", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return "Macrovision SecDrv Update Installer";
|
||||
|
||||
// Present on all "CLOKSPL.DLL" versions before SafeDisc 1.06.000. Found on Redump entries 61731 and 66004.
|
||||
name = pex.ProductName;
|
||||
if (name?.Equals("SafeDisc CDROM Protection System", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return "SafeDisc 1.00.025-1.01.044";
|
||||
|
||||
// Present in "Diag.exe" files from SafeDisc 4.50.000+.
|
||||
else if (name?.Equals("SafeDisc SRV Tool APP", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return $"SafeDisc SRV Tool APP {GetSafeDiscDiagExecutableVersion(pex)}";
|
||||
|
||||
// Present in "Setup.exe" from the later "safedisc.exe" driver update provided by Macrovision.
|
||||
if (name?.Equals("Macrovision SecDrv Update", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return "Macrovision SecDrv Update Installer";
|
||||
|
||||
// Present on all "CLOKSPL.EXE" versions before SafeDisc 1.06.000. Found on Redump entries 61731 and 66004.
|
||||
// Only found so far on SafeDisc 1.00.025-1.01.044, but the report is currently left generic due to the generic nature of the check.
|
||||
name = pex.FileDescription;
|
||||
@@ -95,8 +106,12 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Found in Redump entries 20729 and 65569.
|
||||
// Get the debug data
|
||||
if (pex.FindCodeViewDebugTableByPath("SafeDisc").Any() || pex.FindCodeViewDebugTableByPath("Safedisk").Any())
|
||||
return "SafeDisc";
|
||||
try
|
||||
{
|
||||
if (pex.FindCodeViewDebugTableByPath("SafeDisc").Any() || pex.FindCodeViewDebugTableByPath("Safedisk").Any())
|
||||
return "SafeDisc";
|
||||
}
|
||||
catch { }
|
||||
|
||||
// TODO: Investigate various section names:
|
||||
// "STLPORT_" - Found in Redump entry 11638.
|
||||
@@ -112,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"),
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace BinaryObjectScanner.Protection
|
||||
/// It's used (to an unknown extent) within SafeCast and SafeDisc (https://web.archive.org/web/20030829044647/http://www.macrovision.com:80/solutions/software/SafeWrap_FAQ_July2003.pdf Section #3).
|
||||
/// It can be used separately from any other Macrovision product, such as (supposedly) for RioPort (https://www.cdrinfo.com/d7/content/macrovision-invests-next-generation-security-and-transport-technologies-internet-delivery).
|
||||
/// No direct SafeWrap only sample has currently been found, nor is it exactly clear what parts of SafeCast/SafeDisc are SafeWrap.
|
||||
/// It's claimed that SafeWrap uses one DLL and one .SYS "security driver" (https://www.cdrinfo.com/d7/content/macrovision-invests-next-generation-security-and-transport-technologies-internet-delivery Section #30).
|
||||
/// It's claimed that SafeWrap uses one DLL and one .SYS "security driver" (https://web.archive.org/web/20030829044647/http://www.macrovision.com:80/solutions/software/SafeWrap_FAQ_July2003.pdf Section #30).
|
||||
/// This would appear to be referring to the "drvmgt.dll" and "secdrv.sys" files, the latter of which is officially referred to as the "Macrovision SECURITY Driver" in some SafeDisc versions.
|
||||
/// This may not be fully accurate, as not all of these files are known to always be used with SafeCast, though this does need further investigation.
|
||||
/// The .stxt* sections found in various Macrovision products may indicate SafeWrap, as they started being used around the time that SafeWrap was made public.
|
||||
@@ -18,13 +18,17 @@ namespace BinaryObjectScanner.Protection
|
||||
///
|
||||
/// Further information and resources:
|
||||
/// Macrovision press release that mentions SafeWrap: https://www.sec.gov/Archives/edgar/data/1027443/000100547701501658/ex99-1.txt
|
||||
/// Macrionvision "Tamper-proof" blurb advertising SafeWrap: https://web.archive.org/web/20030412093353/http://www.macrovision.com/solutions/software/tamper.php3
|
||||
/// SafeAudio news that mentions SafeWrap: https://www.cdmediaworld.com/hardware/cdrom/news/0201/safeaudio_3.shtml
|
||||
/// The titles for a few audio DRM FAQ's include the text "SafeWrap™ Frequently Asked Questions" in the page title, but this may be a copy-paste error:
|
||||
/// https://web.archive.org/web/20030324080804/http://www.macrovision.com:80/solutions/audio/images/SafeAudio_FAQ_Public_5-02.pdf + https://web.archive.org/web/20030403050432/http://www.macrovision.com:80/solutions/audio/Audio_protection_FAQ_Public_March2003.pdf
|
||||
/// Eclipse SafeAudio news that mentions SafeWrap: http://www.eclipsedata.com/PDFs/21.pdf
|
||||
/// Report to congress that mentions SafeWrap: https://www.uspto.gov/sites/default/files/web/offices/dcom/olia/teachreport.pdf
|
||||
/// Patent that mentions possibly using SafeWrap: https://patents.google.com/patent/US7493289B2/en
|
||||
/// MacroSafe presentation that mentions current customer of SafeWrap/SafeCast/SafeDisc: https://slideplayer.com/slide/6840826/
|
||||
/// List of DRM companies and products: https://www1.villanova.edu/villanova/generalcounsel/copyright/digitized/companies.html
|
||||
/// Forum post that briefly mentions SafeWrap: https://www.ttlg.com/forums/showthread.php?t=70035
|
||||
/// Forum post (with no replies) that asks for information about SafeWrap: https://forum.powerbasic.com/forum/user-to-user-discussions/powerbasic-for-windows/9167-macrovision-anti-code-tampering-tool
|
||||
/// Document that mentions SafeWrap as third-party security tool: https://www.cs.clemson.edu/course/cpsc420/material/Papers/Guide_AppSecurity.pdf
|
||||
/// Japanese PDF that mentions SafeWrap: https://ipsj.ixsq.nii.ac.jp/ej/index.php?action=pages_view_main&active_action=repository_action_common_download&item_id=64743&item_no=1&attribute_id=1&file_no=1&page_id=13&block_id=8
|
||||
/// Korean PDF that mentions SafeWrap: http://contents.kocw.or.kr/contents4/document/lec/2012/KonKuk_glocal/Nohyounghee1/9.pdf
|
||||
|
||||
@@ -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;
|
||||
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/>
|
||||
@@ -275,6 +240,8 @@ namespace BinaryObjectScanner.Protection
|
||||
if (!string.IsNullOrEmpty(safeDisc))
|
||||
resultsList.Add(safeDisc!);
|
||||
|
||||
// Clean the result list
|
||||
resultsList = CleanResultList(resultsList);
|
||||
if (resultsList != null && resultsList.Count > 0)
|
||||
return string.Join(", ", [.. resultsList]);
|
||||
|
||||
@@ -282,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"),
|
||||
};
|
||||
|
||||
@@ -302,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"),
|
||||
};
|
||||
|
||||
@@ -429,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.
|
||||
@@ -471,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)
|
||||
@@ -551,16 +514,34 @@ namespace BinaryObjectScanner.Protection
|
||||
// Version 1.04.000/1.4.0.0 can be found in "cdac01aa.dll" and "cdac01ba.dll" from IA item "ejay_nestle_trial", but needs further research.
|
||||
// Found in Redump entry 83145.
|
||||
"2.11.010"
|
||||
|
||||
// Found in IA item microsoft-software-jukebox-for-toshiba-1.0.
|
||||
or "2.11.020"
|
||||
|
||||
// Source not documented.
|
||||
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)
|
||||
// Found in Adobe Photoshop according to http://www.reversing.be/article.php?story=2006102413541932
|
||||
"2.41.000"
|
||||
or "2.42.000"
|
||||
"2.42.000"
|
||||
|
||||
// Source not documented.
|
||||
or "2.50.030"
|
||||
or "2.51.000" => "SafeCast (Unconfirmed - Please report to us on GitHub)",
|
||||
|
||||
@@ -571,6 +552,8 @@ namespace BinaryObjectScanner.Protection
|
||||
// SafeDisc (Confirmed)
|
||||
// Found in Redump entry 66005.
|
||||
"1.00.025"
|
||||
|
||||
// Source not documented.
|
||||
or "1.00.026"
|
||||
or "1.00.030"
|
||||
or "1.00.032"
|
||||
@@ -638,12 +621,25 @@ namespace BinaryObjectScanner.Protection
|
||||
};
|
||||
}
|
||||
|
||||
private List<string>? CleanResultList(List<string>? resultsList)
|
||||
private static List<string>? CleanResultList(List<string>? resultsList)
|
||||
{
|
||||
// If we have an invalid result list
|
||||
if (resultsList == null || resultsList.Count == 0)
|
||||
return resultsList;
|
||||
|
||||
// Remove duplicates
|
||||
if (resultsList.Contains("Macrovision Protected Application"))
|
||||
{
|
||||
if (resultsList.Contains("Macrovision Protected Application [Version Expunged]"))
|
||||
resultsList = resultsList.Where(r => r != "Macrovision Protected Application").ToList();
|
||||
else if (resultsList.Contains("Macrovision Protected Application (Entry point not present in the stxt371 section. Executable is either unprotected or nonfunctional)"))
|
||||
resultsList = resultsList.Where(r => r != "Macrovision Protected Application").ToList();
|
||||
else if (resultsList.Contains("Macrovision Protected Application (Generic detection - Report to us on GitHub)"))
|
||||
resultsList = resultsList.Where(r => r != "Macrovision Protected Application").ToList();
|
||||
else if (resultsList.Contains("Macrovision Protected Application (Report this to us on GitHub)"))
|
||||
resultsList = resultsList.Where(r => r != "Macrovision Protected Application").ToList();
|
||||
}
|
||||
|
||||
// Get distinct and order
|
||||
return [.. resultsList.Distinct().OrderBy(s => s)];
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -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
|
||||
@@ -13,6 +11,8 @@ namespace BinaryObjectScanner.Protection
|
||||
///
|
||||
/// nProtect GameGuard (https://nprotect.com/kr/b2b/prod_gg.html) is anti-cheat software used in a fair amount of online games.
|
||||
/// Partial list of games that use GameGuard: https://en.wikipedia.org/wiki/NProtect_GameGuard.
|
||||
/// Known versions of GameGuard:
|
||||
/// "2024.2.27.1" - Found in GameGuard.des in "Soulworker" (Steam Depot 1377581, Manifest 5092481117079359342).
|
||||
///
|
||||
/// nProtect KeyCrypt is an anti-keylogging product that seemingly has other DRM functions as well, such as shutting down processes it deems unnecessary (https://en.wikipedia.org/wiki/INCA_Internet#nProtect_Netizen,_nProtect_Personal,_nProtect_Keycrypt)
|
||||
/// TODO: Verify the exact functions of KeyCrypt.
|
||||
@@ -25,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.
|
||||
@@ -42,7 +42,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
var name = pex.FileDescription;
|
||||
|
||||
// Found in "GameGuard.des" in Redump entry 90526 and 99598.
|
||||
// Found in "GameGuard.des" in Redump entry 90526 and 99598, and "Soulworker" (Steam Depot 1377581, Manifest 5092481117079359342).
|
||||
if (name?.Contains("nProtect GameGuard Launcher") == true)
|
||||
return $"nProtect GameGuard ({pex.GetInternalVersion()})";
|
||||
|
||||
@@ -80,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>
|
||||
{
|
||||
@@ -2,7 +2,7 @@
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.ProtectionType
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
public class OnlineRegistration : IPortableExecutableCheck
|
||||
{
|
||||
|
||||
@@ -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").Replace("\\", "/"), useEndsWith: true),
|
||||
new(Path.Combine("OMGAUDIO", "01AUDSTR.DAT").Replace("\\", "/"), useEndsWith: true),
|
||||
new(Path.Combine("OMGAUDIO", "05SRPCDS.DAT").Replace("\\", "/"), useEndsWith: true),
|
||||
new(Path.Combine("OMGEXTRA", "OMGSVC.DAT").Replace("\\", "/"), useEndsWith: true),
|
||||
}, "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);
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
{
|
||||
// Currently implemented as a text file check, more checks are likely possible but currently unknown.
|
||||
// Current checks based off Redump entry 84082 are found in the InstallShield setup.inx file, but the game also checks if the original disc is present in the drive after installation as well, so it seems unlikely for the InstallShield check to be relevant at that stage.
|
||||
// A later version of it can be found in Redump entry 102493, which is found in the InstallShield setup.ins file, and also has a disc check when the game is run. On top of this, there is also a serial number check present. It is currently unknown how to uniquely detect either of them.
|
||||
// The disc checks may be completely generic and undetectable, as these checks seem to be more lax than the installer checks.
|
||||
// <see href="https://github.com/TheRogueArchivist/DRML/blob/main/entries/phenoProtect/phenoProtect.md"/>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -21,10 +20,11 @@ namespace BinaryObjectScanner.Protection
|
||||
/// TODO: Investigate "sntnlusb.sys" (https://www.rainbow.com.my/document/endusertroubleshooting.pdf).
|
||||
///
|
||||
/// Versions:
|
||||
/// Rainbow Sentinel PD-5.1: IA items "pcwkcd-1296" and "CHIPTRMart97".
|
||||
/// Rainbow Sentinel PD-5.1: IA items "pcwkcd-1296, "CHIPTRMart97", and "bugcd199801".
|
||||
/// Rainbow Sentinel PD-5.1e (Beta): IA item "CHIPTRMart97".
|
||||
/// Rainbow Sentinel PD-5.37: File "CICA 32 For Windows CD-ROM (Walnut Creek) (October 1999) (Disc 4).iso" in IA item "CICA_32_For_Windows_CD-ROM_Walnut_Creek_October_1999".
|
||||
/// Rainbow Sentinel PD-5.39: IA item "chip-cds-2001-08".
|
||||
/// Rainbow Sentinel PD-15: IA items "ASMEsMechanicalEngineeringToolkit1997December" and "aplicaciones-windows".
|
||||
/// Rainbow Sentinel PD-15: IA items "ASMEsMechanicalEngineeringToolkit1997December", "aplicaciones-windows", and "ASMEsMechanicalEngineeringToolkit1997December".
|
||||
/// Rainbow Sentinel PD-17: IA item "czchip199707cd".
|
||||
/// Rainbow Sentinel PD-30: BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]" and IA item "auto-cad-r14-cdrom".
|
||||
/// Rainbow Sentinel PD-31: BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]" and IA item "auto-cad-r14-cdrom".
|
||||
@@ -172,6 +172,11 @@ namespace BinaryObjectScanner.Protection
|
||||
if (name?.Equals("NetSentinel Server for WIN 32", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return "Rainbow NetSentinel Server for Win32";
|
||||
|
||||
// Found in "\disc4\cad\sdcc_200.zip\DISK1\_USER1.HDR\Language_Independent_Intel_32_Files\SNTNLUSB.SYS" in "CICA 32 For Windows CD-ROM (Walnut Creek) (October 1999) (Disc 4).iso" in IA item "CICA_32_For_Windows_CD-ROM_Walnut_Creek_October_1999".
|
||||
// TODO: Check if the version included with this is useful.
|
||||
if (name?.Equals("Rainbow Technologies Sentinel Device Driver", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return "Rainbow Sentinel Driver";
|
||||
|
||||
name = pex.ProductName;
|
||||
|
||||
// Found in multiple files in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]", including "RNBOVTMP.DLL", "SENTTEMP.DLL", and "SNTI386.DLL".
|
||||
@@ -194,6 +199,11 @@ namespace BinaryObjectScanner.Protection
|
||||
if (name?.Equals("Sentinel System Driver", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return $"Rainbow Sentinel {pex.ProductVersion}";
|
||||
|
||||
// Found in "\disc4\cad\sdcc_200.zip\DISK1\_USER1.HDR\Language_Independent_Intel_32_Files\SNTNLUSB.SYS" in "CICA 32 For Windows CD-ROM (Walnut Creek) (October 1999) (Disc 4).iso" in IA item "CICA_32_For_Windows_CD-ROM_Walnut_Creek_October_1999".
|
||||
// TODO: Check if the version included with this is useful.
|
||||
if (name?.Equals("Rainbow Technologies USB Security Device Driver", StringComparison.OrdinalIgnoreCase) == true)
|
||||
return "Rainbow Sentinel Driver";
|
||||
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
@@ -277,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>
|
||||
{
|
||||
@@ -330,6 +336,15 @@ namespace BinaryObjectScanner.Protection
|
||||
new(new FilePathMatch("NSRVOM.EXE"), "Rainbow NetSentinel Server for OS/2"),
|
||||
new(new FilePathMatch("NSRVGX.EXE"), "Rainbow NetSentinel Server for Win32"),
|
||||
|
||||
// Found in "\disc4\cad\sdcc_200.zip\DISK1\_USER1.HDR\Language_Independent_Intel_32_Files" in "CICA 32 For Windows CD-ROM (Walnut Creek) (October 1999) (Disc 4).iso" in IA item "CICA_32_For_Windows_CD-ROM_Walnut_Creek_October_1999".
|
||||
// TODO: Add text file checks for these IFX files.
|
||||
new(new FilePathMatch("SNTNLUSB.IFX"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTNLUSB.INF"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTNLUSB.SYS"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTUSB95.IFX"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTUSB95.INF"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTUSB95.SYS"), "Rainbow Sentinel USB Driver"),
|
||||
|
||||
// Found in IA item "czchip199707cd".
|
||||
new(new List<PathMatch>
|
||||
{
|
||||
@@ -422,6 +437,15 @@ namespace BinaryObjectScanner.Protection
|
||||
new(new FilePathMatch("SNTMIPS.DLL"), "Rainbow Sentinel Windows NT MIPS Platform Driver"),
|
||||
new(new FilePathMatch("SNTPPC.DLL"), "Rainbow Sentinel Windows NT PowerPC Platform Driver"),
|
||||
|
||||
// Found in "\disc4\cad\sdcc_200.zip\DISK1\_USER1.HDR\Language_Independent_Intel_32_Files" in "CICA 32 For Windows CD-ROM (Walnut Creek) (October 1999) (Disc 4).iso" in IA item "CICA_32_For_Windows_CD-ROM_Walnut_Creek_October_1999".
|
||||
// TODO: Add text file checks for these IFX files.
|
||||
new(new FilePathMatch("SNTNLUSB.IFX"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTNLUSB.INF"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTNLUSB.SYS"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTUSB95.IFX"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTUSB95.INF"), "Rainbow Sentinel USB Driver"),
|
||||
new(new FilePathMatch("SNTUSB95.SYS"), "Rainbow Sentinel USB Driver"),
|
||||
|
||||
// Found in IA item "chip-cds-2001-08".
|
||||
// File names for Rainbow Sentinel files sometimes found in ".cab" files.
|
||||
new(new FilePathMatch("F194_rnbovdd.dll.B391C188_6953_11D4_82CB_00D0B72E1DB9"), "Rainbow Sentinel"),
|
||||
|
||||
68
BinaryObjectScanner/Protection/RealArcade.cs
Normal file
68
BinaryObjectScanner/Protection/RealArcade.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
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>
|
||||
/// RealArcade was a game platform that allowed users to play timed demos of games, and then prompted them to purchase the game in order to play the game without a limit.
|
||||
/// Although the servers are long dead, there is a community project actively being developed to allow users to properly download and play these games.
|
||||
/// Links:
|
||||
/// https://github.com/lightbulbatelier/RealArcade-DGA
|
||||
/// https://archive.org/details/realrcade-games-preservation-project
|
||||
/// </summary>
|
||||
public class RealArcade : 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;
|
||||
|
||||
// Get the .data section strings, if they exist
|
||||
var strs = pex.GetFirstSectionStrings(".data");
|
||||
if (strs != null)
|
||||
{
|
||||
// Found in "rebound.exe" in the installation directory for "Rebound" in IA item "Nova_RealArcadeCD_USA".
|
||||
if (strs.Any(s => s.Contains("RngInterstitialDLL")))
|
||||
return "RealArcade";
|
||||
}
|
||||
|
||||
// Found in "RngInterstitial.dll" in the RealArcade installation directory in IA item "Nova_RealArcadeCD_USA".
|
||||
var name = pex.FileDescription;
|
||||
if (name?.Contains("RngInterstitial") == true)
|
||||
return "RealArcade";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// ".rgs" and ".mez" files are also associated with RealArcade.
|
||||
new(new FilePathMatch("RngInterstitial.dll"), "RealArcade"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? CheckFilePath(string path)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// ".rgs" and ".mez" files are also associated with RealArcade.
|
||||
new(new FilePathMatch("RngInterstitial.dll"), "RealArcade"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(path, matchers, any: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
85
BinaryObjectScanner/Protection/Roxxe.cs
Normal file
85
BinaryObjectScanner/Protection/Roxxe.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
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>
|
||||
/// Roxxe was a Czech DRM. It appears to have been a simple disc check that also relied on unusual disc manufacturing and dummy files to attempt to prevent copying.
|
||||
///
|
||||
/// DRML: https://github.com/TheRogueArchivist/DRML/blob/main/entries/Roxxe/Roxxe.md
|
||||
/// </summary>
|
||||
public class Roxxe : 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;
|
||||
|
||||
// Get the code/CODE section strings, if they exist
|
||||
var strs = pex.GetFirstSectionStrings("code") ?? pex.GetFirstSectionStrings("CODE");
|
||||
if (strs != null)
|
||||
{
|
||||
// Found in "Owar.exe" in IA item "game4u-22-cd".
|
||||
if (strs.Any(s => s.Contains("TRCHANGER.INI")))
|
||||
return "Roxxe";
|
||||
}
|
||||
|
||||
// Get the .rsrc section strings, if they exist
|
||||
// TODO: Check for these strings specifically within the application-defined resource that they're found in, not just the generic resource section.
|
||||
strs = pex.GetFirstSectionStrings(".rsrc");
|
||||
if (strs != null)
|
||||
{
|
||||
// Found in "Owar.exe" in IA items "game4u-22-cd" and "original-war".
|
||||
// These checks are less reliable, as they are still found in a version of the game that appears to have patched out Roxxe (the version present in IA item "original-war").
|
||||
if (strs.Any(s => s.Contains("PRRT01")))
|
||||
return "Roxxe (Possibly remnants)";
|
||||
|
||||
if (strs.Any(s => s.Contains("CommonPRRT")))
|
||||
return "Roxxe (Possibly remnants)";
|
||||
|
||||
// Currently overmatches, will likely be a viable check when better Delphi executable parsing is available.
|
||||
// if (strs.Any(s => s.Contains("roxe")))
|
||||
// return "Roxxe (Possibly remnants)";
|
||||
}
|
||||
|
||||
// If any dialog boxes match
|
||||
// Found in "Data6.OWP" in IA item "game4u-22-cd".
|
||||
if (pex.FindDialogBoxByItemTitle("SharpTiny Version 1.0").Any())
|
||||
return "Roxxe";
|
||||
// Found in "Data8.OWP" in IA item "game4u-22-cd".
|
||||
else if (pex.FindDialogBoxByItemTitle("T32xWin Version 1.0").Any())
|
||||
return "Roxxe";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// Files such as "TRCHANGER.INI" may be present, but haven't been found yet.
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? CheckFilePath(string path)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// Files such as "TRCHANGER.INI" may be present, but haven't been found yet.
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(path, matchers, any: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user