Compare commits

...

105 Commits

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

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

* Cleaned up changes.

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

* Fixed formatting.

* Removed some unecessary lines of code.

* Added debatably sufficient documentation.

* Fixed formatting, hopefully

* Finalize formatting and PR.

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

* Fix ordering.

* Fixes pex check, fixes redump id formatting.

* Added copy-X info to readme.

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

This reverts commit 77349aa8de.

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

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

* Remove first person.

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

* Fix typo

* WIP figuring out enumerable (fails to build)

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

* Pass 1 of suggested changes.

* Removed debug match.

* Pass 2 of suggested changes.

* Added line.

* Added line for real.

* Added todo

* Improved comments.

* Finished todo.

* Redid change.

* Fixes more comments.

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

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

* Fix missing using

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

* Small changes to Kalypso Launcher

* More minor Kalypso Launcher changes
2024-10-03 10:42:39 -04:00
Matt Nadareski
570602aac6 Remove unused package 2024-10-01 10:45:12 -04:00
Matt Nadareski
4989956a91 Bump version 2024-09-28 13:13:06 -04:00
Matt Nadareski
14849f45da Remove redundant reports in Macrovision code 2024-09-27 13:24:19 -04:00
TheRogueArchivist
28ebc14fe1 Fix various archive formats not extracting folders (#323)
Fixes folder extraction for 7z, RAR, and WinRAR SFX. Applied same fix to tar, but more is needed for it to work properly.
2024-09-26 01:15:38 -04:00
TheRogueArchivist
54cb996fce [WIP] Add 7-Zip SFX extraction (#321)
* Add 7-Zip SFX extraction

Newest SharpCompress added support for extracting 7-Zip SFX files, so we can add support for them here too.

* Clean up 7z SFX extraction method

* Remove unneeded import

* Use file instead of stream for 7z SFX

* Update 7z SFX to be more consistent with other packers
2024-09-26 00:30:25 -04:00
Matt Nadareski
8df58fa4d4 This doesn't inherit from anything 2024-09-25 11:25:52 -04:00
TheRogueArchivist
422add9827 Update SharpCompress to 0.38.0 (#320) 2024-09-25 11:01:16 -04:00
TheRogueArchivist
59435903eb Small update to nProtect comments (#319)
Add new confirmed game to use GameGuard, and start a known version list.
2024-09-12 02:33:17 -04:00
TheRogueArchivist
95ee417e00 Small update to SafeWrap comments (#318)
* Small update to SafeWrap comments

* Further additions to SafeWrap comments
2024-09-05 01:22:11 -04:00
Matt Nadareski
df913372bf Add more SecuROM PA checks (fixes #313) 2024-08-08 08:55:46 -04:00
TheRogueArchivist
2f1c76b7f9 Add EA Anti Cheat detection (#314)
* Add EA Anti Cheat detection

* Make a check more exact
2024-08-02 12:34:43 -04:00
Matt Nadareski
18e57c8182 Fix minor formatting issue 2024-08-02 12:23:05 -04:00
TheRogueArchivist
b4e2117c4b Confirm one SafeCast version (#309) 2024-08-02 00:07:12 -04:00
Matt Nadareski
1bb5ff9e18 Fix README a bit 2024-07-20 21:54:55 -04:00
TheRogueArchivist
a46cae469d Fix scans that use directory name in Windows (#312)
Removes ``.Replace("\\", "/")``, as it was messing with folder paths on Windows.
2024-07-13 01:29:45 -04:00
TheRogueArchivist
b564ff214d Add initial Channelware detection (#311) 2024-07-12 12:35:26 -04:00
TheRogueArchivist
0744a10de0 Improve phenoProtect detection (#307) 2024-07-04 22:16:11 -04:00
HeroponRikiBestest
343ca9497e Fix #.##.xx version number writing second x digit to first digit (#310) 2024-07-04 22:13:49 -04:00
Matt Nadareski
861958527d Fix under-matched runtimes 2024-06-26 12:44:32 -04:00
Matt Nadareski
a6b9dca291 Only copy DLLs for win-x86 2024-06-26 11:53:10 -04:00
Matt Nadareski
18c05cb49d Update workflow runtimes 2024-06-26 11:34:31 -04:00
Matt Nadareski
ed3e58af6c Update publishing to cooler version 2024-06-26 11:32:20 -04:00
Matt Nadareski
e3eed76826 Make debug table reading safer, kinda 2024-06-20 11:26:20 -04:00
Matt Nadareski
7eb86b223f Fix build script 2024-06-17 16:16:11 -04:00
Matt Nadareski
a4ee4529ca Bump version 2024-06-17 16:15:04 -04:00
Matt Nadareski
abc68d8503 Update Serialization to 1.6.7 2024-06-13 11:20:33 -04:00
TheRogueArchivist
aaff4bad1b Add new Alpha-ROM checks (#306) 2024-06-07 13:11:24 -04:00
TheRogueArchivist
d5c81857c3 Update Roxxe detections (#305) 2024-06-05 09:37:37 -04:00
TheRogueArchivist
c2594cdd2d Add checks for Macrovision SecDrv Update Installer (#304) 2024-06-02 19:43:15 -04:00
Matt Nadareski
2412042cef Update Serialization to 1.6.6 2024-06-02 19:42:49 -04:00
Matt Nadareski
1f5c1a8100 Bump version 2024-05-18 22:12:35 -04:00
Matt Nadareski
78cc67f30e Update UnshieldSharp 2024-05-18 22:05:32 -04:00
Matt Nadareski
5b78ba5621 Bump version 2024-05-15 20:30:43 -04:00
Matt Nadareski
c4734cfc3d Update packages 2024-05-15 15:16:41 -04:00
Matt Nadareski
dd45384226 Add secondary check for WinZipSFX NE 2024-05-15 15:15:09 -04:00
Matt Nadareski
3e75d9fa3b Add safety around executable wrapper creation 2024-05-15 13:09:40 -04:00
Matt Nadareski
aa690ab602 Update packages 2024-05-15 12:24:40 -04:00
Matt Nadareski
7432100139 Bump version 2024-05-07 08:57:17 -04:00
Matt Nadareski
29fabb44eb Update IO and Serialization 2024-05-07 05:31:42 -04:00
Matt Nadareski
ad776d4189 Add explicit compatibility notes section 2024-05-06 22:40:39 -04:00
Matt Nadareski
4cf12c76a8 Update IO and Serialization 2024-05-06 22:30:58 -04:00
Matt Nadareski
39185f5ddd Remove now-irrelevant note 2024-05-06 21:59:37 -04:00
Matt Nadareski
03477327c4 Clearer in another place 2024-05-06 21:59:10 -04:00
Matt Nadareski
29fa0d1ac7 Clarify support 2024-05-06 21:54:45 -04:00
Matt Nadareski
7eca23a7f3 Bump version 2024-04-28 19:51:22 -04:00
Matt Nadareski
f0c90bb332 Update packages for critical issues 2024-04-28 19:50:53 -04:00
Matt Nadareski
0af67e5802 Fix build 2024-04-26 22:13:27 -04:00
Matt Nadareski
6ab9f730f9 Bump version 2024-04-26 22:10:27 -04:00
Matt Nadareski
258238bcc0 Update packages 2024-04-26 22:09:05 -04:00
Matt Nadareski
3936a15ef7 Bump version 2024-04-24 17:08:16 -04:00
Matt Nadareski
f6dbb349c4 Update packages 2024-04-24 17:06:51 -04:00
Matt Nadareski
3c69e02cfc Update SabreTools.Serialization 2024-04-24 16:29:58 -04:00
Matt Nadareski
531e634e62 Version-gate a using statement 2024-04-24 14:43:28 -04:00
Matt Nadareski
f9c0c42b26 One Nuget packing error 2024-04-24 12:13:56 -04:00
Matt Nadareski
83aebbbfbd Maybe the last one? 2024-04-24 12:11:05 -04:00
Matt Nadareski
3847e5e9dc Even more warnings 2024-04-24 11:55:27 -04:00
Matt Nadareski
a72bb7e332 Yet more, plus an XML comment 2024-04-24 11:45:20 -04:00
Matt Nadareski
839791f467 Add a couple more for external 2024-04-24 11:43:09 -04:00
Matt Nadareski
469356e8c1 Suppress some "necessary" warnings 2024-04-24 11:35:09 -04:00
127 changed files with 2120 additions and 3161 deletions

View File

@@ -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]

View File

@@ -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.6</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.37.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.5.0" />
<PackageReference Include="SabreTools.Hashing" Version="1.2.0" />
<PackageReference Include="SabreTools.IO" Version="1.4.0" />
<PackageReference Include="SabreTools.Matching" Version="1.3.1" />
<PackageReference Include="SabreTools.Models" Version="1.4.5" />
<PackageReference Include="SabreTools.Serialization" Version="1.5.5" />
<PackageReference Include="UnshieldSharp" Version="1.8.0" />
<PackageReference Include="WiseUnpacker" Version="1.4.0" />
<PackageReference Include="SabreTools.Compression" Version="0.5.2" />
<PackageReference Include="SabreTools.Hashing" Version="1.2.2" />
<PackageReference Include="SabreTools.IO" Version="1.4.13" />
<PackageReference Include="SabreTools.Matching" Version="1.3.3" />
<PackageReference Include="SabreTools.Models" Version="1.4.11" />
<PackageReference Include="SabreTools.Serialization" Version="1.6.9" />
<PackageReference Include="UnshieldSharp" Version="1.8.5" />
<PackageReference Include="WiseUnpacker" Version="1.4.4" />
</ItemGroup>
</Project>

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Utilities;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner
{
@@ -8,65 +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.RealArcadeInstaller: return new FileType.RealArcadeInstaller();
case SupportedFileType.RealArcadeMezzanine: return new FileType.RealArcadeMezzanine();
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,
};
}
}
}

View File

@@ -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;
}

View File

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

View File

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

View File

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

View File

@@ -50,7 +50,14 @@ namespace BinaryObjectScanner.FileType
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)

View File

@@ -50,7 +50,14 @@ namespace BinaryObjectScanner.FileType
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)

View File

@@ -50,7 +50,15 @@ namespace BinaryObjectScanner.FileType
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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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
}
}
}

View File

@@ -39,15 +39,15 @@ 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
{
@@ -59,7 +59,14 @@ namespace BinaryObjectScanner.Packer
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)

View File

@@ -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,7 +76,6 @@ namespace BinaryObjectScanner.Packer
/// <summary>
/// Handle common extraction between executable types
/// </summary>
/// <inheritdoc/>
public static string? Extract(string file, bool includeDebug)
{
#if NET462_OR_GREATER || NETCOREAPP

View File

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

View File

@@ -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);
}
}

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Serialization.Wrappers;
@@ -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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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);
}
}
}

View File

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

View File

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

View File

@@ -0,0 +1,194 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.IO.Extensions;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
{
// TODO: Technically not necessary, but just check for light/pro first and only if it isn't found look for the other.
// It should be an Or situation and not an And situation.
// TODO: Figure out if Light and Professional are what designate rings and rings+disccheck
public class CopyX : IPathCheck, IPortableExecutableCheck
{
// Previous check 'Tivola Ring Protect' removed because it was found to actually be copy-x.
// The checks were for ZDAT/webmast.dxx and ZDAT/webmast.dxx, for Redump IDs 81628 and 116418.
// https://web.archive.org/web/20011016234742/http://www.optimal-online.de:80/product/copy_x.htm
// There are four kinds of copy-X; Light, Profesisonal, audio, and Trial Maker.
// Audio is for Audio CDs. Might be scannable, might not. Samples needed to confirm.
// No samples of Trial are known at the moment, so it can't be checked for either.
// There are two kinds of copy-X generally observed; those with only rings, and those with rings and a disc check.
// These comments assume with 0 evidence that the former is Light and the latter is Professional.
// Because there is no evidence, only copy-X is being returned for now. This check has pre-emptively separated
// the two, just for when a designation can be applied for sure.
// Overall:
// Whenever these comments state "at the end of" or "at the start of" pertaining to the filesystem, they refer
// to alphabetical order, because this is how copy-X images seem to be mastered usually (not always, but w/e).
// Both Light and Professional have a directory at the end of the image. The files within this directory are
// intersected by the physical ring.
// This file is usually called ZDAT, but not always. At least one instance of Light calls it ZDATA. At least one
// instance of Light calls it System.
// Seemingly it can be anything. It doesn't help that most known samples are specifically from one company's
// games, Tivola. Still, most use ZDAT.
// Professional:
// All instances of professional contain a disc check, performed via optgraph.dll.
// All instances of professional contain in a directory usually (but not always, German Emergency 2 Deluxe has a
// Videos folder as well, which isn't involved in rings/protection) at the end of the image, 3 files:
// gov_[something].x64, iofile.x64, and sound.x64. So far, they have always been in a directory called "System".
// Due to gov's minor name variance, sound.x64 sometimes being intersected by a ring at the start, and
// iofile.x64 being referenced directly in optgraph.x64, only iofile.x64 is being checked for now.
// TODO: optgraph.dll also contains DRM to prevent kernel debugger SoftICE from being used, via a process called
// SoftICE-Test. It is not currently known if this is specifically part of copy-X, or if it's an external
// solution employed by both copy-X and also other companies. If it's the latter, it should have its own check.
// It has none here since it wouldn't be necessary.
// Light:
// All instances of light contain 1 or more files in the directory usually (but not always; Kenny's Adventure has
// uses a System folder, and then has a non-protection Xtras folder on the disc as well) at the end of the image.
// They all consist of either 0x00, or some data that matches between entries (and also is present in the 3
// Professional files), except for the parts with the rings running through them.
// Find a viable way to check the last directory alphabetically and not just ZDAT*
/// <inheritdoc/>
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Checks for Professional
// PEX checks intentionally only detect Professional
var sections = pex.Model.SectionTable;
if (sections == null)
return null;
if (pex.OverlayStrings != null)
{
// Checks if main executable contains reference to optgraph.dll.
// This might be better removed later, as Redump ID 82475 is a false positive, and also doesn't actually
// contain the actual optgraph.dll file.
// TODO: Find a way to check for situations like Redump ID 48393, where the string is spaced out with
// 0x00 between letters and does not show up on string checks.
// TODO: This might need to check every single section. Unsure until more samples are acquired.
// TODO: TKKG also has an NE 3.1x executable with a reference. This can be added later.
// Samples: Redump ID 108150
if (pex.OverlayStrings.Any(s => s.Contains("optgraph.dll")))
return "copy-X [Check disc for physical ring]";
}
var strs = pex.GetFirstSectionStrings(".rdata");
if (strs != null)
{
// Samples: Redump ID 82475, German Emergency 2 Deluxe, Redump ID 48393
if (strs.Any(s => s.Contains("optgraph.dll")))
return "copy-X [Check disc for physical ring]";
}
return null;
}
/// <inheritdoc/>
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var protections = new List<string>();
if (files == null)
return protections;
// Checks for Light
// Directory checks intentionally only detect Light
// Excludes files with .x64 extension to avoid flagging Professional files.
// Sorts list of files in ZDAT* so just the first file gets pulled, later ones have a chance of the ring
// intersecting the start of the file.
// Kenny's Adventure uses System instead of ZDAT.
string[] dirs = ["ZDAT", "ZDATA", "ZZDAT", "ZZDATA", "ZYDAT", "ZYDATA", "System"];
List<string>? lightFiles = null;
// TODO: Compensate for the check being run a directory or more higher
var fileList = files.Where(f => !f.EndsWith(".x64", StringComparison.OrdinalIgnoreCase));
foreach (var dir in dirs)
{
lightFiles = fileList.Where(f =>
{
f = f.Remove(0, path.Length);
f = f.TrimStart('/', '\\');
return f.StartsWith(dir + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase);
})
.OrderBy(f => f)
.ToList();
if (lightFiles.Count > 0)
break;
}
if ((lightFiles != null) && (lightFiles.Count > 0))
{
try
{
using var stream = File.OpenRead(lightFiles[0]);
byte[] block = stream.ReadBytes(1024);
var matchers = new List<ContentMatchSet>
{
// Checks if the file contains 0x00
// Samples: Redump ID 81628
new(Enumerable.Repeat<byte?>(0x00, 1024).ToArray(), "copy-X"),
// Checks for whatever this data is.
// Samples: Redump ID 84759, Redump ID 107929. Professional discs also have this data, hence the exclusion check.
new(
[
0x02, 0xFE, 0x4A, 0x4F, 0x52, 0x4B, 0x1C, 0xE0,
0x79, 0x8C, 0x7F, 0x85, 0x04, 0x00, 0x46, 0x46,
0x49, 0x46, 0x07, 0xF9, 0x9F, 0xA0, 0xA1, 0x9D,
0xDA, 0xB6, 0x2C, 0x2D, 0x2D, 0x2C, 0xFF, 0x00,
0x6F, 0x6E, 0x71, 0x6A, 0xFC, 0x06, 0x64, 0x62,
0x65, 0x5F, 0xFB, 0x06, 0x31, 0x31, 0x31, 0x31,
0x00, 0x00, 0x1D, 0x1D, 0x1F, 0x1D, 0xFE, 0xFD,
0x51, 0x57, 0x56, 0x51, 0xFB, 0x06, 0x33, 0x34,
], "copy-X [Check disc for physical ring]"),
};
var match = MatchUtil.GetFirstMatch(lightFiles[0], block, matchers, false);
if (!string.IsNullOrEmpty(match))
protections.Add(match!);
}
catch { }
}
return protections;
}
/// <inheritdoc/>
public string? CheckFilePath(string path)
{
// Checks for Professional
// File Path checks intentionally only detect Professional
var matchers = new List<PathMatchSet>
{
// Samples: Redump ID 108150, Redump ID 48393
// File responsible for disc check
new(new FilePathMatch("optgraph.dll"), "copy-X [Check disc for physical ring]"),
// Seemingly comorbid file, referenced in above file
new(new FilePathMatch("iofile.x64"), "copy-X [Check disc for physical ring]"),
// Seemingly comorbid file
new(new FilePathMatch("sound.x64"), "copy-X [Check disc for physical ring]"),
// Seemingly comorbid file
// Check commented out until implementation can be decided
// At least one disc seen online calls it mov_05.x64
// new(new FilePathMatch("gov_*.x64"), "copy-X [Check disc for physical ring]"),
};
return MatchUtil.GetFirstMatch(path, matchers, any: true);
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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);
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,12 +1,10 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -51,33 +49,29 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{
// All found to be present on at multiple albums with LabelGate CD2 (Redump entry 95010 and product ID SVWC-7185), the original version of LabelGate still needs to be investigated.
new(new List<PathMatch>
{
new(
[
#if NET20 || NET35
new(Path.Combine(Path.Combine("BIN", "WIN32"), "MQ2SETUP.EXE").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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,11 +1,10 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -13,6 +12,8 @@ namespace BinaryObjectScanner.Protection
/// <summary>
/// SafeCast is in the same family of protections as SafeDisc, and appears to mainly be for license management, and doesn't appear to affect the mastering of the disc in any way.
/// Although SafeCast is most commonly used in non-game software, there is one game that comes with both SafeDisc and SafeCast protections (Redump entry 83145).
/// SafeCast has been confirmed to be present on some programs, such as AutoDesk 3ds Max (IA items CMCD0204 and game-programming-in-c-start-to-finish-2006), Photoshop CS2 (IA item ccd0605), and Boonty Box (IA items PC_Gamer_Disc_7.55_July_2005 and cdrom-pcgamercd7.58).
/// TODO: Check Boonty Box samples closer for new possible detections, there are at least more checks for FlexLM possible.
/// Macrovision bought the company C-Dilla and created SafeCast based on C-Dilla's existing products (https://web.archive.org/web/20030212040047/http://www.auditmypc.com/freescan/readingroom/cdilla.asp).
/// There are multiple different versions of SafeCast out there.
/// Deep dive of MechWarrior 4 and its expansions, which use SafeDisc, possibly SafeDisc LT, and SafeCast: https://digipres.club/@TheRogueArchivist/110224192068908590
@@ -78,6 +79,7 @@ namespace BinaryObjectScanner.Protection
// TODO: Investigate import hint/name table entry "CdaSysInstall"
// TODO: Investigate string table entries: "CDWP02DG", "CDWP02DG", "CDWS02DG"
// TODO: Invesitgate if the "AdobeLM.dll" file (along with mentions of "AdobeLM" in executables) uniquely identifies SafeCast, or if it can be used with different DRM. (Found in IA item ccd0605)
// Get the import directory table, if it exists
if (pex.Model.ImportTable?.ImportDirectoryTable != null)
@@ -146,11 +148,7 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc cref="Interfaces.IPathCheck.CheckDirectoryPath(string, IEnumerable{string})"/>
#if NET20 || NET35
internal Queue<string> SafeCastCheckDirectoryPath(string path, IEnumerable<string>? files)
#else
internal ConcurrentQueue<string> SafeCastCheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
internal IEnumerable<string> SafeCastCheckDirectoryPath(string path, IEnumerable<string>? files)
{
var matchers = new List<PathMatchSet>
{

View File

@@ -1,12 +1,10 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SabreTools.Hashing;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -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"),

View File

@@ -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

View File

@@ -1,14 +1,12 @@
using System;
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Utilities;
using SabreTools.IO.Extensions;
using SabreTools.Matching;
using SabreTools.Matching.Content;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -69,6 +67,9 @@ namespace BinaryObjectScanner.Protection
// The stxt371 and stxt774 sections are found in various newer Macrovision products, including various versions of CDS-300, SafeCast, and SafeDisc.
// They may indicate SafeWrap, but this hasn't been confirmed yet.
// Almost every single sample known has both sections, though one only contains the "stxt371" section. It is unknown if this is intentional, or if the game functions without it.
// It is present in the "Texas HoldEm!" game in "boontybox_PCGamer_DVD.exe" in IA items PC_Gamer_Disc_7.55_July_2005 and cdrom-pcgamercd7.58.
// Other games in this set also aren't functional despite having the normal layout of stxt sections, and the primary program doesn't install at all due to activation servers being down.
bool stxt371Section = pex.ContainsSection("stxt371", exact: true);
bool stxt774Section = pex.ContainsSection("stxt774", exact: true);
if (stxt371Section || stxt774Section)
@@ -164,80 +165,44 @@ namespace BinaryObjectScanner.Protection
}
/// <inheritdoc/>
#if NET20 || NET35
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#else
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
#endif
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
{
#if NET20 || NET35
var results = new Queue<string>();
#else
var results = new ConcurrentQueue<string>();
#endif
var results = new List<string>();
// Run Macrovision directory checks
var macrovision = MacrovisionCheckDirectoryPath(path, files);
#if NET20 || NET35
if (macrovision != null && macrovision.Count > 0)
#else
if (macrovision != null && !macrovision.IsEmpty)
#endif
if (macrovision != null)
results.AddRange(macrovision);
// Run Cactus Data Shield directory checks
var cactusDataShield = CactusDataShieldCheckDirectoryPath(path, files);
#if NET20 || NET35
if (cactusDataShield != null && cactusDataShield.Count > 0)
#else
if (cactusDataShield != null && !cactusDataShield.IsEmpty)
#endif
if (cactusDataShield != null)
results.AddRange(cactusDataShield);
// Run C-Dilla directory checks
var cDilla = CDillaCheckDirectoryPath(path, files);
#if NET20 || NET35
if (cDilla != null && cDilla.Count > 0)
#else
if (cDilla != null && !cDilla.IsEmpty)
#endif
if (cDilla != null)
results.AddRange(cDilla);
// Run RipGuard directory checks
var ripGuard = RipGuardCheckDirectoryPath(path, files);
#if NET20 || NET35
if (ripGuard != null && ripGuard.Count > 0)
#else
if (ripGuard != null && !ripGuard.IsEmpty)
#endif
if (ripGuard != null)
results.AddRange(ripGuard);
// Run SafeCast directory checks
var safeCast = SafeCastCheckDirectoryPath(path, files);
#if NET20 || NET35
if (safeCast != null && safeCast.Count > 0)
#else
if (safeCast != null && !safeCast.IsEmpty)
#endif
if (safeCast != null)
results.AddRange(safeCast);
// Run SafeDisc directory checks
var safeDisc = SafeDiscCheckDirectoryPath(path, files);
#if NET20 || NET35
if (safeDisc != null && safeDisc.Count > 0)
#else
if (safeDisc != null && !safeDisc.IsEmpty)
#endif
if (safeDisc != null)
results.AddRange(safeDisc);
if (results != null && results.Count > 0)
return results;
#if NET20 || NET35
return new Queue<string>();
#else
return new ConcurrentQueue<string>();
#endif
return [];
}
/// <inheritdoc/>
@@ -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)];
}

View File

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

View File

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

View File

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

View File

@@ -1,9 +1,7 @@
#if NET40_OR_GREATER || NETCOREAPP
using System.Collections.Concurrent;
#endif
using System.Collections.Generic;
using System.Collections.Generic;
using BinaryObjectScanner.Interfaces;
using SabreTools.Matching;
using SabreTools.Matching.Paths;
using SabreTools.Serialization.Wrappers;
namespace BinaryObjectScanner.Protection
@@ -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>
{

View File

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

View File

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

View File

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

View File

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

View File

@@ -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"/>
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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