mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-04-05 22:01:12 +00:00
Add support for .NET 10
This commit is contained in:
80
.github/workflows/build_and_test.yml
vendored
80
.github/workflows/build_and_test.yml
vendored
@@ -1,48 +1,48 @@
|
||||
name: Build and Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
push:
|
||||
branches: ["master"]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: |
|
||||
6.0.x
|
||||
8.0.x
|
||||
9.0.x
|
||||
|
||||
- name: Run tests
|
||||
run: dotnet test
|
||||
|
||||
- name: Run publish script
|
||||
run: ./publish-nix.sh -d
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Update rolling tag
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git tag -f rolling
|
||||
git push origin :refs/tags/rolling || true
|
||||
git push origin rolling --force
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v5
|
||||
with:
|
||||
dotnet-version: |
|
||||
8.0.x
|
||||
9.0.x
|
||||
10.0.x
|
||||
|
||||
- name: Upload to rolling
|
||||
uses: ncipollo/release-action@v1.14.0
|
||||
with:
|
||||
allowUpdates: True
|
||||
artifacts: "*.nupkg,*.snupkg,*.zip"
|
||||
body: 'Last built commit: ${{ github.sha }}'
|
||||
name: 'Rolling Release'
|
||||
prerelease: True
|
||||
replacesArtifacts: True
|
||||
tag: "rolling"
|
||||
updateOnlyUnreleased: True
|
||||
- name: Run tests
|
||||
run: dotnet test
|
||||
|
||||
- name: Run publish script
|
||||
run: ./publish-nix.sh -d
|
||||
|
||||
- name: Update rolling tag
|
||||
run: |
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git tag -f rolling
|
||||
git push origin :refs/tags/rolling || true
|
||||
git push origin rolling --force
|
||||
|
||||
- name: Upload to rolling
|
||||
uses: ncipollo/release-action@v1.20.0
|
||||
with:
|
||||
allowUpdates: True
|
||||
artifacts: "*.nupkg,*.snupkg,*.zip"
|
||||
body: "Last built commit: ${{ github.sha }}"
|
||||
name: "Rolling Release"
|
||||
prerelease: True
|
||||
replacesArtifacts: True
|
||||
tag: "rolling"
|
||||
updateOnlyUnreleased: True
|
||||
|
||||
34
.github/workflows/check_pr.yml
vendored
34
.github/workflows/check_pr.yml
vendored
@@ -3,21 +3,21 @@ name: Build PR
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: |
|
||||
6.0.x
|
||||
8.0.x
|
||||
9.0.x
|
||||
|
||||
- name: Build
|
||||
run: dotnet build
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Run tests
|
||||
run: dotnet test
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v5
|
||||
with:
|
||||
dotnet-version: |
|
||||
8.0.x
|
||||
9.0.x
|
||||
10.0.x
|
||||
|
||||
- name: Build
|
||||
run: dotnet build
|
||||
|
||||
- name: Run tests
|
||||
run: dotnet test
|
||||
|
||||
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@@ -10,7 +10,7 @@
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/ProtectionScan/bin/Debug/net9.0/ProtectionScan.dll",
|
||||
"program": "${workspaceFolder}/ProtectionScan/bin/Debug/net10.0/ProtectionScan.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/ProtectionScan",
|
||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<IsPackable>false</IsPackable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -16,8 +16,8 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="[2.1.0]" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="[2.2.0]" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
@@ -31,4 +31,3 @@ namespace BinaryObjectScanner.Test.FileType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,4 +31,3 @@ namespace BinaryObjectScanner.Test.FileType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,4 +31,3 @@ namespace BinaryObjectScanner.Test.FileType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,4 +31,3 @@ namespace BinaryObjectScanner.Test.FileType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,4 +31,3 @@ namespace BinaryObjectScanner.Test.FileType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,4 +31,3 @@ namespace BinaryObjectScanner.Test.FileType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,4 +28,3 @@ namespace BinaryObjectScanner.Test.FileType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
@@ -34,11 +34,11 @@
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`))">
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`)) OR $(TargetFramework.StartsWith(`net10`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(RuntimeIdentifier.StartsWith(`osx-arm`))">
|
||||
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -46,12 +46,12 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="GrindCore.SharpCompress" Version="0.40.4-alpha" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||
<PackageReference Include="GrindCore.SharpCompress" Version="0.41.0" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||
<PackageReference Include="MinThreadingBridge" Version="0.11.4" Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net40`))" />
|
||||
<PackageReference Include="SabreTools.Hashing" Version="[1.5.1]" />
|
||||
<PackageReference Include="SabreTools.IO" Version="[1.8.0]" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="[2.1.0]" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="9.0.10" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||
<PackageReference Include="SabreTools.Hashing" Version="[1.6.0]" />
|
||||
<PackageReference Include="SabreTools.IO" Version="[1.9.0]" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="[2.2.0]" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="10.0.0" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -105,10 +105,11 @@ namespace BinaryObjectScanner.Data
|
||||
string key = keys[i];
|
||||
|
||||
// If the key is empty, remove it
|
||||
if (this[key] == null || this[key].Count == 0)
|
||||
#if NET20 || NET35
|
||||
if (this[key] == null || this[key].Count == 0)
|
||||
Remove(key);
|
||||
#else
|
||||
if (this[key] == null || this[key].IsEmpty)
|
||||
TryRemove(key, out _);
|
||||
#endif
|
||||
}
|
||||
@@ -167,7 +168,11 @@ namespace BinaryObjectScanner.Data
|
||||
continue;
|
||||
|
||||
// Otherwise, get the new key name and transfer over
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
string newKey = currentKey[pathToStrip!.Length..];
|
||||
#else
|
||||
string newKey = currentKey.Substring(pathToStrip!.Length);
|
||||
#endif
|
||||
this[newKey] = this[currentKey];
|
||||
#if NET20 || NET35
|
||||
Remove(currentKey);
|
||||
@@ -243,7 +248,11 @@ namespace BinaryObjectScanner.Data
|
||||
var protections = new List<string>();
|
||||
|
||||
// If we have an indicator of multiple protections
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
if (protection!.Contains(';'))
|
||||
#else
|
||||
if (protection!.Contains(";"))
|
||||
#endif
|
||||
{
|
||||
var splitProtections = protection.Split(';');
|
||||
protections.AddRange(splitProtections);
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace BinaryObjectScanner.FileType
|
||||
// Currently-found worst cases:
|
||||
// "Y:1BY:1BC" in Redump ID 23339
|
||||
var strings = bytes.ReadStringsWithEncoding(charLimit: 7, Encoding.ASCII);
|
||||
var rgx = new Regex("[^a-zA-Z0-9 -'!,.]");
|
||||
var rgx = new Regex("[^a-zA-Z0-9 -'!,.]", RegexOptions.Compiled);
|
||||
foreach (string str in strings)
|
||||
{
|
||||
if (rgx.Replace(str, "").Length > 7)
|
||||
@@ -112,7 +112,7 @@ namespace BinaryObjectScanner.FileType
|
||||
potentialAppUseString = applicationUse.ReadNullTerminatedAnsiString(ref offset);
|
||||
if (potentialAppUseString == "FS")
|
||||
return false;
|
||||
|
||||
|
||||
offset = 141;
|
||||
potentialAppUseString = applicationUse.ReadNullTerminatedAnsiString(ref offset);
|
||||
if (potentialAppUseString == "CD-XA001")
|
||||
|
||||
@@ -60,6 +60,7 @@ namespace BinaryObjectScanner.Packer
|
||||
// TODO: Don't read entire file
|
||||
// TODO: Only 64 bytes at the end of the file is needed
|
||||
|
||||
#pragma warning disable CS0618
|
||||
byte[]? data = exe.ReadArbitraryRange();
|
||||
if (data == null)
|
||||
return "Unknown 1.X";
|
||||
|
||||
@@ -17,7 +17,11 @@ namespace BinaryObjectScanner.Packer
|
||||
string? name = exe.AssemblyDescription;
|
||||
|
||||
if (name.OptionalStartsWith("Nullsoft Install System"))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
return $"NSIS {name!["Nullsoft Install System".Length..].Trim()}";
|
||||
#else
|
||||
return $"NSIS {name!.Substring("Nullsoft Install System".Length).Trim()}";
|
||||
#endif
|
||||
|
||||
name = exe.AssemblyName;
|
||||
|
||||
|
||||
@@ -12,7 +12,11 @@ namespace BinaryObjectScanner.Packer
|
||||
string? name = exe.AssemblyDescription;
|
||||
|
||||
if (name.OptionalStartsWith("7-Zip Self-extracting Archive"))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
return $"7-Zip SFX {exe.AssemblyDescription!["7-Zip Self-extracting Archive ".Length..]}";
|
||||
#else
|
||||
return $"7-Zip SFX {exe.AssemblyDescription!.Substring("7-Zip Self-extracting Archive ".Length)}";
|
||||
#endif
|
||||
|
||||
name = exe.FileDescription;
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@ namespace BinaryObjectScanner.Packer
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class UPX : IExecutableCheck<PortableExecutable>
|
||||
{
|
||||
private static readonly Regex _oldUpxVersionMatch = new Regex(@"\$Id: UPX (.*?) Copyright \(C\)", RegexOptions.Compiled);
|
||||
private static readonly Regex _oldUpxVersionMatch = new(@"\$Id: UPX (.*?) Copyright \(C\)", RegexOptions.Compiled);
|
||||
|
||||
private static readonly Regex _upxVersionMatch = new Regex(@"^([0-9]\.[0-9]{2})$", RegexOptions.Compiled);
|
||||
private static readonly Regex _upxVersionMatch = new(@"^([0-9]\.[0-9]{2})$", RegexOptions.Compiled);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace BinaryObjectScanner.Protection
|
||||
if (applicationIdentifierString == null || applicationIdentifierString.Length < 14)
|
||||
return null;
|
||||
|
||||
if (!Regex.IsMatch(applicationIdentifierString, "^[A-Z0-9]*$"))
|
||||
if (!Regex.IsMatch(applicationIdentifierString, "^[A-Z0-9]*$", RegexOptions.Compiled))
|
||||
return null;
|
||||
|
||||
// While some alpharom discs have data in the publisher identifier that can be checked, not all of them do,
|
||||
@@ -75,7 +75,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// #2 examples: 2003120514103077LAHD, 20040326195254AVKC, 20051019163346WXUDCD
|
||||
|
||||
var applicationIdentifierStringBytes = Encoding.ASCII.GetBytes(applicationIdentifierString);
|
||||
|
||||
|
||||
// Type #1: 18 characters long, mix of letters and numbers. Since the string has already been confirmed
|
||||
// to only consist of capital letters and numbers, a basic byte value check can be performed to ensure
|
||||
// at least 5 bytes are numbers and 5 bytes are letters. Unfortunately, there doesn't seem to be quite
|
||||
@@ -86,26 +86,38 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
return "Alpha-ROM";
|
||||
}
|
||||
|
||||
|
||||
// Type #2: Usually 20 characters long, but Redump ID 124334 is 18 characters long. Validate that it
|
||||
// starts with YYYYMMDD, followed by 6-8 more numbers, followed by letters.
|
||||
if (applicationIdentifierString.Length >= 18 && applicationIdentifierString.Length <= 20)
|
||||
{
|
||||
if (Int32.TryParse(applicationIdentifierString.Substring(0, 4), out int year) == false
|
||||
|| Int32.TryParse(applicationIdentifierString.Substring(4, 2), out int month) == false
|
||||
|| Int32.TryParse(applicationIdentifierString.Substring(6, 2), out int day) == false
|
||||
|| Int32.TryParse(applicationIdentifierString.Substring(8, 6), out int extraTime) == false)
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
if (int.TryParse(applicationIdentifierString.AsSpan(0, 4), out int year) == false
|
||||
|| int.TryParse(applicationIdentifierString.AsSpan(4, 2), out int month) == false
|
||||
|| int.TryParse(applicationIdentifierString.AsSpan(6, 2), out int day) == false
|
||||
|| int.TryParse(applicationIdentifierString.AsSpan(8, 6), out int extraTime) == false)
|
||||
#else
|
||||
if (int.TryParse(applicationIdentifierString.Substring(0, 4), out int year) == false
|
||||
|| int.TryParse(applicationIdentifierString.Substring(4, 2), out int month) == false
|
||||
|| int.TryParse(applicationIdentifierString.Substring(6, 2), out int day) == false
|
||||
|| int.TryParse(applicationIdentifierString.Substring(8, 6), out int extraTime) == false)
|
||||
#endif
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
if (year >= 2009 || year < 2000 || month > 12 || day > 31)
|
||||
return null;
|
||||
|
||||
|
||||
int index = Array.FindIndex(applicationIdentifierStringBytes, b => b > 60);
|
||||
|
||||
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
var startingNumbers = Encoding.ASCII.GetBytes(applicationIdentifierString[..index]);
|
||||
var finalCharacters = Encoding.ASCII.GetBytes(applicationIdentifierString[index..]);
|
||||
#else
|
||||
var startingNumbers = Encoding.ASCII.GetBytes(applicationIdentifierString.Substring(0, index));
|
||||
var finalCharacters = Encoding.ASCII.GetBytes(applicationIdentifierString.Substring(index));
|
||||
#endif
|
||||
if (Array.TrueForAll(startingNumbers, b => b < 60) && Array.TrueForAll(finalCharacters, b => b > 60))
|
||||
return "Alpha-ROM";
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public string? CheckExecutable(string file, NewExecutable exe, bool includeDebug)
|
||||
{
|
||||
// TODO: Don't read entire file
|
||||
#pragma warning disable CS0618
|
||||
byte[]? data = exe.ReadArbitraryRange();
|
||||
if (data == null)
|
||||
return null;
|
||||
@@ -272,7 +273,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// Full string ends with # (i.e. "CD-Cops, ver. 1.72, #"), use that to compensate for comma in version
|
||||
// number cases (don't change the comma, see earlier to-do) like "DVD-Cops, ver. 1,60, #"
|
||||
// TODO: improve regex via the starting "N" character? Possibly unnecessary?
|
||||
var versionMatch = Regex.Match(match, @"(?<=D-Cops,\s{1,}ver. )(.*?)(?=,\s{1,}#)");
|
||||
var versionMatch = Regex.Match(match, @"(?<=D-Cops,\s{1,}ver. )(.*?)(?=,\s{1,}#)", RegexOptions.Compiled);
|
||||
if (versionMatch.Success)
|
||||
return versionMatch.Value;
|
||||
|
||||
|
||||
@@ -13,10 +13,10 @@ namespace BinaryObjectScanner.Protection
|
||||
/// It may have been developed by Russobit-M, though the same source also says that StarForce was created by the same company as well, which seems unlikely (https://m.linkdatasecurity.com/pnews6.htm).
|
||||
/// Others online have been confused by this as well (https://forum.ixbt.com/topic.cgi?id=31:009712).
|
||||
/// A game referred to as having CD-Guard by http://lastboss.ru/games/RUS/randevu-s-neznakomkoi-2 that was published by Russobit-M is known to have an early version of StarForce (Redump entry 97088).
|
||||
/// The FAQ on the game's official website indicates that StarForce specifically is present (https://web.archive.org/web/20011220224222/http://www.aha.ru/~exe_soft/russian/exesoft.htm).
|
||||
/// The FAQ on the game's official website indicates that StarForce specifically is present (https://web.archive.org/web/20011220224222/http://www.aha.ru/~exe_soft/russian/exesoft.htm).
|
||||
/// It's unknown for sure if there were two separate versions of this game that contained separate protections, or if the game never actually contained CD-Guard, or if CD-Guard was an early name for the StarForce line of products.
|
||||
/// There is a re-release of an earlier game by the same developer that seems to include both CD-Guard and StarForce drivers, with the CD-Guard driver seemingly not used during installation, nor installed onto the system (IA item "pahgeby-he3hakomkou").
|
||||
///
|
||||
///
|
||||
/// Additional resources and references:
|
||||
/// https://gamecopyworld.com/games/pc_omikron.shtml
|
||||
/// https://forum.ixbt.com/topic.cgi?id=31:3985
|
||||
|
||||
@@ -110,7 +110,11 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
lightFiles = fileList.FindAll(f =>
|
||||
{
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
f = f[path.Length..];
|
||||
#else
|
||||
f = f.Remove(0, path.Length);
|
||||
#endif
|
||||
f = f.TrimStart('/', '\\');
|
||||
return f.StartsWith(dir + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase);
|
||||
});
|
||||
|
||||
@@ -23,7 +23,11 @@ namespace BinaryObjectScanner.Protection
|
||||
if (bupfile.DirectoryName == null)
|
||||
continue;
|
||||
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
string ifofile = Path.Combine(bupfile.DirectoryName, bupfile.Name[..^bupfile.Extension.Length] + ".ifo");
|
||||
#else
|
||||
string ifofile = Path.Combine(bupfile.DirectoryName, bupfile.Name.Substring(0, bupfile.Name.Length - bupfile.Extension.Length) + ".ifo");
|
||||
#endif
|
||||
if (bupfile.Length != ifofile.FileSize())
|
||||
{
|
||||
protections.Add("DVD-Movie-PROTECT (Unconfirmed - Please report to us on Github)");
|
||||
|
||||
@@ -102,12 +102,11 @@ namespace BinaryObjectScanner.Protection
|
||||
// Mad Max, Metal Gear Solid: TPP, Rise of the Tomb Raider
|
||||
new(
|
||||
new ContentMatch(
|
||||
new byte?[]
|
||||
{
|
||||
[
|
||||
0x51, 0x52, 0x41, 0x50, 0x41, 0x51, 0x4C, 0x8D,
|
||||
null, null, null, null, null, 0x4C, 0x8D, null,
|
||||
null, null, null, null, 0x4D, 0x29, 0xC1,
|
||||
},
|
||||
],
|
||||
end: 0
|
||||
),
|
||||
"Denuvo v1.0 (x64)"),
|
||||
@@ -115,11 +114,10 @@ namespace BinaryObjectScanner.Protection
|
||||
// Lords of the Fallen, Batman: AK, Just Cause 3, Sherlock Holmes: TdD, Tales of Berseria etc
|
||||
new(
|
||||
new ContentMatch(
|
||||
new byte?[]
|
||||
{
|
||||
[
|
||||
0x48, 0x8D, 0x0D, null, null, null, null, 0xE9,
|
||||
null, null, null, null,
|
||||
},
|
||||
],
|
||||
end: 0
|
||||
),
|
||||
"Denuvo v2.0a (x64)"),
|
||||
@@ -127,13 +125,12 @@ namespace BinaryObjectScanner.Protection
|
||||
// Yesterday Origins
|
||||
new(
|
||||
new ContentMatch(
|
||||
new byte?[]
|
||||
{
|
||||
[
|
||||
0x48, 0x89, null, null, null, null, null, 0x48,
|
||||
0x89, null, null, null, null, null, 0x4C, 0x89,
|
||||
null, null, null, null, null, 0x4C, 0x89, null,
|
||||
null, null, null, null, 0x48, 0x83, 0xFA, 0x01,
|
||||
},
|
||||
],
|
||||
end: 0
|
||||
),
|
||||
"Denuvo v2.0b (x64)"),
|
||||
@@ -141,11 +138,10 @@ namespace BinaryObjectScanner.Protection
|
||||
// Sniper Ghost Warrior 3 (beta), Dead Rising 4 (SteamStub-free)
|
||||
new(
|
||||
new ContentMatch(
|
||||
new byte?[]
|
||||
{
|
||||
[
|
||||
null, null, null, null, null, null, null, null,
|
||||
0x4C, 0x89, 0x1C, 0x24, 0x49, 0x89, 0xE3,
|
||||
},
|
||||
],
|
||||
end: 0
|
||||
),
|
||||
"Denuvo v3.0a (x64)"),
|
||||
@@ -153,13 +149,12 @@ namespace BinaryObjectScanner.Protection
|
||||
// Train Sim World CSX Heavy Haul
|
||||
new(
|
||||
new ContentMatch(
|
||||
new byte?[]
|
||||
{
|
||||
[
|
||||
0x4D, 0x8D, null, null, null, null, null, null,
|
||||
null, null, null, 0x48, 0x89, null, null, null,
|
||||
null, null, 0x48, 0x8D, null, null, 0x48, 0x89,
|
||||
null, 0x48, 0x89, null, 0x48, 0x89,
|
||||
},
|
||||
],
|
||||
end: 0
|
||||
),
|
||||
"Denuvo v3.0b (x64)"),
|
||||
@@ -207,13 +202,12 @@ namespace BinaryObjectScanner.Protection
|
||||
// Pro Evolution Soccer 2017, Champions of Anteria
|
||||
new(
|
||||
new ContentMatch(
|
||||
new byte?[]
|
||||
{
|
||||
[
|
||||
0x55, 0x89, 0xE5, 0x8D, null, null, null, null,
|
||||
null, null, 0xE8, null, null, null, null, 0xE8,
|
||||
null, null, null, null, 0xE8, null, null, null,
|
||||
null, 0xE8, null, null, null, null,
|
||||
},
|
||||
],
|
||||
end: 0
|
||||
),
|
||||
"Denuvo v1.0 (x86)"),
|
||||
@@ -221,11 +215,10 @@ namespace BinaryObjectScanner.Protection
|
||||
// Romance of 13 Kingdoms, 2Dark
|
||||
new(
|
||||
new ContentMatch(
|
||||
new byte?[]
|
||||
{
|
||||
[
|
||||
0x8D, null, null, null, null, null, null, 0x89,
|
||||
0x7C, 0x24, 0x04, 0x89, 0xE7,
|
||||
},
|
||||
],
|
||||
end: 0
|
||||
),
|
||||
"Denuvo v2.0 (x86)"),
|
||||
|
||||
@@ -57,7 +57,11 @@ namespace BinaryObjectScanner.Protection
|
||||
private static string GetVersion(string match)
|
||||
{
|
||||
match = match.Trim('*').Trim();
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
return match["Gefest Protection System ".Length..];
|
||||
#else
|
||||
return match.Substring("Gefest Protection System ".Length);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
private static string GetVersion(string match)
|
||||
{
|
||||
var versionMatch = Regex.Match(match, @"(?<=InterLok )(.*?)(?=,)");
|
||||
var versionMatch = Regex.Match(match, @"(?<=InterLok )(.*?)(?=,)", RegexOptions.Compiled);
|
||||
if (versionMatch.Success)
|
||||
return versionMatch.Value;
|
||||
|
||||
|
||||
@@ -140,7 +140,11 @@ namespace BinaryObjectScanner.Protection
|
||||
if (line == null)
|
||||
return null;
|
||||
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
return $"{line[3..]} ({sr.ReadLine()})";
|
||||
#else
|
||||
return $"{line.Substring(3)} ({sr.ReadLine()})";
|
||||
#endif
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
// TODO: Don't read entire file
|
||||
#pragma warning disable CS0618
|
||||
byte[]? data = exe.ReadArbitraryRange();
|
||||
if (data == null)
|
||||
return null;
|
||||
@@ -149,13 +150,13 @@ namespace BinaryObjectScanner.Protection
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// Found in IA item "britney-spears-special-edition-cd-rom".
|
||||
new(new List<PathMatch>
|
||||
{
|
||||
new(
|
||||
[
|
||||
new FilePathMatch("C2C.16"),
|
||||
new FilePathMatch("C2C.DLL"),
|
||||
new FilePathMatch("C2CDEL.16"),
|
||||
new FilePathMatch("C2CDEL.EXE"),
|
||||
}, "SafeCast"),
|
||||
], "SafeCast"),
|
||||
|
||||
// Found in IA item "ejay_nestle_trial".
|
||||
new(new FilePathMatch("cdac01aa.dll"), "SafeCast"),
|
||||
|
||||
@@ -1043,39 +1043,32 @@ namespace BinaryObjectScanner.Protection
|
||||
return string.Empty;
|
||||
|
||||
var sha1 = HashTool.GetFileHash(firstMatchedString, HashType.SHA1);
|
||||
switch (sha1?.ToUpperInvariant())
|
||||
|
||||
return sha1?.ToUpperInvariant() switch
|
||||
{
|
||||
// Found in Redump entry 63488.
|
||||
case "DA39A3EE5E6B4B0D3255BFEF95601890AFD80709":
|
||||
return "(Empty File)";
|
||||
"DA39A3EE5E6B4B0D3255BFEF95601890AFD80709" => "(Empty File)",
|
||||
|
||||
// First known generic SafeDisc splash-screen.
|
||||
// 4-bit (16 color) version, found in Redump entries 43321, 45040, 45202, 66586, 68206, 75501, 79272, and 110603.
|
||||
case "D8A8CF761DD7C04F635385E4C4589E5F26C6171E":
|
||||
return "1.11.000-2.40.011";
|
||||
"D8A8CF761DD7C04F635385E4C4589E5F26C6171E" => "1.11.000-2.40.011",
|
||||
// 8-bit (256 color) version, found in Redump entries 43321, 45040, 45202, 66586, 68206, 75501, 79272, and 110603.
|
||||
case "0C9E45BF3EBE1382A3593994328C22BCB9A55456":
|
||||
return "1.11.000-2.40.011";
|
||||
"0C9E45BF3EBE1382A3593994328C22BCB9A55456" => "1.11.000-2.40.011",
|
||||
|
||||
// Second known generic SafeDisc splash-screen.
|
||||
// 4-bit (16 color), found in Redump entries 46339 and 75897.
|
||||
case "9B80F524D45041ED8CE1613AD5BDE94BFDBB2814":
|
||||
return "2.70.030-2.80.010";
|
||||
"9B80F524D45041ED8CE1613AD5BDE94BFDBB2814" => "2.70.030-2.80.010",
|
||||
// 8-bit (256 color) version, found in Redump entries 46339 and 75897.
|
||||
case "827AE9A32906CBE9098C9101184E0BE74CEA2744":
|
||||
return "2.70.030-2.80.010";
|
||||
"827AE9A32906CBE9098C9101184E0BE74CEA2744" => "2.70.030-2.80.010",
|
||||
|
||||
// Third known generic SafeDisc splash-screen.
|
||||
// 4-bit (16 color), found in Redump entries 74338, 75782, 84985, and 91552.
|
||||
case "814ED63FD619655650E271D1B8B46BBE39C3655A":
|
||||
return "3.15.010-3.20.022";
|
||||
"814ED63FD619655650E271D1B8B46BBE39C3655A" => "3.15.010-3.20.022",
|
||||
// 8-bit (256 color) version, found in Redump entries 31824, 74338, 75782, 84985, 91552, and 104053.
|
||||
case "40C7ACEDB6C41AB067285090373E886EFB4F4AC4":
|
||||
return "3.15.010-4.60.000";
|
||||
"40C7ACEDB6C41AB067285090373E886EFB4F4AC4" => "3.15.010-4.60.000",
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
_ => null,
|
||||
};
|
||||
|
||||
// There appear to be a few distinct generations of file names used for SafeDisc splash-screens.
|
||||
// The first are the files named "SPLSH16.BMP"/"SPLSH256.BMP", which were typically used in SafeDisc versions 1.00.025-1.01.044.
|
||||
|
||||
@@ -63,22 +63,22 @@ namespace BinaryObjectScanner.Protection
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// Found on "All That I Am" by Santana (Barcode 8 2876-59773-2 6)
|
||||
new(new List<PathMatch>
|
||||
{
|
||||
new(
|
||||
[
|
||||
// TODO: Verify if these are OR or AND
|
||||
// TODO: Verify that this is directly related to MediaMax CD-3.
|
||||
new FilePathMatch("PlayDisc.exe"),
|
||||
new FilePathMatch("PlayDisc.xml"),
|
||||
}, "MediaMax CD-3"),
|
||||
], "MediaMax CD-3"),
|
||||
|
||||
// Found on "Contraband" by Velvet Revolver (Barcode 8 28766 05242 8)
|
||||
// "SCCD3X01.dll" should already be detected by the content checks, but not "SCCD3X02.dll".
|
||||
new(new List<PathMatch>
|
||||
{
|
||||
new(
|
||||
[
|
||||
// TODO: Verify if these are OR or AND
|
||||
new FilePathMatch("SCCD3X01.dll"),
|
||||
new FilePathMatch("SCCD3X02.dll"),
|
||||
}, "MediaMax CD-3"),
|
||||
], "MediaMax CD-3"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: false);
|
||||
|
||||
@@ -32,12 +32,17 @@ namespace BinaryObjectScanner.Protection
|
||||
if (copyrightString == null || copyrightString.Length < 19)
|
||||
return null;
|
||||
|
||||
copyrightString = copyrightString.Substring(0, 19); // Redump ID 15896 has a trailing space
|
||||
// Redump ID 15896 has a trailing space
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
copyrightString = copyrightString[..19];
|
||||
#else
|
||||
copyrightString = copyrightString.Substring(0, 19);
|
||||
#endif
|
||||
|
||||
// Stores some kind of serial in the copyright string, format 0000-XXXX-XXXX-XXXX where it can be numbers or
|
||||
// capital letters.
|
||||
|
||||
if (!Regex.IsMatch(copyrightString, "[0]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}"))
|
||||
if (!Regex.IsMatch(copyrightString, "[0]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}", RegexOptions.Compiled))
|
||||
return null;
|
||||
|
||||
offset = 0;
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public string? CheckExecutable(string file, NewExecutable exe, bool includeDebug)
|
||||
{
|
||||
// TODO: Don't read entire file
|
||||
#pragma warning disable CS0618
|
||||
byte[]? data = exe.ReadArbitraryRange();
|
||||
if (data == null)
|
||||
return null;
|
||||
@@ -335,24 +336,24 @@ namespace BinaryObjectScanner.Protection
|
||||
new(new FilePathMatch("SNTUSB95.SYS"), "Rainbow Sentinel USB Driver"),
|
||||
|
||||
// Found in IA item "czchip199707cd".
|
||||
new(new List<PathMatch>
|
||||
{
|
||||
new(
|
||||
[
|
||||
new FilePathMatch("DOSMON.EXE"),
|
||||
new FilePathMatch("FIND.EXE"),
|
||||
new FilePathMatch("NCEDIT.EXE"),
|
||||
new FilePathMatch("NETEVAL.EXE"),
|
||||
}, "Rainbow NetSentinel Monitor for DOS"),
|
||||
], "Rainbow NetSentinel Monitor for DOS"),
|
||||
|
||||
// Found in IA item "czchip199707cd".
|
||||
new(new List<PathMatch>
|
||||
{
|
||||
new(
|
||||
[
|
||||
new FilePathMatch("OS2MON.EXE"),
|
||||
new FilePathMatch("RHPANELP.DLL"),
|
||||
}, "Rainbow NetSentinel Monitor for OS/2"),
|
||||
], "Rainbow NetSentinel Monitor for OS/2"),
|
||||
|
||||
// Found in IA item "czchip199707cd".
|
||||
new(new List<PathMatch>
|
||||
{
|
||||
new(
|
||||
[
|
||||
new FilePathMatch("MAPFILE.TXT"),
|
||||
new FilePathMatch("NKWIN32.DLL"),
|
||||
new FilePathMatch("NSLMS32.DLL"),
|
||||
@@ -362,7 +363,7 @@ namespace BinaryObjectScanner.Protection
|
||||
new FilePathMatch("WINMON.EXE"),
|
||||
new FilePathMatch("WINMON.HLP"),
|
||||
new FilePathMatch("WMON_DOC.EXE"),
|
||||
}, "Rainbow NetSentinel Monitor for Win32"),
|
||||
], "Rainbow NetSentinel Monitor for Win32"),
|
||||
|
||||
// Found in IA item "chip-cds-2001-08".
|
||||
// File names for Rainbow Sentinel files sometimes found in ".cab" files.
|
||||
|
||||
@@ -55,20 +55,20 @@ namespace BinaryObjectScanner.Protection
|
||||
return "SVKP v1.051";
|
||||
|
||||
// Found in the SVKP 1.11 demo.
|
||||
if (exe.EntryPointData.StartsWith(new byte?[]
|
||||
{
|
||||
if (exe.EntryPointData.StartsWith(
|
||||
[
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, 0x06, null, null, null, 0x64, 0xA0, 0x23
|
||||
}))
|
||||
]))
|
||||
return "SVKP v1.11";
|
||||
|
||||
// Found in the SVKP 1.32 demo and Redump entry 84122.
|
||||
if (exe.EntryPointData.StartsWith(new byte?[]
|
||||
{
|
||||
if (exe.EntryPointData.StartsWith(
|
||||
[
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x06, 0x00, 0x00, 0x00, 0xEB, 0x05, 0xB8,
|
||||
null, null, null, null, 0x64, 0xA0, 0x23
|
||||
}))
|
||||
]))
|
||||
return "SVKP v1.3+";
|
||||
}
|
||||
|
||||
|
||||
@@ -355,12 +355,12 @@ namespace BinaryObjectScanner.Protection
|
||||
new(new FilePathMatch("SINTFNT.DLL"), "SecuROM New"),
|
||||
|
||||
// TODO: Find more samples of this for different versions
|
||||
new(new List<PathMatch>
|
||||
{
|
||||
new(
|
||||
[
|
||||
new FilePathMatch("securom_v7_01.bak"),
|
||||
new FilePathMatch("securom_v7_01.dat"),
|
||||
new FilePathMatch("securom_v7_01.tmp"),
|
||||
}, "SecuROM 7.01"),
|
||||
], "SecuROM 7.01"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: true);
|
||||
|
||||
@@ -50,11 +50,11 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
new(new List<PathMatch>
|
||||
{
|
||||
new(
|
||||
[
|
||||
new FilePathMatch("00001.TMP"),
|
||||
new FilePathMatch("00002.TMP")
|
||||
}, "SmartE"),
|
||||
], "SmartE"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: true);
|
||||
|
||||
@@ -73,11 +73,11 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
new(new List<PathMatch>
|
||||
{
|
||||
new(
|
||||
[
|
||||
new FilePathMatch("SOFTLOCKC.dat"),
|
||||
new FilePathMatch("SOFTLOCKI.dat"),
|
||||
}, "SoftLock"),
|
||||
], "SoftLock"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: false);
|
||||
|
||||
@@ -87,7 +87,11 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
var str = strs.Find(s => s.Contains("Solidshield "));
|
||||
if (str != null)
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
return $"SolidShield EXE Wrapper {str["Solidshield ".Length..]}";
|
||||
#else
|
||||
return $"SolidShield EXE Wrapper {str.Substring("Solidshield ".Length)}";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,13 +30,13 @@ namespace BinaryObjectScanner.Protection
|
||||
return null;
|
||||
|
||||
int offset = 0;
|
||||
|
||||
|
||||
// StarForce Keyless check: the key is stored in the Data Preparer identifier.
|
||||
string? dataPreparerIdentiferString = pvd.DataPreparerIdentifier.ReadNullTerminatedAnsiString(ref offset)?.Trim();
|
||||
|
||||
if (dataPreparerIdentiferString != null
|
||||
&& dataPreparerIdentiferString.Length != 0
|
||||
&& Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9-]*$"))
|
||||
|
||||
if (dataPreparerIdentiferString != null
|
||||
&& dataPreparerIdentiferString.Length != 0
|
||||
&& Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9-]*$", RegexOptions.Compiled))
|
||||
{
|
||||
// It is returning the key, as it tells you what set of DPM your disc corresponds to, and it would also
|
||||
// help show why a disc might be an alt of another disc (there are at least a decent amount of StarForce
|
||||
@@ -49,23 +49,23 @@ namespace BinaryObjectScanner.Protection
|
||||
// XXXXX-XXXXX-XXXXX-XXXXX-XXXXX (25 characters, plus 4 dashes seperating 5 groups of 5)
|
||||
// XXXXXXXXXXXXXXXXXXXXXXXXXXXX (28 characters)
|
||||
// XXXX-XXXXXX-XXXXXX-XXXXXX-XXXXXX (28 characters, with 4 dashes)
|
||||
if (Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{25}$")
|
||||
|| Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}$")
|
||||
|| Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{28}$")
|
||||
|| Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{4}-[A-Z0-9]{6}-[A-Z0-9]{6}-[A-Z0-9]{6}-[A-Z0-9]{6}$"))
|
||||
if (Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{25}$", RegexOptions.Compiled)
|
||||
|| Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}$", RegexOptions.Compiled)
|
||||
|| Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{28}$", RegexOptions.Compiled)
|
||||
|| Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{4}-[A-Z0-9]{6}-[A-Z0-9]{6}-[A-Z0-9]{6}-[A-Z0-9]{6}$", RegexOptions.Compiled))
|
||||
{
|
||||
return $"StarForce Keyless - {dataPreparerIdentiferString}";
|
||||
}
|
||||
|
||||
// Redump ID 60270 is a unique case, there could possibly be more.
|
||||
if (UnusualStarforceKeylessKeys.ContainsKey(dataPreparerIdentiferString))
|
||||
return $"StarForce Keyless - {dataPreparerIdentiferString}";
|
||||
return $"StarForce Keyless - {dataPreparerIdentiferString}";
|
||||
}
|
||||
|
||||
|
||||
// Starforce general check: the reserved 653 bytes start with a 32-bit LE number that's slightly less
|
||||
// than the length of the volume size space. The difference varies, it's usually around 10. Check 500 to be
|
||||
// safe. The rest of the data is all 0x00. Not many starforce discs have this, but some do, and it's
|
||||
// currently the only known non-keyless check. Redump ID 60266, 72531, 87181, 91734, 106732, 105356, 74578,
|
||||
// currently the only known non-keyless check. Redump ID 60266, 72531, 87181, 91734, 106732, 105356, 74578,
|
||||
// 78200 are some examples.
|
||||
if (FileType.ISO9660.NoteworthyApplicationUse(pvd))
|
||||
return null;
|
||||
@@ -83,7 +83,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// through here.
|
||||
if (initialValue > pvd.VolumeSpaceSize || initialValue + 500 < pvd.VolumeSpaceSize || !Array.TrueForAll(zeroBytes, b => b == 0x00))
|
||||
return null;
|
||||
|
||||
|
||||
return "StarForce";
|
||||
}
|
||||
|
||||
@@ -201,31 +201,31 @@ namespace BinaryObjectScanner.Protection
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// This file combination is found in Redump entry 21136.
|
||||
new(new List<PathMatch>
|
||||
{
|
||||
new(
|
||||
[
|
||||
new FilePathMatch("protect.x86"),
|
||||
new FilePathMatch("protect.x64"),
|
||||
new FilePathMatch("protect.dll"),
|
||||
new FilePathMatch("protect.exe"),
|
||||
new FilePathMatch("protect.msg"),
|
||||
}, "StarForce"),
|
||||
], "StarForce"),
|
||||
|
||||
// This file combination is found in multiple games, such as Redump entries 81756, 91336, and 93657.
|
||||
new(new List<PathMatch>
|
||||
{
|
||||
new(
|
||||
[
|
||||
new FilePathMatch("protect.x86"),
|
||||
new FilePathMatch("protect.x64"),
|
||||
new FilePathMatch("protect.dll"),
|
||||
new FilePathMatch("protect.exe"),
|
||||
}, "StarForce"),
|
||||
], "StarForce"),
|
||||
|
||||
// This file combination is found in Redump entry 96137.
|
||||
new(new List<PathMatch>
|
||||
{
|
||||
new(
|
||||
[
|
||||
new FilePathMatch("protect.x86"),
|
||||
new FilePathMatch("protect.dll"),
|
||||
new FilePathMatch("protect.exe"),
|
||||
}, "StarForce"),
|
||||
], "StarForce"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: false);
|
||||
|
||||
@@ -60,8 +60,8 @@ namespace BinaryObjectScanner.Protection
|
||||
], "Steam (.sis/.csm/.csd)"),
|
||||
|
||||
// These checks are grouped together due to the names being generic on their own (Redump entry 91450).
|
||||
new(new List<PathMatch>
|
||||
{
|
||||
new(
|
||||
[
|
||||
// TODO: Identify based on "Steam(TM)" being present in "Description" but not in "File Description".
|
||||
// Overmatches on some files, such as IA item "ASMEsMechanicalEngineeringToolkit1997December".
|
||||
// new FilePathMatch("steam.exe"),
|
||||
@@ -70,7 +70,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// TODO: Identify file using MSI property parsing.
|
||||
new FilePathMatch("steam.msi"),
|
||||
}, "Steam"),
|
||||
], "Steam"),
|
||||
|
||||
new(new FilePathMatch("steam_api.dll"), "Steam"),
|
||||
new(new FilePathMatch("steam_api64.dll"), "Steam"),
|
||||
|
||||
@@ -273,7 +273,7 @@ namespace BinaryObjectScanner.Protection
|
||||
return null;
|
||||
|
||||
// TODO: Determine difference between API and BASIC
|
||||
byte typeByte = fileContent[positions[0] + 6];
|
||||
_ = fileContent[positions[0] + 6];
|
||||
byte versionByte = fileContent[positions[0] + 7];
|
||||
|
||||
return versionByte switch
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#if NET20 || NET35 || NET40
|
||||
public class ProtectionProgress : System.EventArgs
|
||||
#else
|
||||
public struct ProtectionProgress
|
||||
public readonly struct ProtectionProgress
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -153,7 +153,11 @@ namespace BinaryObjectScanner
|
||||
// Get the reportable file name
|
||||
string reportableFileName = file;
|
||||
if (reportableFileName.StartsWith(tempFilePath))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
reportableFileName = reportableFileName[tempFilePathWithGuid.Length..];
|
||||
#else
|
||||
reportableFileName = reportableFileName.Substring(tempFilePathWithGuid.Length);
|
||||
#endif
|
||||
|
||||
// Checkpoint
|
||||
_fileProgress?.Report(new ProtectionProgress(reportableFileName, depth, i / (float)files.Count, "Checking file" + (file != reportableFileName ? " from archive" : string.Empty)));
|
||||
@@ -173,7 +177,11 @@ namespace BinaryObjectScanner
|
||||
|
||||
// Checkpoint
|
||||
protections.TryGetValue(file, out var fullProtectionList);
|
||||
#if NET20 || NET35
|
||||
var fullProtection = fullProtectionList != null && fullProtectionList.Count > 0
|
||||
#else
|
||||
var fullProtection = fullProtectionList != null && !fullProtectionList.IsEmpty
|
||||
#endif
|
||||
? string.Join(", ", [.. fullProtectionList])
|
||||
: null;
|
||||
_fileProgress?.Report(new ProtectionProgress(reportableFileName, depth, (i + 1) / (float)files.Count, fullProtection ?? string.Empty));
|
||||
@@ -186,7 +194,11 @@ namespace BinaryObjectScanner
|
||||
// Get the reportable file name
|
||||
string reportableFileName = path;
|
||||
if (reportableFileName.StartsWith(tempFilePath))
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
reportableFileName = reportableFileName[tempFilePathWithGuid.Length..];
|
||||
#else
|
||||
reportableFileName = reportableFileName.Substring(tempFilePathWithGuid.Length);
|
||||
#endif
|
||||
|
||||
// Checkpoint
|
||||
_fileProgress?.Report(new ProtectionProgress(reportableFileName, depth, 0, "Checking file" + (path != reportableFileName ? " from archive" : string.Empty)));
|
||||
@@ -206,7 +218,11 @@ namespace BinaryObjectScanner
|
||||
|
||||
// Checkpoint
|
||||
protections.TryGetValue(path, out var fullProtectionList);
|
||||
#if NET20 || NET35
|
||||
var fullProtection = fullProtectionList != null && fullProtectionList.Count > 0
|
||||
#else
|
||||
var fullProtection = fullProtectionList != null && !fullProtectionList.IsEmpty
|
||||
#endif
|
||||
? string.Join(", ", [.. fullProtectionList])
|
||||
: null;
|
||||
_fileProgress?.Report(new ProtectionProgress(reportableFileName, depth, 1, fullProtection ?? string.Empty));
|
||||
@@ -473,27 +489,27 @@ namespace BinaryObjectScanner
|
||||
private static IDetectable? CreateDetectable(WrapperType fileType, IWrapper? wrapper)
|
||||
{
|
||||
// Use the wrapper before the type
|
||||
switch (wrapper)
|
||||
return wrapper switch
|
||||
{
|
||||
case AACSMediaKeyBlock obj: return new FileType.AACSMediaKeyBlock(obj);
|
||||
case BDPlusSVM obj: return new FileType.BDPlusSVM(obj);
|
||||
case ISO9660 obj: return new FileType.ISO9660(obj);
|
||||
case LDSCRYPT obj: return new FileType.LDSCRYPT(obj);
|
||||
case LinearExecutable obj: return new FileType.LinearExecutable(obj);
|
||||
case MSDOS obj: return new FileType.MSDOS(obj);
|
||||
case NewExecutable obj: return new FileType.NewExecutable(obj);
|
||||
case PlayJAudioFile obj: return new FileType.PLJ(obj);
|
||||
case PortableExecutable obj: return new FileType.PortableExecutable(obj);
|
||||
case RealArcadeInstaller obj: return new FileType.RealArcadeInstaller(obj);
|
||||
case RealArcadeMezzanine obj: return new FileType.RealArcadeMezzanine(obj);
|
||||
case SFFS obj: return new FileType.SFFS(obj);
|
||||
}
|
||||
AACSMediaKeyBlock obj => new FileType.AACSMediaKeyBlock(obj),
|
||||
BDPlusSVM obj => new FileType.BDPlusSVM(obj),
|
||||
ISO9660 obj => new FileType.ISO9660(obj),
|
||||
LDSCRYPT obj => new FileType.LDSCRYPT(obj),
|
||||
LinearExecutable obj => new FileType.LinearExecutable(obj),
|
||||
MSDOS obj => new FileType.MSDOS(obj),
|
||||
NewExecutable obj => new FileType.NewExecutable(obj),
|
||||
PlayJAudioFile obj => new FileType.PLJ(obj),
|
||||
PortableExecutable obj => new FileType.PortableExecutable(obj),
|
||||
RealArcadeInstaller obj => new FileType.RealArcadeInstaller(obj),
|
||||
RealArcadeMezzanine obj => new FileType.RealArcadeMezzanine(obj),
|
||||
SFFS obj => new FileType.SFFS(obj),
|
||||
|
||||
// Fall back on the file type for types not implemented in Serialization
|
||||
return fileType switch
|
||||
{
|
||||
WrapperType.Textfile => new FileType.Textfile(),
|
||||
_ => null,
|
||||
// Fall back on the file type for types not implemented in Serialization
|
||||
_ => fileType switch
|
||||
{
|
||||
WrapperType.Textfile => new FileType.Textfile(),
|
||||
_ => null,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -360,16 +360,15 @@ namespace ProtectionScan.Features
|
||||
var part = pathParts[i];
|
||||
|
||||
// Inserts new subdictionaries if one doesn't already exist
|
||||
if (!current.ContainsKey(part))
|
||||
if (!current.TryGetValue(part, out object? innerObject))
|
||||
{
|
||||
var innerDictionary = new Dictionary<string, object>();
|
||||
current[part] = innerDictionary;
|
||||
innerObject = innerDictionary;
|
||||
current[part] = innerObject;
|
||||
current = innerDictionary;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle instances where a protection was already assigned to the current node
|
||||
var innerObject = current[part];
|
||||
if (innerObject is string[] existingProtections)
|
||||
{
|
||||
modifyNodeList.Add((current, part, existingProtections));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<OutputType>Exe</OutputType>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
|
||||
@@ -20,11 +20,11 @@
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`))">
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`)) OR $(TargetFramework.StartsWith(`net10`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(RuntimeIdentifier.StartsWith(`osx-arm`))">
|
||||
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -32,8 +32,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.CommandLine" Version="[1.3.2]" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="[2.1.0]" />
|
||||
<PackageReference Include="SabreTools.CommandLine" Version="[1.4.0]" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="[2.2.0]" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This batch file assumes the following:
|
||||
# - .NET 9.0 (or newer) SDK is installed and in PATH
|
||||
# - .NET 10.0 (or newer) SDK is installed and in PATH
|
||||
# - zip is installed and in PATH
|
||||
# - Git is installed and in PATH
|
||||
#
|
||||
@@ -49,18 +49,18 @@ echo " No archive (-a) $NO_ARCHIVE"
|
||||
echo " "
|
||||
|
||||
# Create the build matrix arrays
|
||||
FRAMEWORKS=("net9.0")
|
||||
FRAMEWORKS=("net10.0")
|
||||
RUNTIMES=("win-x86" "win-x64" "win-arm64" "linux-x64" "linux-arm64" "osx-x64" "osx-arm64")
|
||||
|
||||
# Use expanded lists, if requested
|
||||
if [ $USE_ALL = true ]; then
|
||||
FRAMEWORKS=("net20" "net35" "net40" "net452" "net462" "net472" "net48" "netcoreapp3.1" "net5.0" "net6.0" "net7.0" "net8.0" "net9.0")
|
||||
FRAMEWORKS=("net20" "net35" "net40" "net452" "net462" "net472" "net48" "netcoreapp3.1" "net5.0" "net6.0" "net7.0" "net8.0" "net9.0" "net10.0")
|
||||
fi
|
||||
|
||||
# Create the filter arrays
|
||||
SINGLE_FILE_CAPABLE=("net5.0" "net6.0" "net7.0" "net8.0" "net9.0")
|
||||
VALID_APPLE_FRAMEWORKS=("net6.0" "net7.0" "net8.0" "net9.0")
|
||||
VALID_CROSS_PLATFORM_FRAMEWORKS=("netcoreapp3.1" "net5.0" "net6.0" "net7.0" "net8.0" "net9.0")
|
||||
SINGLE_FILE_CAPABLE=("net5.0" "net6.0" "net7.0" "net8.0" "net9.0" "net10.0")
|
||||
VALID_APPLE_FRAMEWORKS=("net6.0" "net7.0" "net8.0" "net9.0" "net10.0")
|
||||
VALID_CROSS_PLATFORM_FRAMEWORKS=("netcoreapp3.1" "net5.0" "net6.0" "net7.0" "net8.0" "net9.0" "net10.0")
|
||||
VALID_CROSS_PLATFORM_RUNTIMES=("win-arm64" "linux-x64" "linux-arm64" "osx-x64" "osx-arm64")
|
||||
|
||||
# Only build if requested
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# This batch file assumes the following:
|
||||
# - .NET 9.0 (or newer) SDK is installed and in PATH
|
||||
# - .NET 10.0 (or newer) SDK is installed and in PATH
|
||||
# - 7-zip commandline (7z.exe) is installed and in PATH
|
||||
# - Git for Windows is installed and in PATH
|
||||
#
|
||||
@@ -40,18 +40,18 @@ Write-Host " No archive (-NoArchive) $NO_ARCHIVE"
|
||||
Write-Host " "
|
||||
|
||||
# Create the build matrix arrays
|
||||
$FRAMEWORKS = @('net9.0')
|
||||
$FRAMEWORKS = @('net10.0')
|
||||
$RUNTIMES = @('win-x86', 'win-x64', 'win-arm64', 'linux-x64', 'linux-arm64', 'osx-x64', 'osx-arm64')
|
||||
|
||||
# Use expanded lists, if requested
|
||||
if ($USE_ALL.IsPresent) {
|
||||
$FRAMEWORKS = @('net20', 'net35', 'net40', 'net452', 'net462', 'net472', 'net48', 'netcoreapp3.1', 'net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0')
|
||||
$FRAMEWORKS = @('net20', 'net35', 'net40', 'net452', 'net462', 'net472', 'net48', 'netcoreapp3.1', 'net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0', 'net10.0')
|
||||
}
|
||||
|
||||
# Create the filter arrays
|
||||
$SINGLE_FILE_CAPABLE = @('net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0')
|
||||
$VALID_APPLE_FRAMEWORKS = @('net6.0', 'net7.0', 'net8.0', 'net9.0')
|
||||
$VALID_CROSS_PLATFORM_FRAMEWORKS = @('netcoreapp3.1', 'net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0')
|
||||
$SINGLE_FILE_CAPABLE = @('net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0', 'net10.0')
|
||||
$VALID_APPLE_FRAMEWORKS = @('net6.0', 'net7.0', 'net8.0', 'net9.0', 'net10.0')
|
||||
$VALID_CROSS_PLATFORM_FRAMEWORKS = @('netcoreapp3.1', 'net5.0', 'net6.0', 'net7.0', 'net8.0', 'net9.0', 'net10.0')
|
||||
$VALID_CROSS_PLATFORM_RUNTIMES = @('win-arm64', 'linux-x64', 'linux-arm64', 'osx-x64', 'osx-arm64')
|
||||
|
||||
# Only build if requested
|
||||
|
||||
Reference in New Issue
Block a user