mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-07-15 05:15:05 +00:00
Compare commits
61 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
384db5dcf4 | ||
|
|
b96af0a3c2 | ||
|
|
95f152c105 | ||
|
|
ff02fdb5c3 | ||
|
|
53d4757e5c | ||
|
|
0181917850 | ||
|
|
008d53ad8a | ||
|
|
be5169b935 | ||
|
|
245e840063 | ||
|
|
9be63e9e9a | ||
|
|
57797496cf | ||
|
|
8490d3804f | ||
|
|
8df070ad3d | ||
|
|
6cc6f66c95 | ||
|
|
fbee5a1c52 | ||
|
|
4807520169 | ||
|
|
91da3068b6 | ||
|
|
c9316651c5 | ||
|
|
2b3917a1ee | ||
|
|
efef8d494e | ||
|
|
6c1efccb00 | ||
|
|
0d2f81773d | ||
|
|
7058c7a150 | ||
|
|
417c1f8208 | ||
|
|
82fc850b57 | ||
|
|
973b0118b6 | ||
|
|
c2368661cb | ||
|
|
05bddd6005 | ||
|
|
777232301d | ||
|
|
41a705c343 | ||
|
|
805beb3418 | ||
|
|
cc7592e07a | ||
|
|
41ad8adf6e | ||
|
|
201badd434 | ||
|
|
f58003b3fc | ||
|
|
ff8976a67a | ||
|
|
dc968c2d15 | ||
|
|
3726abb209 | ||
|
|
ac8dfb833c | ||
|
|
f0673046dc | ||
|
|
d9fa073c0f | ||
|
|
95a20fb30d | ||
|
|
dd1e49662f | ||
|
|
78947616b1 | ||
|
|
ba56b9aff6 | ||
|
|
3b287c6f7b | ||
|
|
dcdf0bcf40 | ||
|
|
d2eebd0f00 | ||
|
|
a281e8325e | ||
|
|
9f5b292035 | ||
|
|
466689dcbc | ||
|
|
5b0bf2e7e4 | ||
|
|
cc8dfb8478 | ||
|
|
82412fce9a | ||
|
|
1a67decd7b | ||
|
|
f1afb6d60b | ||
|
|
5e812daf01 | ||
|
|
ab508eebe8 | ||
|
|
31792fab48 | ||
|
|
010f792b1a | ||
|
|
a3118cee68 |
167
.editorconfig
Normal file
167
.editorconfig
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# C# files
|
||||||
|
[*.cs]
|
||||||
|
|
||||||
|
# Indentation and spacing
|
||||||
|
charset = utf-8
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
|
tab_width = 4
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
# New line preferences
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
max_line_length = unset
|
||||||
|
|
||||||
|
# using directive preferences
|
||||||
|
csharp_using_directive_placement = outside_namespace
|
||||||
|
dotnet_diagnostic.IDE0005.severity = error
|
||||||
|
|
||||||
|
# Code-block preferences
|
||||||
|
csharp_style_namespace_declarations = block_scoped
|
||||||
|
csharp_style_prefer_method_group_conversion = true
|
||||||
|
csharp_style_prefer_top_level_statements = false
|
||||||
|
|
||||||
|
# Expression-level preferences
|
||||||
|
csharp_prefer_simple_default_expression = true
|
||||||
|
csharp_style_inlined_variable_declaration = true
|
||||||
|
csharp_style_unused_value_assignment_preference = discard_variable
|
||||||
|
csharp_style_unused_value_expression_statement_preference = discard_variable
|
||||||
|
dotnet_diagnostic.IDE0001.severity = warning
|
||||||
|
dotnet_diagnostic.IDE0002.severity = warning
|
||||||
|
dotnet_diagnostic.IDE0004.severity = warning
|
||||||
|
dotnet_diagnostic.IDE0010.severity = error
|
||||||
|
dotnet_diagnostic.IDE0051.severity = warning
|
||||||
|
dotnet_diagnostic.IDE0052.severity = warning
|
||||||
|
dotnet_diagnostic.IDE0072.severity = warning
|
||||||
|
dotnet_diagnostic.IDE0080.severity = warning
|
||||||
|
dotnet_diagnostic.IDE0100.severity = error
|
||||||
|
dotnet_diagnostic.IDE0110.severity = error
|
||||||
|
dotnet_diagnostic.IDE0120.severity = warning
|
||||||
|
dotnet_diagnostic.IDE0121.severity = warning
|
||||||
|
dotnet_diagnostic.IDE0240.severity = error
|
||||||
|
dotnet_diagnostic.IDE0241.severity = error
|
||||||
|
dotnet_style_coalesce_expression = true
|
||||||
|
dotnet_style_namespace_match_folder = false
|
||||||
|
dotnet_style_null_propagation = true
|
||||||
|
dotnet_style_prefer_auto_properties = true
|
||||||
|
dotnet_style_prefer_collection_expression = when_types_loosely_match
|
||||||
|
dotnet_style_prefer_is_null_check_over_reference_equality_method = true
|
||||||
|
dotnet_style_prefer_compound_assignment = true
|
||||||
|
csharp_style_prefer_simple_property_accessors = true
|
||||||
|
dotnet_style_prefer_simplified_interpolation = true
|
||||||
|
dotnet_style_prefer_simplified_boolean_expressions = true
|
||||||
|
csharp_style_prefer_unbound_generic_type_in_nameof = true
|
||||||
|
|
||||||
|
# Field preferences
|
||||||
|
dotnet_diagnostic.IDE0044.severity = warning
|
||||||
|
dotnet_style_readonly_field = true
|
||||||
|
|
||||||
|
# Language keyword vs. framework types preferences
|
||||||
|
dotnet_diagnostic.IDE0049.severity = error
|
||||||
|
dotnet_style_predefined_type_for_locals_parameters_members = true
|
||||||
|
dotnet_style_predefined_type_for_member_access = true
|
||||||
|
|
||||||
|
# Modifier preferences
|
||||||
|
csharp_prefer_static_local_function = true
|
||||||
|
csharp_style_prefer_readonly_struct = true
|
||||||
|
dotnet_diagnostic.IDE0036.severity = warning
|
||||||
|
dotnet_diagnostic.IDE0040.severity = error
|
||||||
|
dotnet_diagnostic.IDE0380.severity = error
|
||||||
|
dotnet_style_require_accessibility_modifiers = always
|
||||||
|
|
||||||
|
# New-line preferences
|
||||||
|
dotnet_diagnostic.IDE2000.severity = warning
|
||||||
|
dotnet_diagnostic.IDE2002.severity = warning
|
||||||
|
dotnet_diagnostic.IDE2003.severity = warning
|
||||||
|
dotnet_diagnostic.IDE2004.severity = warning
|
||||||
|
dotnet_diagnostic.IDE2005.severity = warning
|
||||||
|
dotnet_diagnostic.IDE2006.severity = warning
|
||||||
|
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = false
|
||||||
|
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = false
|
||||||
|
csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = false
|
||||||
|
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false
|
||||||
|
dotnet_style_allow_multiple_blank_lines_experimental = false
|
||||||
|
dotnet_style_allow_statement_immediately_after_block_experimental = false
|
||||||
|
|
||||||
|
# Null-checking preferences
|
||||||
|
csharp_style_conditional_delegate_call = true
|
||||||
|
|
||||||
|
# Parameter preferences
|
||||||
|
dotnet_code_quality_unused_parameters = all
|
||||||
|
dotnet_diagnostic.IDE0280.severity = error
|
||||||
|
|
||||||
|
# Parentheses preferences
|
||||||
|
dotnet_diagnostic.IDE0047.severity = warning
|
||||||
|
dotnet_diagnostic.IDE0048.severity = warning
|
||||||
|
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
|
||||||
|
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
|
||||||
|
dotnet_style_parentheses_in_other_operators = always_for_clarity
|
||||||
|
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
|
||||||
|
|
||||||
|
# Pattern-matching preferences
|
||||||
|
dotnet_diagnostic.IDE0019.severity = warning
|
||||||
|
dotnet_diagnostic.IDE0020.severity = warning
|
||||||
|
dotnet_diagnostic.IDE0038.severity = warning
|
||||||
|
dotnet_diagnostic.IDE0066.severity = none
|
||||||
|
dotnet_diagnostic.IDE0083.severity = warning
|
||||||
|
dotnet_diagnostic.IDE0260.severity = warning
|
||||||
|
csharp_style_pattern_matching_over_as_with_null_check = true
|
||||||
|
csharp_style_pattern_matching_over_is_with_cast_check = true
|
||||||
|
csharp_style_prefer_not_pattern = true
|
||||||
|
csharp_style_prefer_pattern_matching = true
|
||||||
|
|
||||||
|
# this. and Me. preferences
|
||||||
|
dotnet_style_qualification_for_event = false
|
||||||
|
dotnet_style_qualification_for_field = false
|
||||||
|
dotnet_style_qualification_for_method = false
|
||||||
|
dotnet_style_qualification_for_property = false
|
||||||
|
|
||||||
|
# var preferences
|
||||||
|
csharp_style_var_for_built_in_types = false
|
||||||
|
csharp_style_var_when_type_is_apparent = true
|
||||||
|
|
||||||
|
# .NET formatting options
|
||||||
|
dotnet_separate_import_directive_groups = false
|
||||||
|
dotnet_sort_system_directives_first = true
|
||||||
|
|
||||||
|
# C# formatting options
|
||||||
|
csharp_indent_block_contents = true
|
||||||
|
csharp_indent_braces = false
|
||||||
|
csharp_indent_case_contents = true
|
||||||
|
csharp_indent_case_contents_when_block = false
|
||||||
|
csharp_indent_labels = one_less_than_current
|
||||||
|
csharp_indent_switch_labels = true
|
||||||
|
csharp_new_line_before_catch = true
|
||||||
|
csharp_new_line_before_else = true
|
||||||
|
csharp_new_line_before_finally = true
|
||||||
|
csharp_new_line_before_members_in_anonymous_types = true
|
||||||
|
csharp_new_line_before_members_in_object_initializers = true
|
||||||
|
csharp_new_line_before_open_brace = all
|
||||||
|
csharp_new_line_between_query_expression_clauses = true
|
||||||
|
csharp_preserve_single_line_blocks = true
|
||||||
|
csharp_preserve_single_line_statements = true
|
||||||
|
csharp_space_after_cast = false
|
||||||
|
csharp_space_after_colon_in_inheritance_clause = true
|
||||||
|
csharp_space_after_comma = true
|
||||||
|
csharp_space_after_dot = false
|
||||||
|
csharp_space_after_keywords_in_control_flow_statements = true
|
||||||
|
csharp_space_after_semicolon_in_for_statement = true
|
||||||
|
csharp_space_around_binary_operators = before_and_after
|
||||||
|
csharp_space_around_declaration_statements = false
|
||||||
|
csharp_space_before_colon_in_inheritance_clause = true
|
||||||
|
csharp_space_before_comma = false
|
||||||
|
csharp_space_before_dot = false
|
||||||
|
csharp_space_before_open_square_brackets = false
|
||||||
|
csharp_space_before_semicolon_in_for_statement = false
|
||||||
|
csharp_space_between_empty_square_brackets = false
|
||||||
|
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||||
|
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_parentheses = false
|
||||||
|
csharp_space_between_square_brackets = false
|
||||||
68
.github/workflows/build_and_test.yml
vendored
68
.github/workflows/build_and_test.yml
vendored
@@ -1,40 +1,48 @@
|
|||||||
name: Build and Test
|
name: Build and Test
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ "master" ]
|
branches: ["master"]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@v5
|
||||||
with:
|
with:
|
||||||
dotnet-version: |
|
dotnet-version: |
|
||||||
6.0.x
|
8.0.x
|
||||||
8.0.x
|
9.0.x
|
||||||
9.0.x
|
10.0.x
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: dotnet test
|
run: dotnet test
|
||||||
|
|
||||||
- name: Run publish script
|
- name: Run publish script
|
||||||
run: ./publish-nix.sh -d
|
run: ./publish-nix.sh -d
|
||||||
|
|
||||||
- name: Upload to rolling
|
- name: Update rolling tag
|
||||||
uses: ncipollo/release-action@v1.14.0
|
run: |
|
||||||
with:
|
git config user.name "github-actions[bot]"
|
||||||
allowUpdates: True
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
artifacts: "*.nupkg,*.snupkg,*.zip"
|
git tag -f rolling
|
||||||
body: 'Last built commit: ${{ github.sha }}'
|
git push origin :refs/tags/rolling || true
|
||||||
name: 'Rolling Release'
|
git push origin rolling --force
|
||||||
prerelease: True
|
|
||||||
replacesArtifacts: True
|
- name: Upload to rolling
|
||||||
tag: "rolling"
|
uses: ncipollo/release-action@v1.20.0
|
||||||
updateOnlyUnreleased: True
|
with:
|
||||||
|
allowUpdates: True
|
||||||
|
artifacts: "*.nupkg,*.snupkg,*.zip"
|
||||||
|
body: "Last built commit: ${{ github.sha }}"
|
||||||
|
name: "Rolling Release"
|
||||||
|
prerelease: True
|
||||||
|
replacesArtifacts: True
|
||||||
|
tag: "rolling"
|
||||||
|
updateOnlyUnreleased: True
|
||||||
|
|||||||
30
.github/workflows/check_pr.yml
vendored
30
.github/workflows/check_pr.yml
vendored
@@ -3,21 +3,21 @@ name: Build PR
|
|||||||
on: [pull_request]
|
on: [pull_request]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
uses: actions/setup-dotnet@v4
|
uses: actions/setup-dotnet@v5
|
||||||
with:
|
with:
|
||||||
dotnet-version: |
|
dotnet-version: |
|
||||||
6.0.x
|
8.0.x
|
||||||
8.0.x
|
9.0.x
|
||||||
9.0.x
|
10.0.x
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: dotnet build
|
run: dotnet build
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: dotnet test
|
run: dotnet test
|
||||||
|
|||||||
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@@ -10,7 +10,7 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"preLaunchTask": "build",
|
"preLaunchTask": "build",
|
||||||
// If you have changed target frameworks, make sure to update the program path.
|
// 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": [],
|
"args": [],
|
||||||
"cwd": "${workspaceFolder}/ProtectionScan",
|
"cwd": "${workspaceFolder}/ProtectionScan",
|
||||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
|
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
@@ -12,14 +12,14 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="coverlet.collector" Version="6.0.4">
|
<PackageReference Include="coverlet.collector" Version="8.0.0">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
|
||||||
<PackageReference Include="SabreTools.Serialization" Version="[2.0.1]" />
|
<PackageReference Include="SabreTools.Serialization" Version="[2.3.0]" />
|
||||||
<PackageReference Include="xunit" Version="2.9.3" />
|
<PackageReference Include="xunit" Version="2.9.3" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4">
|
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace BinaryObjectScanner.Test.Data
|
|||||||
public void PortableExecutableCheckClasses_Populated()
|
public void PortableExecutableCheckClasses_Populated()
|
||||||
{
|
{
|
||||||
var actual = StaticChecks.PortableExecutableCheckClasses;
|
var actual = StaticChecks.PortableExecutableCheckClasses;
|
||||||
Assert.Equal(105, actual.Length);
|
Assert.Equal(106, actual.Length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,4 +31,3 @@ namespace BinaryObjectScanner.Test.FileType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,4 +31,3 @@ namespace BinaryObjectScanner.Test.FileType
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
34
BinaryObjectScanner.Test/FileType/DiskImageTests.cs
Normal file
34
BinaryObjectScanner.Test/FileType/DiskImageTests.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using System.IO;
|
||||||
|
using BinaryObjectScanner.FileType;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace BinaryObjectScanner.Test.FileType
|
||||||
|
{
|
||||||
|
public class DiskImageTests
|
||||||
|
{
|
||||||
|
private static readonly SabreTools.Serialization.Wrappers.ISO9660 wrapper
|
||||||
|
= new(new SabreTools.Data.Models.ISO9660.Volume(), new MemoryStream(new byte[1024]));
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DetectFile_EmptyString_Null()
|
||||||
|
{
|
||||||
|
string file = string.Empty;
|
||||||
|
var detectable = new ISO9660(wrapper);
|
||||||
|
|
||||||
|
string? actual = detectable.Detect(file, includeDebug: false);
|
||||||
|
Assert.Null(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DetectStream_EmptyStream_Empty()
|
||||||
|
{
|
||||||
|
Stream? stream = new MemoryStream();
|
||||||
|
string file = string.Empty;
|
||||||
|
var detectable = new ISO9660(wrapper);
|
||||||
|
|
||||||
|
string? actual = detectable.Detect(stream, file, includeDebug: false);
|
||||||
|
Assert.NotNull(actual);
|
||||||
|
Assert.Empty(actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
BinaryObjectScanner.Test/FileType/GCFTests.cs
Normal file
33
BinaryObjectScanner.Test/FileType/GCFTests.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using System.IO;
|
||||||
|
using BinaryObjectScanner.FileType;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace BinaryObjectScanner.Test.FileType
|
||||||
|
{
|
||||||
|
public class GCFTests
|
||||||
|
{
|
||||||
|
private static readonly SabreTools.Serialization.Wrappers.GCF wrapper
|
||||||
|
= new(new SabreTools.Data.Models.GCF.File(), new MemoryStream(new byte[1024]));
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DetectFile_EmptyString_Null()
|
||||||
|
{
|
||||||
|
string file = string.Empty;
|
||||||
|
var detectable = new GCF(wrapper);
|
||||||
|
|
||||||
|
string? actual = detectable.Detect(file, includeDebug: false);
|
||||||
|
Assert.Null(actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void DetectStream_EmptyStream_DefaultValue()
|
||||||
|
{
|
||||||
|
Stream? stream = new MemoryStream();
|
||||||
|
string file = string.Empty;
|
||||||
|
var detectable = new GCF(wrapper);
|
||||||
|
|
||||||
|
string? actual = detectable.Detect(stream, file, includeDebug: false);
|
||||||
|
Assert.Equal(" - 0 (v0)", actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,5 +18,18 @@ namespace BinaryObjectScanner.Test.Protection
|
|||||||
string? actual = checker.CheckExecutable(file, exe, includeDebug: false);
|
string? actual = checker.CheckExecutable(file, exe, includeDebug: false);
|
||||||
Assert.Null(actual);
|
Assert.Null(actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CheckDiskImageTest()
|
||||||
|
{
|
||||||
|
string file = "filename";
|
||||||
|
SabreTools.Data.Models.ISO9660.Volume model = new();
|
||||||
|
Stream source = new MemoryStream(new byte[1024]);
|
||||||
|
SabreTools.Serialization.Wrappers.ISO9660 iso = new(model, source);
|
||||||
|
|
||||||
|
var checker = new AlphaROM();
|
||||||
|
string? actual = checker.CheckDiskImage(file, iso, includeDebug: false);
|
||||||
|
Assert.Null(actual);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
22
BinaryObjectScanner.Test/Protection/CEGTests.cs
Normal file
22
BinaryObjectScanner.Test/Protection/CEGTests.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using System.IO;
|
||||||
|
using BinaryObjectScanner.Protection;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace BinaryObjectScanner.Test.Protection
|
||||||
|
{
|
||||||
|
public class CEGTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void CheckPortableExecutableTest()
|
||||||
|
{
|
||||||
|
string file = "filename";
|
||||||
|
SabreTools.Data.Models.PortableExecutable.Executable model = new();
|
||||||
|
Stream source = new MemoryStream(new byte[1024]);
|
||||||
|
SabreTools.Serialization.Wrappers.PortableExecutable exe = new(model, source);
|
||||||
|
|
||||||
|
var checker = new CEG();
|
||||||
|
string? actual = checker.CheckExecutable(file, exe, includeDebug: false);
|
||||||
|
Assert.Null(actual);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,5 +18,18 @@ namespace BinaryObjectScanner.Test.Protection
|
|||||||
string? actual = checker.CheckExecutable(file, exe, includeDebug: false);
|
string? actual = checker.CheckExecutable(file, exe, includeDebug: false);
|
||||||
Assert.Null(actual);
|
Assert.Null(actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CheckDiskImageTest()
|
||||||
|
{
|
||||||
|
string file = "filename";
|
||||||
|
SabreTools.Data.Models.ISO9660.Volume model = new();
|
||||||
|
Stream source = new MemoryStream(new byte[1024]);
|
||||||
|
SabreTools.Serialization.Wrappers.ISO9660 iso = new(model, source);
|
||||||
|
|
||||||
|
var checker = new CopyLok();
|
||||||
|
string? actual = checker.CheckDiskImage(file, iso, includeDebug: false);
|
||||||
|
Assert.Null(actual);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,5 +40,18 @@ namespace BinaryObjectScanner.Test.Protection
|
|||||||
string? actual = checker.CheckFilePath(path);
|
string? actual = checker.CheckFilePath(path);
|
||||||
Assert.Null(actual);
|
Assert.Null(actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CheckDiskImageTest()
|
||||||
|
{
|
||||||
|
string file = "filename";
|
||||||
|
SabreTools.Data.Models.ISO9660.Volume model = new();
|
||||||
|
Stream source = new MemoryStream(new byte[1024]);
|
||||||
|
SabreTools.Serialization.Wrappers.ISO9660 iso = new(model, source);
|
||||||
|
|
||||||
|
var checker = new LaserLok();
|
||||||
|
string? actual = checker.CheckDiskImage(file, iso, includeDebug: false);
|
||||||
|
Assert.Null(actual);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,5 +53,18 @@ namespace BinaryObjectScanner.Test.Protection
|
|||||||
string? actual = checker.CheckFilePath(path);
|
string? actual = checker.CheckFilePath(path);
|
||||||
Assert.Null(actual);
|
Assert.Null(actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CheckDiskImageTest()
|
||||||
|
{
|
||||||
|
string file = "filename";
|
||||||
|
SabreTools.Data.Models.ISO9660.Volume model = new();
|
||||||
|
Stream source = new MemoryStream(new byte[1024]);
|
||||||
|
SabreTools.Serialization.Wrappers.ISO9660 iso = new(model, source);
|
||||||
|
|
||||||
|
var checker = new Macrovision();
|
||||||
|
string? actual = checker.CheckDiskImage(file, iso, includeDebug: false);
|
||||||
|
Assert.Null(actual);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,5 +40,18 @@ namespace BinaryObjectScanner.Test.Protection
|
|||||||
string? actual = checker.CheckFilePath(path);
|
string? actual = checker.CheckFilePath(path);
|
||||||
Assert.Null(actual);
|
Assert.Null(actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CheckDiskImageTest()
|
||||||
|
{
|
||||||
|
string file = "filename";
|
||||||
|
SabreTools.Data.Models.ISO9660.Volume model = new();
|
||||||
|
Stream source = new MemoryStream(new byte[1024]);
|
||||||
|
SabreTools.Serialization.Wrappers.ISO9660 iso = new(model, source);
|
||||||
|
|
||||||
|
var checker = new ProtectDISC();
|
||||||
|
string? actual = checker.CheckDiskImage(file, iso, includeDebug: false);
|
||||||
|
Assert.Null(actual);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,5 +40,18 @@ namespace BinaryObjectScanner.Test.Protection
|
|||||||
string? actual = checker.CheckFilePath(path);
|
string? actual = checker.CheckFilePath(path);
|
||||||
Assert.Null(actual);
|
Assert.Null(actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CheckDiskImageTest()
|
||||||
|
{
|
||||||
|
string file = "filename";
|
||||||
|
SabreTools.Data.Models.ISO9660.Volume model = new();
|
||||||
|
Stream source = new MemoryStream(new byte[1024]);
|
||||||
|
SabreTools.Serialization.Wrappers.ISO9660 iso = new(model, source);
|
||||||
|
|
||||||
|
var checker = new SecuROM();
|
||||||
|
string? actual = checker.CheckDiskImage(file, iso, includeDebug: false);
|
||||||
|
Assert.Null(actual);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,5 +40,18 @@ namespace BinaryObjectScanner.Test.Protection
|
|||||||
string? actual = checker.CheckFilePath(path);
|
string? actual = checker.CheckFilePath(path);
|
||||||
Assert.Null(actual);
|
Assert.Null(actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CheckDiskImageTest()
|
||||||
|
{
|
||||||
|
string file = "filename";
|
||||||
|
SabreTools.Data.Models.ISO9660.Volume model = new();
|
||||||
|
Stream source = new MemoryStream(new byte[1024]);
|
||||||
|
SabreTools.Serialization.Wrappers.ISO9660 iso = new(model, source);
|
||||||
|
|
||||||
|
var checker = new StarForce();
|
||||||
|
string? actual = checker.CheckDiskImage(file, iso, includeDebug: false);
|
||||||
|
Assert.Null(actual);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,5 +40,18 @@ namespace BinaryObjectScanner.Test.Protection
|
|||||||
string? actual = checker.CheckFilePath(path);
|
string? actual = checker.CheckFilePath(path);
|
||||||
Assert.Null(actual);
|
Assert.Null(actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CheckDiskImageTest()
|
||||||
|
{
|
||||||
|
string file = "filename";
|
||||||
|
SabreTools.Data.Models.ISO9660.Volume model = new();
|
||||||
|
Stream source = new MemoryStream(new byte[1024]);
|
||||||
|
SabreTools.Serialization.Wrappers.ISO9660 iso = new(model, source);
|
||||||
|
|
||||||
|
var checker = new TAGES();
|
||||||
|
string? actual = checker.CheckDiskImage(file, iso, includeDebug: false);
|
||||||
|
Assert.Null(actual);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- Assembly Properties -->
|
<!-- 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>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||||
@@ -13,7 +13,8 @@
|
|||||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
<Version>3.4.4</Version>
|
<Version>3.6.0</Version>
|
||||||
|
<WarningsNotAsErrors>NU5104</WarningsNotAsErrors>
|
||||||
|
|
||||||
<!-- Package Properties -->
|
<!-- Package Properties -->
|
||||||
<Authors>Matt Nadareski</Authors>
|
<Authors>Matt Nadareski</Authors>
|
||||||
@@ -33,11 +34,11 @@
|
|||||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`))">
|
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`))">
|
||||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
|
||||||
</PropertyGroup>
|
</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>
|
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="$(RuntimeIdentifier.StartsWith(`osx-arm`))">
|
<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>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -45,12 +46,12 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="GrindCore.SharpCompress" Version="0.46.2" 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="MinThreadingBridge" Version="0.11.4" Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net40`))" />
|
||||||
<PackageReference Include="SabreTools.Hashing" Version="[1.5.0]" />
|
<PackageReference Include="SabreTools.Hashing" Version="[1.6.1]" />
|
||||||
<PackageReference Include="SabreTools.IO" Version="[1.7.5]" />
|
<PackageReference Include="SabreTools.IO" Version="[1.9.1]" />
|
||||||
<PackageReference Include="SabreTools.Serialization" Version="[2.0.1]" />
|
<PackageReference Include="SabreTools.Serialization" Version="[2.3.0]" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.40.0" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
<PackageReference Include="System.Text.Encoding.CodePages" Version="10.0.5" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="9.0.9" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -13,7 +13,7 @@ namespace BinaryObjectScanner.Data
|
|||||||
/// <remarks>Handles the proper Add implementation</remarks>
|
/// <remarks>Handles the proper Add implementation</remarks>
|
||||||
public void Append(T key, string? value)
|
public void Append(T key, string? value)
|
||||||
{
|
{
|
||||||
if (value == null || value.Trim().Length == 0)
|
if (value is null || value.Trim().Length == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if NET20 || NET35
|
#if NET20 || NET35
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace BinaryObjectScanner.Data
|
|||||||
public void Append(string key, string? value)
|
public void Append(string key, string? value)
|
||||||
{
|
{
|
||||||
// If the value is empty, don't add it
|
// If the value is empty, don't add it
|
||||||
if (value == null || value.Trim().Length == 0)
|
if (value is null || value.Trim().Length == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
EnsureKey(key);
|
EnsureKey(key);
|
||||||
@@ -47,7 +47,7 @@ namespace BinaryObjectScanner.Data
|
|||||||
EnsureKey(key);
|
EnsureKey(key);
|
||||||
foreach (string value in values)
|
foreach (string value in values)
|
||||||
{
|
{
|
||||||
if (value == null || value.Trim().Length == 0)
|
if (value is null || value.Trim().Length == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
foreach (string subValue in ProcessProtectionString(value))
|
foreach (string subValue in ProcessProtectionString(value))
|
||||||
@@ -79,7 +79,7 @@ namespace BinaryObjectScanner.Data
|
|||||||
public void Append(ProtectionDictionary? addition)
|
public void Append(ProtectionDictionary? addition)
|
||||||
{
|
{
|
||||||
// If the dictionary is missing, just return
|
// If the dictionary is missing, just return
|
||||||
if (addition == null)
|
if (addition is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Loop through each of the addition keys and add accordingly
|
// Loop through each of the addition keys and add accordingly
|
||||||
@@ -105,10 +105,11 @@ namespace BinaryObjectScanner.Data
|
|||||||
string key = keys[i];
|
string key = keys[i];
|
||||||
|
|
||||||
// If the key is empty, remove it
|
// If the key is empty, remove it
|
||||||
if (this[key] == null || this[key].Count == 0)
|
|
||||||
#if NET20 || NET35
|
#if NET20 || NET35
|
||||||
|
if (this[key] is null || this[key].Count == 0)
|
||||||
Remove(key);
|
Remove(key);
|
||||||
#else
|
#else
|
||||||
|
if (this[key] is null || this[key].IsEmpty)
|
||||||
TryRemove(key, out _);
|
TryRemove(key, out _);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -167,7 +168,11 @@ namespace BinaryObjectScanner.Data
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Otherwise, get the new key name and transfer over
|
// 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);
|
string newKey = currentKey.Substring(pathToStrip!.Length);
|
||||||
|
#endif
|
||||||
this[newKey] = this[currentKey];
|
this[newKey] = this[currentKey];
|
||||||
#if NET20 || NET35
|
#if NET20 || NET35
|
||||||
Remove(currentKey);
|
Remove(currentKey);
|
||||||
@@ -184,13 +189,13 @@ namespace BinaryObjectScanner.Data
|
|||||||
/// <param name="values">Queue to get data from</param>
|
/// <param name="values">Queue to get data from</param>
|
||||||
private void AddRangeToKey(string key, IEnumerable<string> values)
|
private void AddRangeToKey(string key, IEnumerable<string> values)
|
||||||
{
|
{
|
||||||
if (values == null)
|
if (values is null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
EnsureKey(key);
|
EnsureKey(key);
|
||||||
foreach (string value in values)
|
foreach (string value in values)
|
||||||
{
|
{
|
||||||
if (value == null || value.Trim().Length == 0)
|
if (value is null || value.Trim().Length == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
foreach (string subValue in ProcessProtectionString(value))
|
foreach (string subValue in ProcessProtectionString(value))
|
||||||
@@ -243,7 +248,11 @@ namespace BinaryObjectScanner.Data
|
|||||||
var protections = new List<string>();
|
var protections = new List<string>();
|
||||||
|
|
||||||
// If we have an indicator of multiple protections
|
// If we have an indicator of multiple protections
|
||||||
|
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||||
|
if (protection!.Contains(';'))
|
||||||
|
#else
|
||||||
if (protection!.Contains(";"))
|
if (protection!.Contains(";"))
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
var splitProtections = protection.Split(';');
|
var splitProtections = protection.Split(';');
|
||||||
protections.AddRange(splitProtections);
|
protections.AddRange(splitProtections);
|
||||||
|
|||||||
@@ -17,8 +17,20 @@ namespace BinaryObjectScanner.Data
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
contentCheckClasses ??= InitCheckClasses<IContentCheck>();
|
field ??= InitCheckClasses<IContentCheck>();
|
||||||
return contentCheckClasses;
|
return field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cache for all IDiskImageCheck<ISO9660> types
|
||||||
|
/// </summary>
|
||||||
|
public static IDiskImageCheck<ISO9660>[] ISO9660CheckClasses
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
field ??= InitCheckClasses<IDiskImageCheck<ISO9660>>();
|
||||||
|
return field;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,8 +41,8 @@ namespace BinaryObjectScanner.Data
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
linearExecutableCheckClasses ??= InitCheckClasses<IExecutableCheck<LinearExecutable>>();
|
field ??= InitCheckClasses<IExecutableCheck<LinearExecutable>>();
|
||||||
return linearExecutableCheckClasses;
|
return field;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,8 +53,8 @@ namespace BinaryObjectScanner.Data
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
msdosExecutableCheckClasses ??= InitCheckClasses<IExecutableCheck<MSDOS>>();
|
field ??= InitCheckClasses<IExecutableCheck<MSDOS>>();
|
||||||
return msdosExecutableCheckClasses;
|
return field;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,8 +65,8 @@ namespace BinaryObjectScanner.Data
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
newExecutableCheckClasses ??= InitCheckClasses<IExecutableCheck<NewExecutable>>();
|
field ??= InitCheckClasses<IExecutableCheck<NewExecutable>>();
|
||||||
return newExecutableCheckClasses;
|
return field;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,8 +77,8 @@ namespace BinaryObjectScanner.Data
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
pathCheckClasses ??= InitCheckClasses<IPathCheck>();
|
field ??= InitCheckClasses<IPathCheck>();
|
||||||
return pathCheckClasses;
|
return field;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,47 +89,15 @@ namespace BinaryObjectScanner.Data
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
portableExecutableCheckClasses ??= InitCheckClasses<IExecutableCheck<PortableExecutable>>();
|
field ??= InitCheckClasses<IExecutableCheck<PortableExecutable>>();
|
||||||
return portableExecutableCheckClasses;
|
return field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Internal Instances
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cache for all IContentCheck types
|
|
||||||
/// </summary>
|
|
||||||
private static IContentCheck[]? contentCheckClasses;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cache for all IExecutableCheck<LinearExecutable> types
|
|
||||||
/// </summary>
|
|
||||||
private static IExecutableCheck<LinearExecutable>[]? linearExecutableCheckClasses;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cache for all IExecutableCheck<MSDOS> types
|
|
||||||
/// </summary>
|
|
||||||
private static IExecutableCheck<MSDOS>[]? msdosExecutableCheckClasses;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cache for all IExecutableCheck<NewExecutable> types
|
|
||||||
/// </summary>
|
|
||||||
private static IExecutableCheck<NewExecutable>[]? newExecutableCheckClasses;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cache for all IPathCheck types
|
|
||||||
/// </summary>
|
|
||||||
private static IPathCheck[]? pathCheckClasses;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cache for all IExecutableCheck<PortableExecutable> types
|
|
||||||
/// </summary>
|
|
||||||
private static IExecutableCheck<PortableExecutable>[]? portableExecutableCheckClasses;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Helpers
|
#region Helpers
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -133,7 +113,7 @@ namespace BinaryObjectScanner.Data
|
|||||||
{
|
{
|
||||||
// Get information from the type param
|
// Get information from the type param
|
||||||
string? interfaceName = typeof(T).FullName;
|
string? interfaceName = typeof(T).FullName;
|
||||||
if (interfaceName == null)
|
if (interfaceName is null)
|
||||||
return [];
|
return [];
|
||||||
|
|
||||||
// If not all types can be loaded, use the ones that could be
|
// If not all types can be loaded, use the ones that could be
|
||||||
@@ -156,7 +136,7 @@ namespace BinaryObjectScanner.Data
|
|||||||
foreach (Type? type in assemblyTypes)
|
foreach (Type? type in assemblyTypes)
|
||||||
{
|
{
|
||||||
// Skip invalid types
|
// Skip invalid types
|
||||||
if (type == null)
|
if (type is null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// If the type isn't a class
|
// If the type isn't a class
|
||||||
@@ -170,7 +150,7 @@ namespace BinaryObjectScanner.Data
|
|||||||
|
|
||||||
// Try to create a concrete instance of the type
|
// Try to create a concrete instance of the type
|
||||||
var instance = (T?)Activator.CreateInstance(type);
|
var instance = (T?)Activator.CreateInstance(type);
|
||||||
if (instance != null)
|
if (instance is not null)
|
||||||
classTypes.Add(instance);
|
classTypes.Add(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
|
#pragma warning disable IDE0290 // Use primary constructor
|
||||||
namespace BinaryObjectScanner.FileType
|
namespace BinaryObjectScanner.FileType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
|
#pragma warning disable IDE0290 // Use primary constructor
|
||||||
namespace BinaryObjectScanner.FileType
|
namespace BinaryObjectScanner.FileType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using BinaryObjectScanner.Interfaces;
|
using BinaryObjectScanner.Interfaces;
|
||||||
using SabreTools.Serialization.Wrappers;
|
using SabreTools.Serialization.Wrappers;
|
||||||
|
|
||||||
|
#pragma warning disable IDE0290 // Use primary constructor
|
||||||
namespace BinaryObjectScanner.FileType
|
namespace BinaryObjectScanner.FileType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
50
BinaryObjectScanner/FileType/DiskImage.cs
Normal file
50
BinaryObjectScanner/FileType/DiskImage.cs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using BinaryObjectScanner.Data;
|
||||||
|
using BinaryObjectScanner.Interfaces;
|
||||||
|
using SabreTools.IO.Extensions;
|
||||||
|
using SabreTools.Serialization.Wrappers;
|
||||||
|
|
||||||
|
#pragma warning disable IDE0290 // Use primary constructor
|
||||||
|
namespace BinaryObjectScanner.FileType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Disk image file
|
||||||
|
/// </summary>
|
||||||
|
public abstract class DiskImage<T> : DetectableBase<T>
|
||||||
|
where T : WrapperBase
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public DiskImage(T wrapper) : base(wrapper) { }
|
||||||
|
|
||||||
|
#region Check Runners
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handle a single file based on all disk image check implementations
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="file">Name of the source file of the disk image, for tracking</param>
|
||||||
|
/// <param name="checks">Set of checks to use</param>
|
||||||
|
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||||
|
/// <returns>Set of protections in file, empty on error</returns>
|
||||||
|
protected IDictionary<U, string> RunDiskImageChecks<U>(string file, U[] checks, bool includeDebug)
|
||||||
|
where U : IDiskImageCheck<T>
|
||||||
|
{
|
||||||
|
// Create the output dictionary
|
||||||
|
var protections = new CheckDictionary<U>();
|
||||||
|
|
||||||
|
// Iterate through all checks
|
||||||
|
checks.IterateWithAction(checkClass =>
|
||||||
|
{
|
||||||
|
// Get the protection for the class, if possible
|
||||||
|
var protection = checkClass.CheckDiskImage(file, _wrapper, includeDebug);
|
||||||
|
if (string.IsNullOrEmpty(protection))
|
||||||
|
return;
|
||||||
|
|
||||||
|
protections.Append(checkClass, protection);
|
||||||
|
});
|
||||||
|
|
||||||
|
return protections;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ using BinaryObjectScanner.Interfaces;
|
|||||||
using SabreTools.IO.Extensions;
|
using SabreTools.IO.Extensions;
|
||||||
using SabreTools.Serialization.Wrappers;
|
using SabreTools.Serialization.Wrappers;
|
||||||
|
|
||||||
|
#pragma warning disable IDE0290 // Use primary constructor
|
||||||
namespace BinaryObjectScanner.FileType
|
namespace BinaryObjectScanner.FileType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -47,7 +48,7 @@ namespace BinaryObjectScanner.FileType
|
|||||||
|
|
||||||
stream.Seek(0, SeekOrigin.Begin);
|
stream.Seek(0, SeekOrigin.Begin);
|
||||||
fileContent = stream.ReadBytes((int)stream.Length);
|
fileContent = stream.ReadBytes((int)stream.Length);
|
||||||
if (fileContent == null)
|
if (fileContent is null)
|
||||||
return protections;
|
return protections;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -74,12 +75,10 @@ namespace BinaryObjectScanner.FileType
|
|||||||
/// Handle a single file based on all executable check implementations
|
/// Handle a single file based on all executable check implementations
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="file">Name of the source file of the executable, for tracking</param>
|
/// <param name="file">Name of the source file of the executable, for tracking</param>
|
||||||
/// <param name="exe">Executable to scan</param>
|
|
||||||
/// <param name="checks">Set of checks to use</param>
|
/// <param name="checks">Set of checks to use</param>
|
||||||
/// <param name="scanner">Scanner for handling recursive protections</param>
|
|
||||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||||
/// <returns>Set of protections in file, empty on error</returns>
|
/// <returns>Set of protections in file, empty on error</returns>
|
||||||
protected IDictionary<U, string> RunExecutableChecks<U>(string file, T exe, U[] checks, bool includeDebug)
|
protected IDictionary<U, string> RunExecutableChecks<U>(string file, U[] checks, bool includeDebug)
|
||||||
where U : IExecutableCheck<T>
|
where U : IExecutableCheck<T>
|
||||||
{
|
{
|
||||||
// Create the output dictionary
|
// Create the output dictionary
|
||||||
@@ -89,7 +88,7 @@ namespace BinaryObjectScanner.FileType
|
|||||||
checks.IterateWithAction(checkClass =>
|
checks.IterateWithAction(checkClass =>
|
||||||
{
|
{
|
||||||
// Get the protection for the class, if possible
|
// Get the protection for the class, if possible
|
||||||
var protection = checkClass.CheckExecutable(file, exe, includeDebug);
|
var protection = checkClass.CheckExecutable(file, _wrapper, includeDebug);
|
||||||
if (string.IsNullOrEmpty(protection))
|
if (string.IsNullOrEmpty(protection))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
35
BinaryObjectScanner/FileType/GCF.cs
Normal file
35
BinaryObjectScanner/FileType/GCF.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace BinaryObjectScanner.FileType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Game Cache File (GCF)
|
||||||
|
/// </summary>
|
||||||
|
public class GCF : DetectableBase<SabreTools.Serialization.Wrappers.GCF>
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public GCF(SabreTools.Serialization.Wrappers.GCF wrapper) : base(wrapper) { }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override string? Detect(Stream stream, string file, bool includeDebug)
|
||||||
|
{
|
||||||
|
// Filename is worth reporting, since it's descriptive and has to match the Steam2 CDN in order to work.
|
||||||
|
string fileName = Path.GetFileName(file);
|
||||||
|
uint depotId = _wrapper.Model.Header.CacheID;
|
||||||
|
uint manifestVersion = _wrapper.Model.Header.LastVersionPlayed;
|
||||||
|
|
||||||
|
// At the moment, all samples of GCF files on redump are unencrypted. Combined with being uncertain about
|
||||||
|
// whether this is the best way to check whether the GCF is encrypted, this block will be left commented
|
||||||
|
// out until further research is done.
|
||||||
|
// bool encrypted = false;
|
||||||
|
// if (_wrapper.Files != null && _wrapper.Files.Length > 0)
|
||||||
|
// encrypted = _wrapper.Files[0].Encrypted;
|
||||||
|
|
||||||
|
// string encryptedString = encrypted ? "encrypted" : "unencrypted";
|
||||||
|
// string returnString = $"{fileName} - {depotId} (v{manifestVersion}, {encryptedString})";
|
||||||
|
|
||||||
|
string returnString = $"{fileName} - {depotId} (v{manifestVersion})";
|
||||||
|
return returnString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
139
BinaryObjectScanner/FileType/ISO9660.cs
Normal file
139
BinaryObjectScanner/FileType/ISO9660.cs
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using BinaryObjectScanner.Data;
|
||||||
|
using SabreTools.Data.Models.ISO9660;
|
||||||
|
using SabreTools.IO.Extensions;
|
||||||
|
|
||||||
|
#pragma warning disable IDE0290 // Use primary constructor
|
||||||
|
namespace BinaryObjectScanner.FileType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ISO9660
|
||||||
|
/// </summary>
|
||||||
|
public class ISO9660 : DiskImage<SabreTools.Serialization.Wrappers.ISO9660>
|
||||||
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public ISO9660(SabreTools.Serialization.Wrappers.ISO9660 wrapper) : base(wrapper) { }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override string? Detect(Stream stream, string file, bool includeDebug)
|
||||||
|
{
|
||||||
|
// Create the output dictionary
|
||||||
|
var protections = new ProtectionDictionary();
|
||||||
|
|
||||||
|
// Standard checks
|
||||||
|
var subProtections
|
||||||
|
= RunDiskImageChecks(file, StaticChecks.ISO9660CheckClasses, includeDebug);
|
||||||
|
protections.Append(file, subProtections.Values);
|
||||||
|
|
||||||
|
// If there are no protections
|
||||||
|
if (protections.Count == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Create the internal list
|
||||||
|
var protectionList = new List<string>();
|
||||||
|
foreach (string key in protections.Keys)
|
||||||
|
{
|
||||||
|
protectionList.AddRange(protections[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Join(";", [.. protectionList]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks whether the sequence of bytes is pure data (as in, not empty,
|
||||||
|
/// not text, just high-entropy data)
|
||||||
|
/// </summary>
|
||||||
|
public static bool IsPureData(byte[] bytes)
|
||||||
|
{
|
||||||
|
// Check if there are three 0x00s in a row. Two seems like pushing it
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < bytes.Length; ++i)
|
||||||
|
{
|
||||||
|
if (bytes[i] == 0x00)
|
||||||
|
{
|
||||||
|
if (++index >= 3)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if there are strings in the data
|
||||||
|
// TODO: is this too dangerous, or too faulty?
|
||||||
|
// 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 -'!,.]", RegexOptions.Compiled);
|
||||||
|
foreach (string str in strings)
|
||||||
|
{
|
||||||
|
if (rgx.Replace(str, "").Length > 7)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks whether the Application Use data is "noteworthy" enough to be worth checking for protection.
|
||||||
|
/// </summary>
|
||||||
|
/// TODO: can these 2 "noteworthy" functions be cached?
|
||||||
|
public static bool NoteworthyApplicationUse(PrimaryVolumeDescriptor pvd)
|
||||||
|
{
|
||||||
|
var applicationUse = pvd.ApplicationUse;
|
||||||
|
if (Array.TrueForAll(applicationUse, b => b == 0x00))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
string? potentialAppUseString = applicationUse.ReadNullTerminatedAnsiString(ref offset);
|
||||||
|
if (potentialAppUseString is not null && potentialAppUseString.Length > 0) // Some image authoring programs add a starting string to AU data
|
||||||
|
{
|
||||||
|
if (potentialAppUseString.StartsWith("ImgBurn"))
|
||||||
|
return false;
|
||||||
|
else if (potentialAppUseString.StartsWith("ULTRAISO"))
|
||||||
|
return false;
|
||||||
|
else if (potentialAppUseString.StartsWith("Rimage"))
|
||||||
|
return false;
|
||||||
|
else if (Array.TrueForAll(Encoding.ASCII.GetBytes(potentialAppUseString), b => b == 0x20))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// TODO: Unhandled "norb" mastering that puts stuff everywhere, inconsistently. See RID 103641
|
||||||
|
// More things will have to go here as more disc authoring softwares are found that do this.
|
||||||
|
// Redump ID 24478 has a bunch of 0x20 with norb in the middle, some discs have 0x20 that ends in a "/"
|
||||||
|
// character. If these are found to be causing issues they can be added.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seems to come from "FERGUS_MCNEILL - ISOCD 1.00 by Pantaray, Inc. USA -"
|
||||||
|
offset = 1;
|
||||||
|
potentialAppUseString = applicationUse.ReadNullTerminatedAnsiString(ref offset);
|
||||||
|
if (potentialAppUseString == "FS")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
offset = 141;
|
||||||
|
potentialAppUseString = applicationUse.ReadNullTerminatedAnsiString(ref offset);
|
||||||
|
if (potentialAppUseString == "CD-XA001")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks whether the Reserved 653 Bytes are "noteworthy" enough to be worth checking for protection.
|
||||||
|
/// </summary>
|
||||||
|
public static bool NoteworthyReserved653Bytes(PrimaryVolumeDescriptor pvd)
|
||||||
|
{
|
||||||
|
var reserved653Bytes = pvd.Reserved653Bytes;
|
||||||
|
var noteworthyReserved653Bytes = true;
|
||||||
|
if (Array.TrueForAll(reserved653Bytes, b => b == 0x00))
|
||||||
|
noteworthyReserved653Bytes = false;
|
||||||
|
|
||||||
|
// Unsure if more will be needed
|
||||||
|
return noteworthyReserved653Bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
|
#pragma warning disable IDE0290 // Use primary constructor
|
||||||
namespace BinaryObjectScanner.FileType
|
namespace BinaryObjectScanner.FileType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using BinaryObjectScanner.Data;
|
using BinaryObjectScanner.Data;
|
||||||
|
|
||||||
|
#pragma warning disable IDE0290 // Use primary constructor
|
||||||
namespace BinaryObjectScanner.FileType
|
namespace BinaryObjectScanner.FileType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -27,7 +28,7 @@ namespace BinaryObjectScanner.FileType
|
|||||||
|
|
||||||
// Standard checks
|
// Standard checks
|
||||||
var subProtections
|
var subProtections
|
||||||
= RunExecutableChecks(file, _wrapper, StaticChecks.LinearExecutableCheckClasses, includeDebug);
|
= RunExecutableChecks(file, StaticChecks.LinearExecutableCheckClasses, includeDebug);
|
||||||
protections.Append(file, subProtections.Values);
|
protections.Append(file, subProtections.Values);
|
||||||
|
|
||||||
// If there are no protections
|
// If there are no protections
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using BinaryObjectScanner.Data;
|
using BinaryObjectScanner.Data;
|
||||||
|
|
||||||
|
#pragma warning disable IDE0290 // Use primary constructor
|
||||||
namespace BinaryObjectScanner.FileType
|
namespace BinaryObjectScanner.FileType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -27,7 +28,7 @@ namespace BinaryObjectScanner.FileType
|
|||||||
|
|
||||||
// Standard checks
|
// Standard checks
|
||||||
var subProtections
|
var subProtections
|
||||||
= RunExecutableChecks(file, _wrapper, StaticChecks.MSDOSExecutableCheckClasses, includeDebug);
|
= RunExecutableChecks(file, StaticChecks.MSDOSExecutableCheckClasses, includeDebug);
|
||||||
protections.Append(file, subProtections.Values);
|
protections.Append(file, subProtections.Values);
|
||||||
|
|
||||||
// If there are no protections
|
// If there are no protections
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using BinaryObjectScanner.Data;
|
using BinaryObjectScanner.Data;
|
||||||
|
|
||||||
|
#pragma warning disable IDE0290 // Use primary constructor
|
||||||
namespace BinaryObjectScanner.FileType
|
namespace BinaryObjectScanner.FileType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -27,7 +28,7 @@ namespace BinaryObjectScanner.FileType
|
|||||||
|
|
||||||
// Standard checks
|
// Standard checks
|
||||||
var subProtections
|
var subProtections
|
||||||
= RunExecutableChecks(file, _wrapper, StaticChecks.NewExecutableCheckClasses, includeDebug);
|
= RunExecutableChecks(file, StaticChecks.NewExecutableCheckClasses, includeDebug);
|
||||||
protections.Append(file, subProtections.Values);
|
protections.Append(file, subProtections.Values);
|
||||||
|
|
||||||
// If there are no protections
|
// If there are no protections
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using SabreTools.Serialization.Wrappers;
|
using SabreTools.Serialization.Wrappers;
|
||||||
|
|
||||||
|
#pragma warning disable IDE0290 // Use primary constructor
|
||||||
namespace BinaryObjectScanner.FileType
|
namespace BinaryObjectScanner.FileType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using BinaryObjectScanner.Data;
|
using BinaryObjectScanner.Data;
|
||||||
|
|
||||||
|
#pragma warning disable IDE0290 // Use primary constructor
|
||||||
namespace BinaryObjectScanner.FileType
|
namespace BinaryObjectScanner.FileType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -27,7 +28,7 @@ namespace BinaryObjectScanner.FileType
|
|||||||
|
|
||||||
// Standard checks
|
// Standard checks
|
||||||
var subProtections
|
var subProtections
|
||||||
= RunExecutableChecks(file, _wrapper, StaticChecks.PortableExecutableCheckClasses, includeDebug);
|
= RunExecutableChecks(file, StaticChecks.PortableExecutableCheckClasses, includeDebug);
|
||||||
protections.Append(file, subProtections.Values);
|
protections.Append(file, subProtections.Values);
|
||||||
|
|
||||||
// If there are no protections
|
// If there are no protections
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
|
#pragma warning disable IDE0290 // Use primary constructor
|
||||||
namespace BinaryObjectScanner.FileType
|
namespace BinaryObjectScanner.FileType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
|
#pragma warning disable IDE0290 // Use primary constructor
|
||||||
namespace BinaryObjectScanner.FileType
|
namespace BinaryObjectScanner.FileType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
|
#pragma warning disable IDE0290 // Use primary constructor
|
||||||
namespace BinaryObjectScanner.FileType
|
namespace BinaryObjectScanner.FileType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -153,7 +153,6 @@ namespace BinaryObjectScanner.FileType
|
|||||||
protections.Add("SafeDiscLT for Macintosh (Unknown Version - Please report to us on GitHub)");
|
protections.Add("SafeDiscLT for Macintosh (Unknown Version - Please report to us on GitHub)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// The full line from a sample is as follows:
|
// The full line from a sample is as follows:
|
||||||
//
|
//
|
||||||
// The files securom_v7_01.dat and securom_v7_01.bak have been created during the installation of a SecuROM protected application.
|
// The files securom_v7_01.dat and securom_v7_01.bak have been created during the installation of a SecuROM protected application.
|
||||||
|
|||||||
@@ -12,6 +12,6 @@
|
|||||||
/// <param name="fileContent">Byte array representing the file contents</param>
|
/// <param name="fileContent">Byte array representing the file contents</param>
|
||||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||||
/// <returns>String containing any protections found in the file</returns>
|
/// <returns>String containing any protections found in the file</returns>
|
||||||
string? CheckContents(string file, byte[] fileContent, bool includeDebug);
|
public string? CheckContents(string file, byte[] fileContent, bool includeDebug);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace BinaryObjectScanner.Interfaces
|
|||||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||||
/// <returns>Detected file or protection type, null on error</returns>
|
/// <returns>Detected file or protection type, null on error</returns>
|
||||||
/// <remarks>Ideally, this should just point to the other detect implementation.</remarks>
|
/// <remarks>Ideally, this should just point to the other detect implementation.</remarks>
|
||||||
string? Detect(string file, bool includeDebug);
|
public string? Detect(string file, bool includeDebug);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if a stream is detected as this file type
|
/// Check if a stream is detected as this file type
|
||||||
@@ -23,6 +23,6 @@ namespace BinaryObjectScanner.Interfaces
|
|||||||
/// <param name="file">Path to the input file</param>
|
/// <param name="file">Path to the input file</param>
|
||||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||||
/// <returns>Detected file or protection type, null on error</returns>
|
/// <returns>Detected file or protection type, null on error</returns>
|
||||||
string? Detect(Stream stream, string file, bool includeDebug);
|
public string? Detect(Stream stream, string file, bool includeDebug);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
19
BinaryObjectScanner/Interfaces/IDiskImageCheck.cs
Normal file
19
BinaryObjectScanner/Interfaces/IDiskImageCheck.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using SabreTools.Serialization.Wrappers;
|
||||||
|
|
||||||
|
namespace BinaryObjectScanner.Interfaces
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Check a disk image for protection
|
||||||
|
/// </summary>
|
||||||
|
public interface IDiskImageCheck<T> where T : WrapperBase
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Check a path for protections based on file contents
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="file">File to check for protection indicators</param>
|
||||||
|
/// <param name="diskImage">Disk image representing the read-in file</param>
|
||||||
|
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||||
|
/// <returns>String containing any protections found in the file</returns>
|
||||||
|
public string? CheckDiskImage(string file, T diskImage, bool includeDebug);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,6 @@ namespace BinaryObjectScanner.Interfaces
|
|||||||
/// <param name="exe">Executable representing the read-in file</param>
|
/// <param name="exe">Executable representing the read-in file</param>
|
||||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||||
/// <returns>String containing any protections found in the file</returns>
|
/// <returns>String containing any protections found in the file</returns>
|
||||||
string? CheckExecutable(string file, T exe, bool includeDebug);
|
public string? CheckExecutable(string file, T exe, bool includeDebug);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ namespace BinaryObjectScanner.Interfaces
|
|||||||
/// <param name="path">Path to check for protection indicators</param>
|
/// <param name="path">Path to check for protection indicators</param>
|
||||||
/// <param name="files">List of strings representing files in a directory</param>
|
/// <param name="files">List 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>
|
/// <remarks>This can do some limited content checking as well, but it's suggested to use a content check instead, if possible</remarks>
|
||||||
List<string> CheckDirectoryPath(string path, List<string>? files);
|
public List<string> CheckDirectoryPath(string path, List<string>? files);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check a file path for protections based on path name
|
/// Check a file path for protections based on path name
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">Path to check for protection indicators</param>
|
/// <param name="path">Path to check for protection indicators</param>
|
||||||
/// <remarks>This can do some limited content checking as well, but it's suggested to use a content check instead, if possible</remarks>
|
/// <remarks>This can do some limited content checking as well, but it's suggested to use a content check instead, if possible</remarks>
|
||||||
string? CheckFilePath(string path);
|
public string? CheckFilePath(string path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
return "ASPack 2.29";
|
return "ASPack 2.29";
|
||||||
|
|
||||||
// Use the entry point data, if it exists
|
// Use the entry point data, if it exists
|
||||||
if (exe.EntryPointData != null)
|
if (exe.EntryPointData is not null)
|
||||||
{
|
{
|
||||||
var matchers = GenerateMatchers();
|
var matchers = GenerateMatchers();
|
||||||
var match = MatchUtil.GetFirstMatch(file, exe.EntryPointData, matchers, includeDebug);
|
var match = MatchUtil.GetFirstMatch(file, exe.EntryPointData, matchers, includeDebug);
|
||||||
@@ -28,7 +28,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
|
|
||||||
// Get the .adata* section, if it exists
|
// Get the .adata* section, if it exists
|
||||||
var adataSectionRaw = exe.GetFirstSectionData(".adata", exact: false);
|
var adataSectionRaw = exe.GetFirstSectionData(".adata", exact: false);
|
||||||
if (adataSectionRaw != null)
|
if (adataSectionRaw is not null)
|
||||||
{
|
{
|
||||||
var matchers = GenerateMatchers();
|
var matchers = GenerateMatchers();
|
||||||
var match = MatchUtil.GetFirstMatch(file, adataSectionRaw, matchers, includeDebug);
|
var match = MatchUtil.GetFirstMatch(file, adataSectionRaw, matchers, includeDebug);
|
||||||
@@ -38,7 +38,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
|
|
||||||
// Get the .data/DATA section, if it exists
|
// Get the .data/DATA section, if it exists
|
||||||
var dataSectionRaw = exe.GetFirstSectionData(".data") ?? exe.GetFirstSectionData("DATA");
|
var dataSectionRaw = exe.GetFirstSectionData(".data") ?? exe.GetFirstSectionData("DATA");
|
||||||
if (dataSectionRaw != null)
|
if (dataSectionRaw is not null)
|
||||||
{
|
{
|
||||||
var matchers = GenerateMatchers();
|
var matchers = GenerateMatchers();
|
||||||
var match = MatchUtil.GetFirstMatch(file, dataSectionRaw, matchers, includeDebug);
|
var match = MatchUtil.GetFirstMatch(file, dataSectionRaw, matchers, includeDebug);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
{
|
{
|
||||||
// Get the .rdata section strings, if they exist
|
// Get the .rdata section strings, if they exist
|
||||||
var strs = exe.GetFirstSectionStrings(".rdata");
|
var strs = exe.GetFirstSectionStrings(".rdata");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
if (strs.Exists(s => s.Contains("Software\\Caphyon\\Advanced Installer")))
|
if (strs.Exists(s => s.Contains("Software\\Caphyon\\Advanced Installer")))
|
||||||
return "Caphyon Advanced Installer SFX";
|
return "Caphyon Advanced Installer SFX";
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
if (exe.FindResourceByNamedType("99, ").Count == 2)
|
if (exe.FindResourceByNamedType("99, ").Count == 2)
|
||||||
return "CExe";
|
return "CExe";
|
||||||
|
|
||||||
if (exe.StubExecutableData != null)
|
if (exe.StubExecutableData is not null)
|
||||||
{
|
{
|
||||||
var matchers = new List<ContentMatchSet>
|
var matchers = new List<ContentMatchSet>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ namespace BinaryObjectScanner.Packer
|
|||||||
// TODO: Investigate if this can be found by aligning to section containing entry point
|
// TODO: Investigate if this can be found by aligning to section containing entry point
|
||||||
|
|
||||||
// Get the last section strings, if they exist
|
// Get the last section strings, if they exist
|
||||||
var sections = exe.SectionTable ?? [];
|
var sections = exe.SectionTable;
|
||||||
var strs = exe.GetSectionStrings(sections.Length - 1);
|
var strs = exe.GetSectionStrings(sections.Length - 1);
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
if (strs.Exists(s => s.Contains("BITARTS")))
|
if (strs.Exists(s => s.Contains("BITARTS")))
|
||||||
return "Crunch";
|
return "Crunch";
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
{
|
{
|
||||||
// Get the .text section strings, if they exist
|
// Get the .text section strings, if they exist
|
||||||
var strs = exe.GetFirstSectionStrings(".text");
|
var strs = exe.GetFirstSectionStrings(".text");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
if (strs.Exists(s => s.Contains("DotfuscatorAttribute")))
|
if (strs.Exists(s => s.Contains("DotfuscatorAttribute")))
|
||||||
return "dotFuscator";
|
return "dotFuscator";
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
|
|
||||||
// Get the .text section, if it exists
|
// Get the .text section, if it exists
|
||||||
var textData = exe.GetFirstSectionData(".text");
|
var textData = exe.GetFirstSectionData(".text");
|
||||||
if (textData != null)
|
if (textData is not null)
|
||||||
{
|
{
|
||||||
var matchers = new List<ContentMatchSet>
|
var matchers = new List<ContentMatchSet>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using BinaryObjectScanner.Interfaces;
|
using BinaryObjectScanner.Interfaces;
|
||||||
|
using SabreTools.Data.Models.PortableExecutable.Resource.Entries;
|
||||||
using SabreTools.IO.Extensions;
|
using SabreTools.IO.Extensions;
|
||||||
using SabreTools.Serialization.Wrappers;
|
using SabreTools.Serialization.Wrappers;
|
||||||
|
|
||||||
@@ -19,7 +20,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
|
|
||||||
// Check the overlay, if it exists
|
// Check the overlay, if it exists
|
||||||
byte[]? overlayData = exe.OverlayData;
|
byte[]? overlayData = exe.OverlayData;
|
||||||
if (overlayData != null && overlayData.Length > 0)
|
if (overlayData is not null && overlayData.Length > 0)
|
||||||
{
|
{
|
||||||
// Set the output variables
|
// Set the output variables
|
||||||
int overlayOffset = 0;
|
int overlayOffset = 0;
|
||||||
@@ -111,12 +112,16 @@ namespace BinaryObjectScanner.Packer
|
|||||||
|
|
||||||
// Only process the resources if they are recognized
|
// Only process the resources if they are recognized
|
||||||
var resourceData = exe.ResourceData;
|
var resourceData = exe.ResourceData;
|
||||||
if (resourceData != null)
|
if (resourceData is not null)
|
||||||
{
|
{
|
||||||
// Get the resources that have an archive signature
|
// Get the resources that have an archive signature
|
||||||
foreach (var value in resourceData.Values)
|
foreach (var value in resourceData.Values)
|
||||||
{
|
{
|
||||||
if (value == null || value is not byte[] ba || ba.Length == 0)
|
if (value is null || value is not GenericResourceEntry gre)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
byte[] ba = gre.Data;
|
||||||
|
if (ba.Length == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Set the output variables
|
// Set the output variables
|
||||||
@@ -162,7 +167,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
|
|
||||||
// Check the overlay, if it exists
|
// Check the overlay, if it exists
|
||||||
byte[]? overlayData = exe.OverlayData;
|
byte[]? overlayData = exe.OverlayData;
|
||||||
if (overlayData != null && overlayData.Length > 0)
|
if (overlayData is not null && overlayData.Length > 0)
|
||||||
{
|
{
|
||||||
// Set the output variables
|
// Set the output variables
|
||||||
int overlayOffset = 0;
|
int overlayOffset = 0;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
|
|
||||||
// Get the .data/DATA section strings, if they exist
|
// Get the .data/DATA section strings, if they exist
|
||||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
if (strs.Exists(s => s.Contains("Gentee installer")))
|
if (strs.Exists(s => s.Contains("Gentee installer")))
|
||||||
return "Gentee Installer";
|
return "Gentee Installer";
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
{
|
{
|
||||||
// <see href="https://www.virustotal.com/gui/file/b2fc4cffe5131195baf419e96c9fa68c3f23208986fb14e3c5b458b1e7d6af89/details"/>
|
// <see href="https://www.virustotal.com/gui/file/b2fc4cffe5131195baf419e96c9fa68c3f23208986fb14e3c5b458b1e7d6af89/details"/>
|
||||||
var overlayData = exe.OverlayData;
|
var overlayData = exe.OverlayData;
|
||||||
if (overlayData != null)
|
if (overlayData is not null)
|
||||||
{
|
{
|
||||||
// GIPEND
|
// GIPEND
|
||||||
if (overlayData.EndsWith([0x47, 0x49, 0x50, 0x45, 0x4E, 0x44]))
|
if (overlayData.EndsWith([0x47, 0x49, 0x50, 0x45, 0x4E, 0x44]))
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
{
|
{
|
||||||
// Check for "Inno" in the reserved words
|
// Check for "Inno" in the reserved words
|
||||||
var reserved2 = exe.Stub?.Header?.Reserved2;
|
var reserved2 = exe.Stub?.Header?.Reserved2;
|
||||||
if (reserved2 != null && reserved2.Length > 5)
|
if (reserved2 is not null && reserved2.Length > 5)
|
||||||
{
|
{
|
||||||
if (reserved2[4] == 0x6E49 && reserved2[5] == 0x6F6E)
|
if (reserved2[4] == 0x6E49 && reserved2[5] == 0x6F6E)
|
||||||
{
|
{
|
||||||
@@ -35,10 +35,10 @@ namespace BinaryObjectScanner.Packer
|
|||||||
{
|
{
|
||||||
// Get the .data/DATA section strings, if they exist
|
// Get the .data/DATA section strings, if they exist
|
||||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
var str = strs.Find(s => s.StartsWith("Inno Setup Setup Data"));
|
var str = strs.Find(s => s.StartsWith("Inno Setup Setup Data"));
|
||||||
if (str != null)
|
if (str is not null)
|
||||||
{
|
{
|
||||||
return str.Replace("Inno Setup Setup Data", "Inno Setup")
|
return str.Replace("Inno Setup Setup Data", "Inno Setup")
|
||||||
.Replace("(u)", "[Unicode]")
|
.Replace("(u)", "[Unicode]")
|
||||||
@@ -60,8 +60,9 @@ namespace BinaryObjectScanner.Packer
|
|||||||
// TODO: Don't read entire file
|
// TODO: Don't read entire file
|
||||||
// TODO: Only 64 bytes at the end of the file is needed
|
// TODO: Only 64 bytes at the end of the file is needed
|
||||||
|
|
||||||
|
#pragma warning disable CS0618
|
||||||
byte[]? data = exe.ReadArbitraryRange();
|
byte[]? data = exe.ReadArbitraryRange();
|
||||||
if (data == null)
|
if (data is null)
|
||||||
return "Unknown 1.X";
|
return "Unknown 1.X";
|
||||||
|
|
||||||
var matchers = new List<ContentMatchSet>
|
var matchers = new List<ContentMatchSet>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
{
|
{
|
||||||
// Get the .data/DATA section strings, if they exist
|
// Get the .data/DATA section strings, if they exist
|
||||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
if (strs.Exists(s => s.Contains("ViseMain")))
|
if (strs.Exists(s => s.Contains("ViseMain")))
|
||||||
return "Installer VISE";
|
return "Installer VISE";
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
|
|
||||||
// Get the .data/DATA section strings, if they exist
|
// Get the .data/DATA section strings, if they exist
|
||||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
if (strs.Exists(s => s.Contains("wextract_cleanup")))
|
if (strs.Exists(s => s.Contains("wextract_cleanup")))
|
||||||
return $"Microsoft CAB SFX {GetVersion(exe)}";
|
return $"Microsoft CAB SFX {GetVersion(exe)}";
|
||||||
@@ -31,7 +31,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
|
|
||||||
// Get the .text section strings, if they exist
|
// Get the .text section strings, if they exist
|
||||||
strs = exe.GetFirstSectionStrings(".text");
|
strs = exe.GetFirstSectionStrings(".text");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
// This detects a different but similar type of SFX that uses Microsoft CAB files.
|
// This detects a different but similar type of SFX that uses Microsoft CAB files.
|
||||||
// Further research is needed to see if it's just a different version or entirely separate.
|
// Further research is needed to see if it's just a different version or entirely separate.
|
||||||
|
|||||||
@@ -17,11 +17,20 @@ namespace BinaryObjectScanner.Packer
|
|||||||
string? name = exe.AssemblyDescription;
|
string? name = exe.AssemblyDescription;
|
||||||
|
|
||||||
if (name.OptionalStartsWith("Nullsoft Install System"))
|
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()}";
|
return $"NSIS {name!.Substring("Nullsoft Install System".Length).Trim()}";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
name = exe.AssemblyName;
|
||||||
|
|
||||||
|
if (name.OptionalStartsWith("Nullsoft.NSIS"))
|
||||||
|
return "NSIS";
|
||||||
|
|
||||||
// Get the .data/DATA section strings, if they exist
|
// Get the .data/DATA section strings, if they exist
|
||||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
if (strs.Exists(s => s.Contains("NullsoftInst")))
|
if (strs.Exists(s => s.Contains("NullsoftInst")))
|
||||||
return "NSIS";
|
return "NSIS";
|
||||||
@@ -29,7 +38,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
|
|
||||||
// Get the overlay strings, if they exist
|
// Get the overlay strings, if they exist
|
||||||
strs = exe.OverlayStrings;
|
strs = exe.OverlayStrings;
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
if (strs.Exists(s => s.Contains("NullsoftInst")))
|
if (strs.Exists(s => s.Contains("NullsoftInst")))
|
||||||
return "NSIS";
|
return "NSIS";
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
{
|
{
|
||||||
// Get the .data/DATA section strings, if they exist
|
// Get the .data/DATA section strings, if they exist
|
||||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
// <see href="https://www.virustotal.com/gui/file/33b98b675d78b88ed317e7e52dca21ca07bd84e79211294fcec72cab48d11184"/>
|
// <see href="https://www.virustotal.com/gui/file/33b98b675d78b88ed317e7e52dca21ca07bd84e79211294fcec72cab48d11184"/>
|
||||||
if (strs.Exists(s => s.Contains("ReflexiveArcade")))
|
if (strs.Exists(s => s.Contains("ReflexiveArcade")))
|
||||||
|
|||||||
@@ -12,7 +12,11 @@ namespace BinaryObjectScanner.Packer
|
|||||||
string? name = exe.AssemblyDescription;
|
string? name = exe.AssemblyDescription;
|
||||||
|
|
||||||
if (name.OptionalStartsWith("7-Zip Self-extracting Archive"))
|
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)}";
|
return $"7-Zip SFX {exe.AssemblyDescription!.Substring("7-Zip Self-extracting Archive ".Length)}";
|
||||||
|
#endif
|
||||||
|
|
||||||
name = exe.FileDescription;
|
name = exe.FileDescription;
|
||||||
|
|
||||||
|
|||||||
@@ -4,28 +4,30 @@ using System.Text.RegularExpressions;
|
|||||||
using BinaryObjectScanner.Interfaces;
|
using BinaryObjectScanner.Interfaces;
|
||||||
using SabreTools.Serialization.Wrappers;
|
using SabreTools.Serialization.Wrappers;
|
||||||
|
|
||||||
|
#pragma warning disable IDE0060 // Remove unused parameter
|
||||||
|
#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'
|
||||||
namespace BinaryObjectScanner.Packer
|
namespace BinaryObjectScanner.Packer
|
||||||
{
|
{
|
||||||
// TODO: Add extraction
|
// TODO: Add extraction
|
||||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||||
public class UPX : IExecutableCheck<PortableExecutable>
|
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/>
|
/// <inheritdoc/>
|
||||||
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
||||||
{
|
{
|
||||||
// Check header padding strings
|
// Check header padding strings
|
||||||
if (exe.HeaderPaddingStrings != null && exe.HeaderPaddingStrings.Count > 0)
|
if (exe.HeaderPaddingStrings is not null && exe.HeaderPaddingStrings.Count > 0)
|
||||||
{
|
{
|
||||||
var match = exe.HeaderPaddingStrings.Find(s => s.Contains("UPX!"));
|
var match = exe.HeaderPaddingStrings.Find(s => s.Contains("UPX!"));
|
||||||
//if (match != null)
|
//if (match is not null)
|
||||||
// return "UPX";
|
// return "UPX";
|
||||||
|
|
||||||
match = exe.HeaderPaddingStrings.Find(s => s.StartsWith("$Id: UPX"));
|
match = exe.HeaderPaddingStrings.Find(s => s.StartsWith("$Id: UPX"));
|
||||||
if (match != null)
|
if (match is not null)
|
||||||
{
|
{
|
||||||
var regexMatch = _oldUpxVersionMatch.Match(match);
|
var regexMatch = _oldUpxVersionMatch.Match(match);
|
||||||
if (regexMatch.Success)
|
if (regexMatch.Success)
|
||||||
@@ -35,7 +37,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
}
|
}
|
||||||
|
|
||||||
match = exe.HeaderPaddingStrings.Find(s => _upxVersionMatch.IsMatch(s));
|
match = exe.HeaderPaddingStrings.Find(s => _upxVersionMatch.IsMatch(s));
|
||||||
if (match != null && exe.HeaderPaddingStrings.Exists(s => s == "UPX!"))
|
if (match is not null && exe.HeaderPaddingStrings.Exists(s => s == "UPX!"))
|
||||||
{
|
{
|
||||||
var regexMatch = _upxVersionMatch.Match(match);
|
var regexMatch = _upxVersionMatch.Match(match);
|
||||||
if (regexMatch.Success)
|
if (regexMatch.Success)
|
||||||
@@ -43,7 +45,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
else
|
else
|
||||||
return "UPX (Unknown Version)";
|
return "UPX (Unknown Version)";
|
||||||
}
|
}
|
||||||
else if (match != null && exe.HeaderPaddingStrings.Exists(s => s == "NOS "))
|
else if (match is not null && exe.HeaderPaddingStrings.Exists(s => s == "NOS "))
|
||||||
{
|
{
|
||||||
var regexMatch = _upxVersionMatch.Match(match);
|
var regexMatch = _upxVersionMatch.Match(match);
|
||||||
if (regexMatch.Success)
|
if (regexMatch.Success)
|
||||||
|
|||||||
@@ -11,14 +11,14 @@ namespace BinaryObjectScanner.Packer
|
|||||||
public string? CheckExecutable(string file, NewExecutable exe, bool includeDebug)
|
public string? CheckExecutable(string file, NewExecutable exe, bool includeDebug)
|
||||||
{
|
{
|
||||||
// If the resident-name table doesnt exist
|
// If the resident-name table doesnt exist
|
||||||
if (exe.ResidentNameTable == null)
|
if (exe.ResidentNameTable is null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// Get the resident and non-resident name table strings
|
// Get the resident and non-resident name table strings
|
||||||
var rntStrs = Array.ConvertAll(exe.ResidentNameTable,
|
var rntStrs = Array.ConvertAll(exe.ResidentNameTable,
|
||||||
rnte => rnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(rnte.NameString));
|
rnte => rnte?.NameString is null ? string.Empty : Encoding.ASCII.GetString(rnte.NameString));
|
||||||
var nrntStrs = Array.ConvertAll(exe.NonResidentNameTable ?? [],
|
var nrntStrs = Array.ConvertAll(exe.NonResidentNameTable ?? [],
|
||||||
nrnte => nrnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(nrnte.NameString));
|
nrnte => nrnte?.NameString is null ? string.Empty : Encoding.ASCII.GetString(nrnte.NameString));
|
||||||
|
|
||||||
// Check for the WinZip name strings
|
// Check for the WinZip name strings
|
||||||
bool winZipNameFound = Array.Exists(rntStrs, s => s.Contains("WZ-SE-01"));
|
bool winZipNameFound = Array.Exists(rntStrs, s => s.Contains("WZ-SE-01"));
|
||||||
@@ -40,7 +40,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
||||||
{
|
{
|
||||||
// Check the export directory table, if it exists
|
// Check the export directory table, if it exists
|
||||||
if (exe.ExportDirectoryTable != null)
|
if (exe.ExportDirectoryTable is not null)
|
||||||
{
|
{
|
||||||
var version = GetPEExportDirectoryVersion(exe);
|
var version = GetPEExportDirectoryVersion(exe);
|
||||||
if (!string.IsNullOrEmpty(version))
|
if (!string.IsNullOrEmpty(version))
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace BinaryObjectScanner.Packer
|
|||||||
return "Wise Installation Wizard Module";
|
return "Wise Installation Wizard Module";
|
||||||
|
|
||||||
// If the section header can be found
|
// If the section header can be found
|
||||||
if (exe.WiseSection != null)
|
if (exe.WiseSection is not null)
|
||||||
return "Wise Installation Wizard Module";
|
return "Wise Installation Wizard Module";
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
// - In the stub data, there's a string for the download: "http://d.trymedia.com/dd/..."
|
// - In the stub data, there's a string for the download: "http://d.trymedia.com/dd/..."
|
||||||
|
|
||||||
// Get the entry point data, if it exists
|
// Get the entry point data, if it exists
|
||||||
if (exe.EntryPointData != null)
|
if (exe.EntryPointData is not null)
|
||||||
{
|
{
|
||||||
// Found in "Zuma.exe"
|
// Found in "Zuma.exe"
|
||||||
if (exe.EntryPointData.StartsWith(new byte?[] { 0x89, 0x25, 0x04, 0xF0, 0x86, 0x00, 0x68, 0x30 }))
|
if (exe.EntryPointData.StartsWith(new byte?[] { 0x89, 0x25, 0x04, 0xF0, 0x86, 0x00, 0x68, 0x30 }))
|
||||||
@@ -46,7 +46,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the .data section strings, if they exist
|
// Get the .data section strings, if they exist
|
||||||
var strs = exe.GetLastSectionStrings(".data");
|
var strs = exe.GetLastSectionStrings(".data");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
if (strs.Exists(s => s.Contains("MPRMMGVA"))
|
if (strs.Exists(s => s.Contains("MPRMMGVA"))
|
||||||
&& strs.Exists(s => s.Contains("This application cannot run with an active debugger in memory.")))
|
&& strs.Exists(s => s.Contains("This application cannot run with an active debugger in memory.")))
|
||||||
@@ -60,14 +60,14 @@ namespace BinaryObjectScanner.Protection
|
|||||||
if (resources.Count > 0)
|
if (resources.Count > 0)
|
||||||
{
|
{
|
||||||
bool match = resources
|
bool match = resources
|
||||||
.ConvertAll(r => r == null ? string.Empty : Encoding.ASCII.GetString(r))
|
.ConvertAll(r => r is null ? string.Empty : Encoding.ASCII.GetString(r))
|
||||||
.FindIndex(r => r.Contains("ActiveMARK")) > -1;
|
.FindIndex(r => r.Contains("ActiveMARK")) > -1;
|
||||||
if (match)
|
if (match)
|
||||||
return "ActiveMARK";
|
return "ActiveMARK";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the overlay data, if it exists
|
// Get the overlay data, if it exists
|
||||||
if (exe.OverlayStrings != null)
|
if (exe.OverlayStrings is not null)
|
||||||
{
|
{
|
||||||
if (exe.OverlayStrings.Exists(s => s.Contains("TMSAMVOH")))
|
if (exe.OverlayStrings.Exists(s => s.Contains("TMSAMVOH")))
|
||||||
return "ActiveMARK";
|
return "ActiveMARK";
|
||||||
@@ -75,7 +75,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the last .bss section strings, if they exist
|
// Get the last .bss section strings, if they exist
|
||||||
strs = exe.GetLastSectionStrings(".bss");
|
strs = exe.GetLastSectionStrings(".bss");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
if (strs.Exists(s => s.Contains("TMSAMVOF")))
|
if (strs.Exists(s => s.Contains("TMSAMVOF")))
|
||||||
return "ActiveMARK";
|
return "ActiveMARK";
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the .data/DATA section, if it exists
|
// Get the .data/DATA section, if it exists
|
||||||
var dataSectionRaw = exe.GetFirstSectionData(".data") ?? exe.GetFirstSectionData("DATA");
|
var dataSectionRaw = exe.GetFirstSectionData(".data") ?? exe.GetFirstSectionData("DATA");
|
||||||
if (dataSectionRaw != null)
|
if (dataSectionRaw is not null)
|
||||||
{
|
{
|
||||||
var matchers = new List<ContentMatchSet>
|
var matchers = new List<ContentMatchSet>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
using BinaryObjectScanner.Interfaces;
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using BinaryObjectScanner.Interfaces;
|
||||||
|
using SabreTools.Data.Models.ISO9660;
|
||||||
|
using SabreTools.IO.Extensions;
|
||||||
using SabreTools.Serialization.Wrappers;
|
using SabreTools.Serialization.Wrappers;
|
||||||
|
|
||||||
|
#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'
|
||||||
namespace BinaryObjectScanner.Protection
|
namespace BinaryObjectScanner.Protection
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -39,8 +45,87 @@ namespace BinaryObjectScanner.Protection
|
|||||||
// - SETTEC0000SETTEC1111
|
// - SETTEC0000SETTEC1111
|
||||||
// - SOFTWARE\SETTEC
|
// - SOFTWARE\SETTEC
|
||||||
// TODO: Are there version numbers?
|
// TODO: Are there version numbers?
|
||||||
public class AlphaROM : IExecutableCheck<PortableExecutable>
|
public class AlphaROM : IDiskImageCheck<ISO9660>, IExecutableCheck<PortableExecutable>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string? CheckDiskImage(string file, ISO9660 diskImage, bool includeDebug)
|
||||||
|
{
|
||||||
|
// Checks can be made even easier once UDF support exists, as most (although not all, some early discs like
|
||||||
|
// redump ID 124111 have no UDF partition) discs have "Settec" slathered over every field UDF lets them.
|
||||||
|
|
||||||
|
if (diskImage.VolumeDescriptorSet.Length == 0)
|
||||||
|
return null;
|
||||||
|
if (diskImage.VolumeDescriptorSet[0] is not PrimaryVolumeDescriptor pvd)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Disc has varying (but observed to at least always be larger than 14) length
|
||||||
|
// application identifier string made up of numbers and capital letters.
|
||||||
|
// TODO: triple-check that length is never below 14
|
||||||
|
int offset = 0;
|
||||||
|
var applicationIdentifierString = pvd.ApplicationIdentifier.ReadNullTerminatedAnsiString(ref offset)?.Trim();
|
||||||
|
if (applicationIdentifierString is null || applicationIdentifierString.Length < 14)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
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,
|
||||||
|
// so that can't reliably be used. There are two formats currently observed regarding the application
|
||||||
|
// identifier strings.
|
||||||
|
// #1 examples: DCOBG11C1B094961XN, DCXA9083CA554846GP, RCXA1107UD2510461A
|
||||||
|
// #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
|
||||||
|
// enough of a pattern to have a better check than this, but it works well enough.
|
||||||
|
if (applicationIdentifierString.Length == 18
|
||||||
|
&& Array.FindAll(applicationIdentifierStringBytes, b => b < 60).Length >= 5
|
||||||
|
&& Array.FindAll(applicationIdentifierStringBytes, b => b > 60).Length >= 5)
|
||||||
|
{
|
||||||
|
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 NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||||
|
if (!int.TryParse(applicationIdentifierString.AsSpan(0, 4), out int year)
|
||||||
|
|| !int.TryParse(applicationIdentifierString.AsSpan(4, 2), out int month)
|
||||||
|
|| !int.TryParse(applicationIdentifierString.AsSpan(6, 2), out int day)
|
||||||
|
|| !int.TryParse(applicationIdentifierString.AsSpan(8, 6), out int extraTime))
|
||||||
|
#else
|
||||||
|
if (!int.TryParse(applicationIdentifierString.Substring(0, 4), out int year)
|
||||||
|
|| !int.TryParse(applicationIdentifierString.Substring(4, 2), out int month)
|
||||||
|
|| !int.TryParse(applicationIdentifierString.Substring(6, 2), out int day)
|
||||||
|
|| !int.TryParse(applicationIdentifierString.Substring(8, 6), out int extraTime))
|
||||||
|
#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";
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
||||||
{
|
{
|
||||||
@@ -49,7 +134,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the .data/DATA section strings, if they exist
|
// Get the .data/DATA section strings, if they exist
|
||||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
if (strs.Exists(s => s.Contains("\\SETTEC")))
|
if (strs.Exists(s => s.Contains("\\SETTEC")))
|
||||||
return "Alpha-ROM";
|
return "Alpha-ROM";
|
||||||
@@ -60,7 +145,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the .rdata section strings, if they exist
|
// Get the .rdata section strings, if they exist
|
||||||
strs = exe.GetFirstSectionStrings(".rdata");
|
strs = exe.GetFirstSectionStrings(".rdata");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
if (strs.Exists(s => s.Contains("This Game is Japan Only")))
|
if (strs.Exists(s => s.Contains("This Game is Japan Only")))
|
||||||
return "Alpha-ROM";
|
return "Alpha-ROM";
|
||||||
@@ -75,7 +160,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the overlay data, if it exists
|
// Get the overlay data, if it exists
|
||||||
if (exe.OverlayStrings != null)
|
if (exe.OverlayStrings is not null)
|
||||||
{
|
{
|
||||||
// Found in Redump entry 84122.
|
// Found in Redump entry 84122.
|
||||||
if (exe.OverlayStrings.Exists(s => s.Contains("SETTEC0000")))
|
if (exe.OverlayStrings.Exists(s => s.Contains("SETTEC0000")))
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
{
|
{
|
||||||
// Get the section strings, if they exist
|
// Get the section strings, if they exist
|
||||||
var strs = exe.GetFirstSectionStrings(sectionName);
|
var strs = exe.GetFirstSectionStrings(sectionName);
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
if (strs.Exists(s => s.Contains("ARMDEBUG")))
|
if (strs.Exists(s => s.Contains("ARMDEBUG")))
|
||||||
return "Armadillo";
|
return "Armadillo";
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the .data/DATA section strings, if they exist
|
// Get the .data/DATA section strings, if they exist
|
||||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
// Found in "LineRider2.exe" in Redump entry 6236
|
// Found in "LineRider2.exe" in Redump entry 6236
|
||||||
if (strs.Exists(s => s.OptionalContains("ByteShield")))
|
if (strs.Exists(s => s.OptionalContains("ByteShield")))
|
||||||
@@ -98,7 +98,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the .rdata section strings, if they exist
|
// Get the .rdata section strings, if they exist
|
||||||
strs = exe.GetFirstSectionStrings(".rdata");
|
strs = exe.GetFirstSectionStrings(".rdata");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
// Found in "ByteShield.dll" in Redump entry 6236
|
// Found in "ByteShield.dll" in Redump entry 6236
|
||||||
if (strs.Exists(s => s.OptionalContains("Byte|Shield")))
|
if (strs.Exists(s => s.OptionalContains("Byte|Shield")))
|
||||||
@@ -115,7 +115,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the .ret section strings, if they exist
|
// Get the .ret section strings, if they exist
|
||||||
strs = exe.GetFirstSectionStrings(".ret");
|
strs = exe.GetFirstSectionStrings(".ret");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
// TODO: Figure out if this specifically indicates if the file is encrypted
|
// TODO: Figure out if this specifically indicates if the file is encrypted
|
||||||
// Found in "LineRider2.bbz" in Redump entry 6236
|
// Found in "LineRider2.bbz" in Redump entry 6236
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using SabreTools.IO.Extensions;
|
|||||||
using SabreTools.IO.Matching;
|
using SabreTools.IO.Matching;
|
||||||
using SabreTools.Serialization.Wrappers;
|
using SabreTools.Serialization.Wrappers;
|
||||||
|
|
||||||
|
#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'
|
||||||
namespace BinaryObjectScanner.Protection
|
namespace BinaryObjectScanner.Protection
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -72,8 +73,9 @@ namespace BinaryObjectScanner.Protection
|
|||||||
public string? CheckExecutable(string file, NewExecutable exe, bool includeDebug)
|
public string? CheckExecutable(string file, NewExecutable exe, bool includeDebug)
|
||||||
{
|
{
|
||||||
// TODO: Don't read entire file
|
// TODO: Don't read entire file
|
||||||
|
#pragma warning disable CS0618
|
||||||
byte[]? data = exe.ReadArbitraryRange();
|
byte[]? data = exe.ReadArbitraryRange();
|
||||||
if (data == null)
|
if (data is null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// TODO: Figure out what NE section this lives in
|
// TODO: Figure out what NE section this lives in
|
||||||
@@ -120,11 +122,11 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the resident and non-resident name table strings
|
// Get the resident and non-resident name table strings
|
||||||
var nrntStrs = Array.ConvertAll(exe.NonResidentNameTable ?? [],
|
var nrntStrs = Array.ConvertAll(exe.NonResidentNameTable ?? [],
|
||||||
nrnte => nrnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(nrnte.NameString));
|
nrnte => nrnte?.NameString is null ? string.Empty : Encoding.ASCII.GetString(nrnte.NameString));
|
||||||
|
|
||||||
// Check the imported-name table
|
// Check the imported-name table
|
||||||
// Found in "h3blade.exe" in Redump entry 85077.
|
// Found in "h3blade.exe" in Redump entry 85077.
|
||||||
if (exe.ImportedNameTable != null)
|
if (exe.ImportedNameTable is not null)
|
||||||
{
|
{
|
||||||
foreach (var inte in exe.ImportedNameTable.Values)
|
foreach (var inte in exe.ImportedNameTable.Values)
|
||||||
{
|
{
|
||||||
@@ -149,7 +151,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
||||||
{
|
{
|
||||||
// Get the stub executable data, if it exists
|
// Get the stub executable data, if it exists
|
||||||
if (exe.StubExecutableData != null)
|
if (exe.StubExecutableData is not null)
|
||||||
{
|
{
|
||||||
var matchers = new List<ContentMatchSet>
|
var matchers = new List<ContentMatchSet>
|
||||||
{
|
{
|
||||||
@@ -181,10 +183,10 @@ namespace BinaryObjectScanner.Protection
|
|||||||
// This contains the version section that the Content Check looked for. There are likely other sections
|
// This contains the version section that the Content Check looked for. There are likely other sections
|
||||||
// that may contain it. Update when more are found.
|
// that may contain it. Update when more are found.
|
||||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
var match = strs.Find(s => s.Contains(" ver. ") && (s.Contains("CD-Cops, ") || s.Contains("DVD-Cops, ")));
|
var match = strs.Find(s => s.Contains(" ver. ") && (s.Contains("CD-Cops, ") || s.Contains("DVD-Cops, ")));
|
||||||
if (match != null)
|
if (match is not null)
|
||||||
if (match.Contains("CD-Cops"))
|
if (match.Contains("CD-Cops"))
|
||||||
return $"CD-Cops {GetVersionString(match)}";
|
return $"CD-Cops {GetVersionString(match)}";
|
||||||
else if (match.Contains("DVD-Cops"))
|
else if (match.Contains("DVD-Cops"))
|
||||||
@@ -257,7 +259,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
private static string? GetVersion(string file, byte[]? fileContent, List<int> positions)
|
private static string? GetVersion(string file, byte[]? fileContent, List<int> positions)
|
||||||
{
|
{
|
||||||
// If we have no content
|
// If we have no content
|
||||||
if (fileContent == null)
|
if (fileContent is null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
string version = Encoding.ASCII.GetString(fileContent, positions[0] + 15, 4);
|
string version = Encoding.ASCII.GetString(fileContent, positions[0] + 15, 4);
|
||||||
@@ -272,7 +274,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
// Full string ends with # (i.e. "CD-Cops, ver. 1.72, #"), use that to compensate for comma in version
|
// 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, #"
|
// 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?
|
// 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)
|
if (versionMatch.Success)
|
||||||
return versionMatch.Value;
|
return versionMatch.Value;
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
// TODO: Investigate the numerous ".guard" sections present in "Randevu.exe" in Redump entry 97142.
|
// TODO: Investigate the numerous ".guard" sections present in "Randevu.exe" in Redump entry 97142.
|
||||||
|
|
||||||
// Get the export directory table
|
// Get the export directory table
|
||||||
if (exe.ExportDirectoryTable != null)
|
if (exe.ExportDirectoryTable is not null)
|
||||||
{
|
{
|
||||||
// Found in "cdguard.dll" in Redump entry 97142 and IA item "pahgeby-he3hakomkou".
|
// Found in "cdguard.dll" in Redump entry 97142 and IA item "pahgeby-he3hakomkou".
|
||||||
bool match = exe.ExportDirectoryTable.Name.OptionalEquals("cdguard.dll", StringComparison.OrdinalIgnoreCase);
|
bool match = exe.ExportDirectoryTable.Name.OptionalEquals("cdguard.dll", StringComparison.OrdinalIgnoreCase);
|
||||||
@@ -38,10 +38,10 @@ namespace BinaryObjectScanner.Protection
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the import directory table
|
// Get the import directory table
|
||||||
if (exe.ImportDirectoryTable != null)
|
if (exe.ImportDirectoryTable is not null)
|
||||||
{
|
{
|
||||||
// Found in "Randevu.exe" in Redump entry 97142.
|
// Found in "Randevu.exe" in Redump entry 97142.
|
||||||
bool match = Array.Exists(exe.ImportDirectoryTable, idte => idte?.Name != null && idte.Name.Equals("cdguard.dll", StringComparison.OrdinalIgnoreCase));
|
bool match = Array.Exists(exe.ImportDirectoryTable, idte => idte?.Name is not null && idte.Name.Equals("cdguard.dll", StringComparison.OrdinalIgnoreCase));
|
||||||
if (match)
|
if (match)
|
||||||
return "CD-Guard Copy Protection System";
|
return "CD-Guard Copy Protection System";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
{
|
{
|
||||||
// Get the .data/DATA section, if it exists
|
// Get the .data/DATA section, if it exists
|
||||||
var dataSectionRaw = exe.GetFirstSectionData(".data") ?? exe.GetFirstSectionData("DATA");
|
var dataSectionRaw = exe.GetFirstSectionData(".data") ?? exe.GetFirstSectionData("DATA");
|
||||||
if (dataSectionRaw != null)
|
if (dataSectionRaw is not null)
|
||||||
{
|
{
|
||||||
var matchers = new List<ContentMatchSet>
|
var matchers = new List<ContentMatchSet>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
{
|
{
|
||||||
// TODO: Indicates Hypertech Crack Proof as well?
|
// TODO: Indicates Hypertech Crack Proof as well?
|
||||||
//// Get the import directory table
|
//// Get the import directory table
|
||||||
//if (exe.ImportDirectoryTable != null)
|
//if (exe.ImportDirectoryTable is not null)
|
||||||
//{
|
//{
|
||||||
// bool match = exe.ImportDirectoryTable.Any(idte => idte.Name == "KeRnEl32.dLl");
|
// bool match = exe.ImportDirectoryTable.Any(idte => idte.Name == "KeRnEl32.dLl");
|
||||||
// if (match)
|
// if (match)
|
||||||
@@ -19,7 +19,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the code/CODE section strings, if they exist
|
// Get the code/CODE section strings, if they exist
|
||||||
var strs = exe.GetFirstSectionStrings("code") ?? exe.GetFirstSectionStrings("CODE");
|
var strs = exe.GetFirstSectionStrings("code") ?? exe.GetFirstSectionStrings("CODE");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
if (strs.Exists(s => s.Contains("~0017.tmp")))
|
if (strs.Exists(s => s.Contains("~0017.tmp")))
|
||||||
return "CDSHiELD SE";
|
return "CDSHiELD SE";
|
||||||
|
|||||||
9322
BinaryObjectScanner/Protection/CEG.Constants.cs
Normal file
9322
BinaryObjectScanner/Protection/CEG.Constants.cs
Normal file
File diff suppressed because it is too large
Load Diff
147
BinaryObjectScanner/Protection/CEG.cs
Normal file
147
BinaryObjectScanner/Protection/CEG.cs
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
using BinaryObjectScanner.Interfaces;
|
||||||
|
using SabreTools.IO.Extensions;
|
||||||
|
using SabreTools.Serialization.Wrappers;
|
||||||
|
|
||||||
|
namespace BinaryObjectScanner.Protection
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Protection that used to be offered by Valve for games on Steam. By default, protected executables are "stripped"
|
||||||
|
/// of varying 4KiB "strips", and these "strips" would only be downloaded when the user attempted to run the game on
|
||||||
|
/// Steam.
|
||||||
|
/// </summary>
|
||||||
|
public partial class CEG : IExecutableCheck<PortableExecutable>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// General info on the contents of a CEG executable, as pertaining to detection.
|
||||||
|
/// CEG executables should have 3 resources in .rsrc: STEAM_GUIDD, STEAM_MINSTANCE, and STEAM_SPLIT_GUID.
|
||||||
|
/// STEAM_GUIDD's meaning is unknown, as it remains largely consistent within a depot, but not the whole time,
|
||||||
|
/// and the same one will often show up across a few different unrelated depots. It's required along with split
|
||||||
|
/// GUID to request strips from Steam's servers, so it might be some kind of specific server identifier.
|
||||||
|
/// STEAM_MINSTANCE identifies a personalized executable that contains strips (and is all 0x00 if the executable is stripped)
|
||||||
|
/// STEAM_SPLIT_GUID identifies a specific build of that particular executable.
|
||||||
|
/// Some cracked versions of games are known to 0x00 out the data in all 3, but still keep them there.
|
||||||
|
/// There's also one edge case with a manifest for depotID 246581 where they're all 0x00, but this one might not
|
||||||
|
/// be active anyways.
|
||||||
|
///
|
||||||
|
/// All* CEG executables contain a .version section (virtual size 4, physical size 512) that begins with 4 bytes
|
||||||
|
/// identifying some kind of version, and the rest is all 0x00. This is not parsed or output since it's
|
||||||
|
/// specifically the version of the static library the executable was compiled against, which doesn't mean much,
|
||||||
|
/// and since there are CEG v1/v2/v3 functions, which *do* have significance, this would likely just create confusion.
|
||||||
|
/// Unfortunately, it is not feasible to parse v1/v2/v3 functions in BOS anyways, at least not at the moment.
|
||||||
|
/// *The only exceptions to this are some (but not all) versions of Company of Heroes 2 (depot ID 231431), as
|
||||||
|
/// well as Football Manager 2013 (depot IDs 207892, 216532, 216552, 216572, 216592, 216612, 220502, likely more)
|
||||||
|
/// use StarForce (ProActive? or maybe just packing/encryption/antitamper?), and this seems to strip the .version
|
||||||
|
/// section. Currently not checked if the version just wound up somewhere else.
|
||||||
|
///
|
||||||
|
/// All CEG executables contain the strings "STEAMSTART" and "STEAM_DRM_IPC" in the .rdata section.
|
||||||
|
/// Additionally, the .rdata section will either contain the string "This file has been stripped" if the executable
|
||||||
|
/// is stripped, or contain the string "This file contains strips" if the executable contains strips.
|
||||||
|
/// </summary>
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
||||||
|
{
|
||||||
|
string[] lookupValues = ["STEAM_GUIDD", "STEAM_MINSTANCE", "STEAM_SPLIT_GUID"];
|
||||||
|
string[] returnedGuids = ["NOTHING", "NOTHING", "NOTHING"];
|
||||||
|
int localOffset = 0;
|
||||||
|
for (int i = 0; i < lookupValues.Length; i++)
|
||||||
|
{
|
||||||
|
var resourceDataList = exe.FindResourceByNamedType(lookupValues[i]);
|
||||||
|
if (resourceDataList.Count <= 0)
|
||||||
|
{
|
||||||
|
// The .version section should always be present, besides the two aforementioned games that use
|
||||||
|
// StarForce on top of CEG. If an executable contains a .version section, it almost certainly has
|
||||||
|
// CEG.
|
||||||
|
if (exe.ContainsSection(".version"))
|
||||||
|
return "CEG - Unable to parse resources, please report to us on GitHub!";
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var resourceData = resourceDataList[0];
|
||||||
|
if (resourceData != null)
|
||||||
|
returnedGuids[i] = resourceData.ReadGuid(ref localOffset).ToString();
|
||||||
|
|
||||||
|
localOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
string steamGuid = returnedGuids[0].ToUpperInvariant();
|
||||||
|
string steamMInstance = returnedGuids[1].ToUpperInvariant();
|
||||||
|
string steamSplitGuid = returnedGuids[2].ToUpperInvariant();
|
||||||
|
uint timestamp = exe.COFFFileHeader.TimeDateStamp;
|
||||||
|
|
||||||
|
const string zeroGUID = "00000000-0000-0000-0000-000000000000";
|
||||||
|
|
||||||
|
// If steam M instance is all 0x00, either the executable is stripped or it was tampered with.
|
||||||
|
if (steamMInstance == zeroGUID)
|
||||||
|
{
|
||||||
|
// If the steam guid or the steam split guid are all 0x00, the executable is almost certainly
|
||||||
|
// tampered. Tampered executables are also desired, though, which is why it's reported.
|
||||||
|
// There's also one edge case with a manifest for depotID 246581 where they're all 0x00, but this one
|
||||||
|
// might not active anyways, and is a pretty major edge case
|
||||||
|
if (steamGuid == zeroGUID || steamSplitGuid == zeroGUID)
|
||||||
|
{
|
||||||
|
// If for whatever reason only the steam guid is zeroed out, the Steam Split Guid can still be
|
||||||
|
// used to look up the executable.
|
||||||
|
if (steamSplitGuid != zeroGUID)
|
||||||
|
{
|
||||||
|
if (CEGDictionary.TryGetValue(steamSplitGuid, out string? tamperedName))
|
||||||
|
return $"CEG - Possibly tampered - {tamperedName} {ReportHelper(steamSplitGuid)}";
|
||||||
|
|
||||||
|
return "CEG - Unknown manifest, please report to us on GitHub!";
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it's tampered and the steam split guid is zeroed out, the compilation timestamp needs to be
|
||||||
|
// used as a less precise fallback.
|
||||||
|
if (CEGBackupDictionary.TryGetValue(timestamp, out string[]? lookupGuids))
|
||||||
|
{
|
||||||
|
string returnString = "CEG - Possibly tampered, potentially";
|
||||||
|
for (int i = 0; i < lookupGuids.Length; i++)
|
||||||
|
{
|
||||||
|
string lookupGuid = lookupGuids[i];
|
||||||
|
if (CEGDictionary.TryGetValue(lookupGuid, out string? lookedUpName))
|
||||||
|
{
|
||||||
|
returnString = $"{returnString} {lookedUpName} {ReportHelper(lookupGuid)}";
|
||||||
|
if (i + 1 == lookupGuids.Length)
|
||||||
|
break;
|
||||||
|
|
||||||
|
returnString = $"{returnString} or";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnString;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it still can't be matched to anything, it's an unknown manifest.
|
||||||
|
return "CEG - Unknown manifest, please report to us on GitHub!";
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the steam M instance is all 0x00 but the other values are not, the executable is stripped.
|
||||||
|
// Some tampered executables may still wind up here, but there's only so much that can be done to
|
||||||
|
// compensate for tampering.
|
||||||
|
if (CEGDictionary.TryGetValue(steamSplitGuid, out string? strippedName))
|
||||||
|
return $"CEG - Stripped - {strippedName}";
|
||||||
|
else
|
||||||
|
return "CEG - Unknown manifest, please report to us on GitHub!";
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the steam M instance is not all 0x00, it has strips.
|
||||||
|
if (CEGDictionary.TryGetValue(steamSplitGuid, out string? name))
|
||||||
|
return $"CEG - Contains Strips - {name} {ReportHelper(steamSplitGuid)}";
|
||||||
|
else
|
||||||
|
return "CEG - Unknown manifest, please report to us on GitHub!";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a given steam split guid is in the dictionary already to determine if reporting is desired.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="steamSplitGuid">Steam split GUID</param>
|
||||||
|
/// <returns>A string about reporting on GitHub if not found, otherwise returns null.</returns>
|
||||||
|
private static string? ReportHelper(string steamSplitGuid)
|
||||||
|
{
|
||||||
|
if (!HaveStrips.Contains(steamSplitGuid))
|
||||||
|
return "- Please report to us on GitHub!";
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ using BinaryObjectScanner.Interfaces;
|
|||||||
using SabreTools.IO;
|
using SabreTools.IO;
|
||||||
using SabreTools.IO.Matching;
|
using SabreTools.IO.Matching;
|
||||||
|
|
||||||
|
#pragma warning disable IDE0230 // Use UTF-8 string literal
|
||||||
namespace BinaryObjectScanner.Protection
|
namespace BinaryObjectScanner.Protection
|
||||||
{
|
{
|
||||||
public class CactusDataShield : IContentCheck
|
public class CactusDataShield : IContentCheck
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
||||||
{
|
{
|
||||||
// Get the export directory table
|
// Get the export directory table
|
||||||
if (exe.ExportDirectoryTable != null)
|
if (exe.ExportDirectoryTable is not null)
|
||||||
{
|
{
|
||||||
// Found in "cenega.dll" in IA item "speed-pack".
|
// Found in "cenega.dll" in IA item "speed-pack".
|
||||||
bool match = exe.ExportDirectoryTable.Name.OptionalEquals("ProtectDVD.dll", StringComparison.OrdinalIgnoreCase);
|
bool match = exe.ExportDirectoryTable.Name.OptionalEquals("ProtectDVD.dll", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the .text section strings, if they exist
|
// Get the .text section strings, if they exist
|
||||||
var strs = exe.GetFirstSectionStrings(".text");
|
var strs = exe.GetFirstSectionStrings(".text");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
if (strs.Exists(s => s.Contains("CODE-LOCK.OCX")))
|
if (strs.Exists(s => s.Contains("CODE-LOCK.OCX")))
|
||||||
return "ChosenBytes Code-Lock";
|
return "ChosenBytes Code-Lock";
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using BinaryObjectScanner.Interfaces;
|
using BinaryObjectScanner.Interfaces;
|
||||||
|
using SabreTools.Data.Models.ISO9660;
|
||||||
|
using SabreTools.IO.Extensions;
|
||||||
using SabreTools.Serialization.Wrappers;
|
using SabreTools.Serialization.Wrappers;
|
||||||
|
|
||||||
namespace BinaryObjectScanner.Protection
|
namespace BinaryObjectScanner.Protection
|
||||||
@@ -20,8 +22,88 @@ namespace BinaryObjectScanner.Protection
|
|||||||
///
|
///
|
||||||
/// COPYLOK trademark: https://www.trademarkelite.com/europe/trademark/trademark-detail/000618512/COPYLOK.
|
/// COPYLOK trademark: https://www.trademarkelite.com/europe/trademark/trademark-detail/000618512/COPYLOK.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CopyLok : IExecutableCheck<PortableExecutable>
|
public class CopyLok : IDiskImageCheck<ISO9660>, IExecutableCheck<PortableExecutable>
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public string? CheckDiskImage(string file, ISO9660 diskImage, bool includeDebug)
|
||||||
|
{
|
||||||
|
if (diskImage.VolumeDescriptorSet.Length == 0)
|
||||||
|
return null;
|
||||||
|
if (diskImage.VolumeDescriptorSet[0] is not PrimaryVolumeDescriptor pvd)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!FileType.ISO9660.NoteworthyApplicationUse(pvd))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (FileType.ISO9660.NoteworthyReserved653Bytes(pvd))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
#region Read Application Use
|
||||||
|
|
||||||
|
var applicationUse = pvd.ApplicationUse;
|
||||||
|
uint constantValueOne = applicationUse.ReadUInt32LittleEndian(ref offset);
|
||||||
|
ushort smallSizeBytes = applicationUse.ReadUInt16LittleEndian(ref offset);
|
||||||
|
ushort constantValueTwo = applicationUse.ReadUInt16LittleEndian(ref offset);
|
||||||
|
uint finalSectionOneBytes = applicationUse.ReadUInt32LittleEndian(ref offset);
|
||||||
|
byte zeroByte = applicationUse.ReadByte(ref offset);
|
||||||
|
ushort earlyCopyLokBytesOne = applicationUse.ReadUInt16LittleEndian(ref offset);
|
||||||
|
ushort pairBytesOne = applicationUse.ReadUInt16LittleEndian(ref offset);
|
||||||
|
uint oneValueBytes = applicationUse.ReadUInt32LittleEndian(ref offset);
|
||||||
|
uint earlyCopyLokBytesTwo = applicationUse.ReadUInt32LittleEndian(ref offset);
|
||||||
|
uint pairBytesTwo = applicationUse.ReadUInt32LittleEndian(ref offset);
|
||||||
|
var endingZeroBytes = applicationUse.ReadBytes(ref offset, 483);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Main Checks
|
||||||
|
|
||||||
|
// Early return if the rest of the AU data isn't 0x00
|
||||||
|
if (!Array.TrueForAll(endingZeroBytes, b => b == 0x00))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Check first currently-observed constant value
|
||||||
|
if (constantValueOne != 0x4ED38AE1)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Check for early variant copylok
|
||||||
|
if (earlyCopyLokBytesOne == 0x00)
|
||||||
|
{
|
||||||
|
// Redump ID 35908, 56433, 44526
|
||||||
|
if (pairBytesOne == 0 && oneValueBytes == 0 && earlyCopyLokBytesTwo == 0 && pairBytesTwo == 0)
|
||||||
|
return "CopyLok / CodeLok (Early, ~1850 errors)";
|
||||||
|
|
||||||
|
return "CopyLok / CodeLok - Unknown variant, please report to us on GitHub!";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check remaining currently-observed constant values
|
||||||
|
if (constantValueTwo != 0x4ED3 || zeroByte != 0x00 || earlyCopyLokBytesOne != 0x0C76 || oneValueBytes != 0x00000001)
|
||||||
|
return "CopyLok / CodeLok - Unknown variant, please report to us on GitHub!";
|
||||||
|
|
||||||
|
// Always 0xD1AD, except in Redump ID 71985 (the only sample) where it's 0x6999
|
||||||
|
// Update number be more accurate if more samples are acquired.
|
||||||
|
if (smallSizeBytes < 0xADD1)
|
||||||
|
return "CopyLok / CodeLok (Less errors, ~255)";
|
||||||
|
|
||||||
|
if (pairBytesOne == 0x9425)
|
||||||
|
{
|
||||||
|
// Redump ID 37860, 37881, 38239, 100685, 108375
|
||||||
|
if (pairBytesTwo != 0x00000000)
|
||||||
|
return "CopyLok / CodeLok (Pair errors, ~1500)";
|
||||||
|
|
||||||
|
return "CopyLok / CodeLok - Unknown variant, please report to us on GitHub!";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redump ID 31557, 44210, 49087, 72183, 31675
|
||||||
|
if (pairBytesOne == 0xF3ED && pairBytesTwo == 0x00000000)
|
||||||
|
return "CopyLok / CodeLok (Solo errors, ~775)";
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
return "CopyLok / CodeLok - Unknown variant, please report to us on GitHub!";
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
// Checks for Professional
|
// Checks for Professional
|
||||||
// PEX checks intentionally only detect Professional
|
// PEX checks intentionally only detect Professional
|
||||||
|
|
||||||
if (exe.OverlayStrings != null)
|
if (exe.OverlayStrings is not null)
|
||||||
{
|
{
|
||||||
// Checks if main executable contains reference to optgraph.dll.
|
// 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
|
// This might be better removed later, as Redump ID 82475 is a false positive, and also doesn't actually
|
||||||
@@ -76,7 +76,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
}
|
}
|
||||||
|
|
||||||
var strs = exe.GetFirstSectionStrings(".rdata");
|
var strs = exe.GetFirstSectionStrings(".rdata");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
// Samples: Redump ID 82475, German Emergency 2 Deluxe, Redump ID 48393
|
// Samples: Redump ID 82475, German Emergency 2 Deluxe, Redump ID 48393
|
||||||
if (strs.Exists(s => s.Contains("optgraph.dll")))
|
if (strs.Exists(s => s.Contains("optgraph.dll")))
|
||||||
@@ -90,7 +90,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
public List<string> CheckDirectoryPath(string path, List<string>? files)
|
public List<string> CheckDirectoryPath(string path, List<string>? files)
|
||||||
{
|
{
|
||||||
var protections = new List<string>();
|
var protections = new List<string>();
|
||||||
if (files == null)
|
if (files is null)
|
||||||
return protections;
|
return protections;
|
||||||
|
|
||||||
// Checks for Light
|
// Checks for Light
|
||||||
@@ -110,7 +110,11 @@ namespace BinaryObjectScanner.Protection
|
|||||||
{
|
{
|
||||||
lightFiles = fileList.FindAll(f =>
|
lightFiles = fileList.FindAll(f =>
|
||||||
{
|
{
|
||||||
|
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||||
|
f = f[path.Length..];
|
||||||
|
#else
|
||||||
f = f.Remove(0, path.Length);
|
f = f.Remove(0, path.Length);
|
||||||
|
#endif
|
||||||
f = f.TrimStart('/', '\\');
|
f = f.TrimStart('/', '\\');
|
||||||
return f.StartsWith(dir + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase);
|
return f.StartsWith(dir + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase);
|
||||||
});
|
});
|
||||||
@@ -120,7 +124,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((lightFiles != null) && (lightFiles.Count > 0))
|
if ((lightFiles is not null) && (lightFiles.Count > 0))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
{
|
{
|
||||||
// Get the code/CODE section strings, if they exist
|
// Get the code/CODE section strings, if they exist
|
||||||
var strs = exe.GetFirstSectionStrings("code") ?? exe.GetFirstSectionStrings("CODE");
|
var strs = exe.GetFirstSectionStrings("code") ?? exe.GetFirstSectionStrings("CODE");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
// Found in "NECRO95.EXE" in IA item "NBECRORV11".
|
// Found in "NECRO95.EXE" in IA item "NBECRORV11".
|
||||||
// Full string:
|
// Full string:
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
{
|
{
|
||||||
// Get the .text section, if it exists
|
// Get the .text section, if it exists
|
||||||
var textData = exe.GetFirstSectionData(".text");
|
var textData = exe.GetFirstSectionData(".text");
|
||||||
if (textData != null)
|
if (textData is not null)
|
||||||
{
|
{
|
||||||
var matchers = new List<ContentMatchSet>
|
var matchers = new List<ContentMatchSet>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
public List<string> CheckDirectoryPath(string path, List<string>? files)
|
public List<string> CheckDirectoryPath(string path, List<string>? files)
|
||||||
{
|
{
|
||||||
var protections = new List<string>();
|
var protections = new List<string>();
|
||||||
if (files == null)
|
if (files is null)
|
||||||
return protections;
|
return protections;
|
||||||
|
|
||||||
if (Directory.Exists(Path.Combine(path, "VIDEO_TS")))
|
if (Directory.Exists(Path.Combine(path, "VIDEO_TS")))
|
||||||
@@ -20,10 +20,14 @@ namespace BinaryObjectScanner.Protection
|
|||||||
for (int i = 0; i < bupfiles.Count; i++)
|
for (int i = 0; i < bupfiles.Count; i++)
|
||||||
{
|
{
|
||||||
var bupfile = new FileInfo(bupfiles[i]);
|
var bupfile = new FileInfo(bupfiles[i]);
|
||||||
if (bupfile.DirectoryName == null)
|
if (bupfile.DirectoryName is null)
|
||||||
continue;
|
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");
|
string ifofile = Path.Combine(bupfile.DirectoryName, bupfile.Name.Substring(0, bupfile.Name.Length - bupfile.Extension.Length) + ".ifo");
|
||||||
|
#endif
|
||||||
if (bupfile.Length != ifofile.FileSize())
|
if (bupfile.Length != ifofile.FileSize())
|
||||||
{
|
{
|
||||||
protections.Add("DVD-Movie-PROTECT (Unconfirmed - Please report to us on Github)");
|
protections.Add("DVD-Movie-PROTECT (Unconfirmed - Please report to us on Github)");
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using SabreTools.IO.Matching;
|
|||||||
using SabreTools.Serialization.Wrappers;
|
using SabreTools.Serialization.Wrappers;
|
||||||
using OHMN = SabreTools.Data.Models.COFF.OptionalHeaderMagicNumber;
|
using OHMN = SabreTools.Data.Models.COFF.OptionalHeaderMagicNumber;
|
||||||
|
|
||||||
|
#pragma warning disable IDE0230 // Use UTF-8 string literal
|
||||||
namespace BinaryObjectScanner.Protection
|
namespace BinaryObjectScanner.Protection
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -63,7 +64,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
// https://github.com/horsicq/Detect-It-Easy/blob/master/db/PE/_denuvoComplete.2.sg
|
// https://github.com/horsicq/Detect-It-Easy/blob/master/db/PE/_denuvoComplete.2.sg
|
||||||
|
|
||||||
// Denuvo Protector
|
// Denuvo Protector
|
||||||
if (exe.OptionalHeader?.Magic == OHMN.PE32Plus && exe.EntryPointData != null)
|
if (exe.OptionalHeader?.Magic == OHMN.PE32Plus && exe.EntryPointData is not null)
|
||||||
{
|
{
|
||||||
byte?[] denuvoProtector =
|
byte?[] denuvoProtector =
|
||||||
[
|
[
|
||||||
@@ -102,12 +103,11 @@ namespace BinaryObjectScanner.Protection
|
|||||||
// Mad Max, Metal Gear Solid: TPP, Rise of the Tomb Raider
|
// Mad Max, Metal Gear Solid: TPP, Rise of the Tomb Raider
|
||||||
new(
|
new(
|
||||||
new ContentMatch(
|
new ContentMatch(
|
||||||
new byte?[]
|
[
|
||||||
{
|
|
||||||
0x51, 0x52, 0x41, 0x50, 0x41, 0x51, 0x4C, 0x8D,
|
0x51, 0x52, 0x41, 0x50, 0x41, 0x51, 0x4C, 0x8D,
|
||||||
null, null, null, null, null, 0x4C, 0x8D, null,
|
null, null, null, null, null, 0x4C, 0x8D, null,
|
||||||
null, null, null, null, 0x4D, 0x29, 0xC1,
|
null, null, null, null, 0x4D, 0x29, 0xC1,
|
||||||
},
|
],
|
||||||
end: 0
|
end: 0
|
||||||
),
|
),
|
||||||
"Denuvo v1.0 (x64)"),
|
"Denuvo v1.0 (x64)"),
|
||||||
@@ -115,11 +115,10 @@ namespace BinaryObjectScanner.Protection
|
|||||||
// Lords of the Fallen, Batman: AK, Just Cause 3, Sherlock Holmes: TdD, Tales of Berseria etc
|
// Lords of the Fallen, Batman: AK, Just Cause 3, Sherlock Holmes: TdD, Tales of Berseria etc
|
||||||
new(
|
new(
|
||||||
new ContentMatch(
|
new ContentMatch(
|
||||||
new byte?[]
|
[
|
||||||
{
|
|
||||||
0x48, 0x8D, 0x0D, null, null, null, null, 0xE9,
|
0x48, 0x8D, 0x0D, null, null, null, null, 0xE9,
|
||||||
null, null, null, null,
|
null, null, null, null,
|
||||||
},
|
],
|
||||||
end: 0
|
end: 0
|
||||||
),
|
),
|
||||||
"Denuvo v2.0a (x64)"),
|
"Denuvo v2.0a (x64)"),
|
||||||
@@ -127,13 +126,12 @@ namespace BinaryObjectScanner.Protection
|
|||||||
// Yesterday Origins
|
// Yesterday Origins
|
||||||
new(
|
new(
|
||||||
new ContentMatch(
|
new ContentMatch(
|
||||||
new byte?[]
|
[
|
||||||
{
|
|
||||||
0x48, 0x89, null, null, null, null, null, 0x48,
|
0x48, 0x89, null, null, null, null, null, 0x48,
|
||||||
0x89, null, null, null, null, null, 0x4C, 0x89,
|
0x89, null, null, null, null, null, 0x4C, 0x89,
|
||||||
null, null, null, null, null, 0x4C, 0x89, null,
|
null, null, null, null, null, 0x4C, 0x89, null,
|
||||||
null, null, null, null, 0x48, 0x83, 0xFA, 0x01,
|
null, null, null, null, 0x48, 0x83, 0xFA, 0x01,
|
||||||
},
|
],
|
||||||
end: 0
|
end: 0
|
||||||
),
|
),
|
||||||
"Denuvo v2.0b (x64)"),
|
"Denuvo v2.0b (x64)"),
|
||||||
@@ -141,11 +139,10 @@ namespace BinaryObjectScanner.Protection
|
|||||||
// Sniper Ghost Warrior 3 (beta), Dead Rising 4 (SteamStub-free)
|
// Sniper Ghost Warrior 3 (beta), Dead Rising 4 (SteamStub-free)
|
||||||
new(
|
new(
|
||||||
new ContentMatch(
|
new ContentMatch(
|
||||||
new byte?[]
|
[
|
||||||
{
|
|
||||||
null, null, null, null, null, null, null, null,
|
null, null, null, null, null, null, null, null,
|
||||||
0x4C, 0x89, 0x1C, 0x24, 0x49, 0x89, 0xE3,
|
0x4C, 0x89, 0x1C, 0x24, 0x49, 0x89, 0xE3,
|
||||||
},
|
],
|
||||||
end: 0
|
end: 0
|
||||||
),
|
),
|
||||||
"Denuvo v3.0a (x64)"),
|
"Denuvo v3.0a (x64)"),
|
||||||
@@ -153,13 +150,12 @@ namespace BinaryObjectScanner.Protection
|
|||||||
// Train Sim World CSX Heavy Haul
|
// Train Sim World CSX Heavy Haul
|
||||||
new(
|
new(
|
||||||
new ContentMatch(
|
new ContentMatch(
|
||||||
new byte?[]
|
[
|
||||||
{
|
|
||||||
0x4D, 0x8D, null, null, null, null, null, null,
|
0x4D, 0x8D, null, null, null, null, null, null,
|
||||||
null, null, null, 0x48, 0x89, null, null, null,
|
null, null, null, 0x48, 0x89, null, null, null,
|
||||||
null, null, 0x48, 0x8D, null, null, 0x48, 0x89,
|
null, null, 0x48, 0x8D, null, null, 0x48, 0x89,
|
||||||
null, 0x48, 0x89, null, 0x48, 0x89,
|
null, 0x48, 0x89, null, 0x48, 0x89,
|
||||||
},
|
],
|
||||||
end: 0
|
end: 0
|
||||||
),
|
),
|
||||||
"Denuvo v3.0b (x64)"),
|
"Denuvo v3.0b (x64)"),
|
||||||
@@ -207,13 +203,12 @@ namespace BinaryObjectScanner.Protection
|
|||||||
// Pro Evolution Soccer 2017, Champions of Anteria
|
// Pro Evolution Soccer 2017, Champions of Anteria
|
||||||
new(
|
new(
|
||||||
new ContentMatch(
|
new ContentMatch(
|
||||||
new byte?[]
|
[
|
||||||
{
|
|
||||||
0x55, 0x89, 0xE5, 0x8D, null, null, null, null,
|
0x55, 0x89, 0xE5, 0x8D, null, null, null, null,
|
||||||
null, null, 0xE8, null, null, null, null, 0xE8,
|
null, null, 0xE8, null, null, null, null, 0xE8,
|
||||||
null, null, null, null, 0xE8, null, null, null,
|
null, null, null, null, 0xE8, null, null, null,
|
||||||
null, 0xE8, null, null, null, null,
|
null, 0xE8, null, null, null, null,
|
||||||
},
|
],
|
||||||
end: 0
|
end: 0
|
||||||
),
|
),
|
||||||
"Denuvo v1.0 (x86)"),
|
"Denuvo v1.0 (x86)"),
|
||||||
@@ -221,11 +216,10 @@ namespace BinaryObjectScanner.Protection
|
|||||||
// Romance of 13 Kingdoms, 2Dark
|
// Romance of 13 Kingdoms, 2Dark
|
||||||
new(
|
new(
|
||||||
new ContentMatch(
|
new ContentMatch(
|
||||||
new byte?[]
|
[
|
||||||
{
|
|
||||||
0x8D, null, null, null, null, null, null, 0x89,
|
0x8D, null, null, null, null, null, null, 0x89,
|
||||||
0x7C, 0x24, 0x04, 0x89, 0xE7,
|
0x7C, 0x24, 0x04, 0x89, 0xE7,
|
||||||
},
|
],
|
||||||
end: 0
|
end: 0
|
||||||
),
|
),
|
||||||
"Denuvo v2.0 (x86)"),
|
"Denuvo v2.0 (x86)"),
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ namespace BinaryObjectScanner.Protection
|
|||||||
// LockBlocks falls under this category, being created by and seemingly exclusively in Dinamic Multimedia products, but in every place I find it described online, it is said to very specifically have two rings on the data side of the disc.
|
// LockBlocks falls under this category, being created by and seemingly exclusively in Dinamic Multimedia products, but in every place I find it described online, it is said to very specifically have two rings on the data side of the disc.
|
||||||
// Due to there being seemingly no absolute defining feature to LockBlocks other than this, any protected disc from Dinamic Multimedia that doesn't specifically have two rings is considered to have "Dinamic Multimedia Protection".
|
// Due to there being seemingly no absolute defining feature to LockBlocks other than this, any protected disc from Dinamic Multimedia that doesn't specifically have two rings is considered to have "Dinamic Multimedia Protection".
|
||||||
// That being said, it may be entirely possible that LockBlocks is the name for all these protections as a whole, as some sources seem to consider games that don't seem to have two rings to have LockBlocks.
|
// That being said, it may be entirely possible that LockBlocks is the name for all these protections as a whole, as some sources seem to consider games that don't seem to have two rings to have LockBlocks.
|
||||||
|
// FX Interactive was formed by people formerly working at Dinamic Multimedia. The ring system used by this company shares many features of the Dinamic one, including using the same Mastering SIDs. It's possible related as a result but no direct connection has been found.
|
||||||
|
// Another possibly related DRM is SonoProtec. All known instances of Dinamic Multimedia Protection (aswell as FX Interactive) have been mastered at Sonopress Ibermemory SA. And while no directly comfirmed isntances of Sonoprotec has been found. Patent for this protection was filled by Sonopress Ibermemory SA on 1998-11-06. Around the same time Dinamic Multimedia Protection started showing up and patent description is very similar to how LockBlocks was described.
|
||||||
|
|
||||||
// Resources:
|
// Resources:
|
||||||
// https://www.cdmediaworld.com/hardware/cdrom/cd_protections_lockblocks.shtml
|
// https://www.cdmediaworld.com/hardware/cdrom/cd_protections_lockblocks.shtml
|
||||||
@@ -21,6 +23,10 @@ namespace BinaryObjectScanner.Protection
|
|||||||
// https://www.gamecopyworld.com/games/pc_pc_atletismo.shtml
|
// https://www.gamecopyworld.com/games/pc_pc_atletismo.shtml
|
||||||
// https://www.gamecopyworld.com/games/pc_pc_calcio_2000.shtml
|
// https://www.gamecopyworld.com/games/pc_pc_calcio_2000.shtml
|
||||||
// https://www.gamecopyworld.com/games/pc_pc_futbol_2000.shtml
|
// https://www.gamecopyworld.com/games/pc_pc_futbol_2000.shtml
|
||||||
|
// https://www.gamecopyworld.com/games/pc_space_clash.shtml
|
||||||
|
// https://www.trademarkelite.com/europe/trademark/trademark-detail/001282730/SONOPROTEC
|
||||||
|
// https://www.patents.google.com/patent/EP1107251A1
|
||||||
|
// https://www.patents.google.com/patent/ES2149719A1
|
||||||
|
|
||||||
public List<string> CheckDirectoryPath(string path, List<string>? files)
|
public List<string> CheckDirectoryPath(string path, List<string>? files)
|
||||||
{
|
{
|
||||||
@@ -46,7 +52,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
{
|
{
|
||||||
var matchers = new List<PathMatchSet>
|
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.
|
// Many more checks are likely possible based on the sources, but only ones that have been personally verified are getting added. As it stands now file names might be randomised though and not a good source for detection.
|
||||||
|
|
||||||
// Uncopyable files found in at least http://redump.org/disc/70531/, and likely in multiple others.
|
// Uncopyable files found in at least http://redump.org/disc/70531/, and likely in multiple others.
|
||||||
new(new FilePathMatch("2kscore.sc0"), "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]"),
|
||||||
@@ -58,6 +64,15 @@ namespace BinaryObjectScanner.Protection
|
|||||||
new(new FilePathMatch("opublic.001"), "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("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]"),
|
new(new FilePathMatch("uqprime.ipx"), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
|
||||||
|
// Uncopyable files found in at least http://redump.org/disc/55245/, and likely in multiple others.
|
||||||
|
new(new FilePathMatch("ZAXARAIE.DA0"), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
|
||||||
|
new(new FilePathMatch("IEDESAEO.EAS"), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
|
||||||
|
new(new FilePathMatch("NAIOUEGO.FEK"), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
|
||||||
|
new(new FilePathMatch("PIDAEIAI.DA0"), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
|
||||||
|
new(new FilePathMatch("SIXADIRE.PAU"), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
|
||||||
|
new(new FilePathMatch("UOUOZEJE.DA0"), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
|
||||||
|
new(new FilePathMatch("BAWIVOZI.YAQ"), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
|
||||||
|
new(new FilePathMatch("YAUAEARO.QAI"), "Dinamic Multimedia Protection/LockBlocks [Check disc for 2 physical rings]"),
|
||||||
};
|
};
|
||||||
|
|
||||||
return MatchUtil.GetFirstMatch(path, matchers, any: true);
|
return MatchUtil.GetFirstMatch(path, matchers, any: true);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using BinaryObjectScanner.Interfaces;
|
using BinaryObjectScanner.Interfaces;
|
||||||
|
using SabreTools.Data.Models.PortableExecutable.Resource.Entries;
|
||||||
using SabreTools.IO;
|
using SabreTools.IO;
|
||||||
using SabreTools.IO.Extensions;
|
using SabreTools.IO.Extensions;
|
||||||
using SabreTools.IO.Matching;
|
using SabreTools.IO.Matching;
|
||||||
@@ -63,7 +64,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
return "DiscGuard";
|
return "DiscGuard";
|
||||||
|
|
||||||
// Found in "Alternate.exe" (Redump entry 31914) and "Alt.exe" (Redump entries 46743, 46961, 79284, and 79374).
|
// Found in "Alternate.exe" (Redump entry 31914) and "Alt.exe" (Redump entries 46743, 46961, 79284, and 79374).
|
||||||
List<Dictionary<int, string?>?> resources =
|
List<StringTableResource?> resources =
|
||||||
[
|
[
|
||||||
.. exe.FindStringTableByEntry("DiscGuard"),
|
.. exe.FindStringTableByEntry("DiscGuard"),
|
||||||
.. exe.FindStringTableByEntry("The file Dg.vbn was not found."),
|
.. exe.FindStringTableByEntry("The file Dg.vbn was not found."),
|
||||||
@@ -75,7 +76,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the .vbn section, if it exists
|
// Get the .vbn section, if it exists
|
||||||
var vbnData = exe.GetFirstSectionData(".vbn");
|
var vbnData = exe.GetFirstSectionData(".vbn");
|
||||||
if (vbnData != null)
|
if (vbnData is not null)
|
||||||
{
|
{
|
||||||
var matchers = new List<ContentMatchSet>
|
var matchers = new List<ContentMatchSet>
|
||||||
{
|
{
|
||||||
@@ -195,7 +196,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
private string? GetVersion(string file, byte[]? fileContent, List<int> positions)
|
private string? GetVersion(string file, byte[]? fileContent, List<int> positions)
|
||||||
{
|
{
|
||||||
// If we have no content
|
// If we have no content
|
||||||
if (fileContent == null)
|
if (fileContent is null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// Check the internal versions
|
// Check the internal versions
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the .data/DATA section strings, if they exist
|
// Get the .data/DATA section strings, if they exist
|
||||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
if (strs.Exists(s => s.Contains("EReg Config Form")))
|
if (strs.Exists(s => s.Contains("EReg Config Form")))
|
||||||
return "EA CdKey Registration Module";
|
return "EA CdKey Registration Module";
|
||||||
@@ -39,7 +39,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the .rdata section strings, if they exist
|
// Get the .rdata section strings, if they exist
|
||||||
strs = exe.GetFirstSectionStrings(".rdata");
|
strs = exe.GetFirstSectionStrings(".rdata");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
if (strs.Exists(s => s.Contains("GenericEA")) && strs.Exists(s => s.Contains("Activation")))
|
if (strs.Exists(s => s.Contains("GenericEA")) && strs.Exists(s => s.Contains("Activation")))
|
||||||
return "EA DRM Protection";
|
return "EA DRM Protection";
|
||||||
@@ -47,7 +47,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the .rdata section strings, if they exist
|
// Get the .rdata section strings, if they exist
|
||||||
strs = exe.GetFirstSectionStrings(".text");
|
strs = exe.GetFirstSectionStrings(".text");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
if (strs.Exists(s => s.Contains("GenericEA")) && strs.Exists(s => s.Contains("Activation")))
|
if (strs.Exists(s => s.Contains("GenericEA")) && strs.Exists(s => s.Contains("Activation")))
|
||||||
return "EA DRM Protection";
|
return "EA DRM Protection";
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ namespace BinaryObjectScanner.Protection
|
|||||||
// Most every tested sample of "engine32.dll" has a product name of "engine32", and the file description typically follows the naming pattern of "[Game Name] DLL-helper".
|
// Most every tested sample of "engine32.dll" has a product name of "engine32", and the file description typically follows the naming pattern of "[Game Name] DLL-helper".
|
||||||
|
|
||||||
// Detects Engine32 within the game executables that contain it.
|
// Detects Engine32 within the game executables that contain it.
|
||||||
if (exe.ImportDirectoryTable != null && exe.ImportHintNameTable != null)
|
if (exe.ImportDirectoryTable is not null && exe.ImportHintNameTable is not null)
|
||||||
{
|
{
|
||||||
bool importDirectoryTableMatch = Array.Exists(exe.ImportDirectoryTable,
|
bool importDirectoryTableMatch = Array.Exists(exe.ImportDirectoryTable,
|
||||||
idte => idte?.Name != null && idte.Name.Equals("ENGINE32.DLL", StringComparison.OrdinalIgnoreCase));
|
idte => idte?.Name is not null && idte.Name.Equals("ENGINE32.DLL", StringComparison.OrdinalIgnoreCase));
|
||||||
bool hintNameTableMatch = Array.Exists(exe.ImportHintNameTable,
|
bool hintNameTableMatch = Array.Exists(exe.ImportHintNameTable,
|
||||||
ihne => ihne?.Name == "InitEngine");
|
ihne => ihne?.Name == "InitEngine");
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Detects Engine32 within the file "engine32.dll".
|
// Detects Engine32 within the file "engine32.dll".
|
||||||
if (exe.ExportNameTable?.Strings != null)
|
if (exe.ExportNameTable?.Strings is not null)
|
||||||
{
|
{
|
||||||
bool exportNameTableMatch1 = Array.Exists(exe.ExportNameTable.Strings, s => s == "engine32.dll");
|
bool exportNameTableMatch1 = Array.Exists(exe.ExportNameTable.Strings, s => s == "engine32.dll");
|
||||||
bool exportNameTableMatch2 = Array.Exists(exe.ExportNameTable.Strings, s => s == "DeinitEngine");
|
bool exportNameTableMatch2 = Array.Exists(exe.ExportNameTable.Strings, s => s == "DeinitEngine");
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
return $"Games for Windows LIVE {exe.GetInternalVersion()}";
|
return $"Games for Windows LIVE {exe.GetInternalVersion()}";
|
||||||
|
|
||||||
// Get the import directory table
|
// Get the import directory table
|
||||||
if (exe.ImportDirectoryTable != null)
|
if (exe.ImportDirectoryTable is not null)
|
||||||
{
|
{
|
||||||
if (Array.Exists(exe.ImportDirectoryTable, idte => idte?.Name == "xlive.dll"))
|
if (Array.Exists(exe.ImportDirectoryTable, idte => idte?.Name == "xlive.dll"))
|
||||||
return "Games for Windows LIVE";
|
return "Games for Windows LIVE";
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ namespace BinaryObjectScanner.Protection
|
|||||||
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
||||||
{
|
{
|
||||||
// Get the header padding strings, if it exists
|
// Get the header padding strings, if it exists
|
||||||
if (exe.HeaderPaddingStrings != null)
|
if (exe.HeaderPaddingStrings is not null)
|
||||||
{
|
{
|
||||||
var match = exe.HeaderPaddingStrings.Find(s => s.Contains("Gefest Protection System"));
|
var match = exe.HeaderPaddingStrings.Find(s => s.Contains("Gefest Protection System"));
|
||||||
if (match != null)
|
if (match is not null)
|
||||||
return $"Gefest Protection System {GetVersion(match)}";
|
return $"Gefest Protection System {GetVersion(match)}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +57,11 @@ namespace BinaryObjectScanner.Protection
|
|||||||
private static string GetVersion(string match)
|
private static string GetVersion(string match)
|
||||||
{
|
{
|
||||||
match = match.Trim('*').Trim();
|
match = match.Trim('*').Trim();
|
||||||
|
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||||
|
return match["Gefest Protection System ".Length..];
|
||||||
|
#else
|
||||||
return match.Substring("Gefest Protection System ".Length);
|
return match.Substring("Gefest Protection System ".Length);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the .text section strings, if they exist
|
// Get the .text section strings, if they exist
|
||||||
var strs = exe.GetFirstSectionStrings(".text");
|
var strs = exe.GetFirstSectionStrings(".text");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
// Found in "The Sudoku Challenge Collection.exe" in "The Sudoku Challenge! Collection" by Play at Joe's.
|
// Found in "The Sudoku Challenge Collection.exe" in "The Sudoku Challenge! Collection" by Play at Joe's.
|
||||||
if (strs.Exists(s => s.Contains("mfint.dll")))
|
if (strs.Exists(s => s.Contains("mfint.dll")))
|
||||||
@@ -63,7 +63,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the code/CODE section strings, if they exist
|
// Get the code/CODE section strings, if they exist
|
||||||
strs = exe.GetFirstSectionStrings("code") ?? exe.GetFirstSectionStrings("CODE");
|
strs = exe.GetFirstSectionStrings("code") ?? exe.GetFirstSectionStrings("CODE");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
// Found in "launcher.exe" in "Sea Adventure / Adventure de la Mer" by Compedia.
|
// Found in "launcher.exe" in "Sea Adventure / Adventure de la Mer" by Compedia.
|
||||||
if (strs.Exists(s => s.Contains("mfint.dll")))
|
if (strs.Exists(s => s.Contains("mfint.dll")))
|
||||||
@@ -72,7 +72,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the UPX1 section strings, if they exist
|
// Get the UPX1 section strings, if they exist
|
||||||
strs = exe.GetFirstSectionStrings("UPX1");
|
strs = exe.GetFirstSectionStrings("UPX1");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
// Found in "postmanpat.exe" in "Postman Pat" by Compedia.
|
// Found in "postmanpat.exe" in "Postman Pat" by Compedia.
|
||||||
if (strs.Exists(s => s.Contains("mfint.dll")))
|
if (strs.Exists(s => s.Contains("mfint.dll")))
|
||||||
|
|||||||
@@ -33,13 +33,13 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// TODO: Check for CVP* instead?
|
// TODO: Check for CVP* instead?
|
||||||
bool containsCheck = false;
|
bool containsCheck = false;
|
||||||
if (exe.ExportNameTable?.Strings != null)
|
if (exe.ExportNameTable?.Strings is not null)
|
||||||
containsCheck = Array.Exists(exe.ExportNameTable.Strings, s => s.OptionalStartsWith("CVPInitializeClient"));
|
containsCheck = Array.Exists(exe.ExportNameTable.Strings, s => s.OptionalStartsWith("CVPInitializeClient"));
|
||||||
|
|
||||||
// Get the .rdata section strings, if they exist
|
// Get the .rdata section strings, if they exist
|
||||||
bool containsCheck2 = false;
|
bool containsCheck2 = false;
|
||||||
var strs = exe.GetFirstSectionStrings(".rdata");
|
var strs = exe.GetFirstSectionStrings(".rdata");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
containsCheck2 = strs.Exists(s => s.EndsWith("ATTLIST"))
|
containsCheck2 = strs.Exists(s => s.EndsWith("ATTLIST"))
|
||||||
&& strs.Exists(s => s.Equals("ELEMENT"))
|
&& strs.Exists(s => s.Equals("ELEMENT"))
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ using System.Text.RegularExpressions;
|
|||||||
using BinaryObjectScanner.Interfaces;
|
using BinaryObjectScanner.Interfaces;
|
||||||
using SabreTools.Serialization.Wrappers;
|
using SabreTools.Serialization.Wrappers;
|
||||||
|
|
||||||
|
#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'
|
||||||
namespace BinaryObjectScanner.Protection
|
namespace BinaryObjectScanner.Protection
|
||||||
{
|
{
|
||||||
public class InterLok : IExecutableCheck<PortableExecutable>
|
public class InterLok : IExecutableCheck<PortableExecutable>
|
||||||
@@ -11,13 +12,13 @@ namespace BinaryObjectScanner.Protection
|
|||||||
{
|
{
|
||||||
// Get the .rsrc section strings, if they exist
|
// Get the .rsrc section strings, if they exist
|
||||||
var strs = exe.GetFirstSectionStrings(".rsrc");
|
var strs = exe.GetFirstSectionStrings(".rsrc");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
// Found in "nfsc_link.exe" in IA item "nfscorigin".
|
// Found in "nfsc_link.exe" in IA item "nfscorigin".
|
||||||
// Full string:
|
// Full string:
|
||||||
// (: ) InterLok PC v2.0, PACE Anti-Piracy, Copyright (C) 1998, ALL RIGHTS RESERVED
|
// (: ) InterLok PC v2.0, PACE Anti-Piracy, Copyright (C) 1998, ALL RIGHTS RESERVED
|
||||||
var match = strs.Find(s => s.Contains("InterLok") && s.Contains("PACE Anti-Piracy"));
|
var match = strs.Find(s => s.Contains("InterLok") && s.Contains("PACE Anti-Piracy"));
|
||||||
if (match != null)
|
if (match is not null)
|
||||||
return $"PACE Anti-Piracy InterLok {GetVersion(match)}";
|
return $"PACE Anti-Piracy InterLok {GetVersion(match)}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
private static string GetVersion(string match)
|
private static string GetVersion(string match)
|
||||||
{
|
{
|
||||||
var versionMatch = Regex.Match(match, @"(?<=InterLok )(.*?)(?=,)");
|
var versionMatch = Regex.Match(match, @"(?<=InterLok )(.*?)(?=,)", RegexOptions.Compiled);
|
||||||
if (versionMatch.Success)
|
if (versionMatch.Success)
|
||||||
return versionMatch.Value;
|
return versionMatch.Value;
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
if (exe.ContainsSection(".dcrtext") && importTableMatches)
|
if (exe.ContainsSection(".dcrtext") && importTableMatches)
|
||||||
{
|
{
|
||||||
var dcrtextData = exe.GetFirstSectionData(".dcrtext");
|
var dcrtextData = exe.GetFirstSectionData(".dcrtext");
|
||||||
if (dcrtextData != null)
|
if (dcrtextData is not null)
|
||||||
{
|
{
|
||||||
var matchers = new List<ContentMatchSet>
|
var matchers = new List<ContentMatchSet>
|
||||||
{
|
{
|
||||||
@@ -63,7 +63,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
private static string? GetVersion(string file, byte[]? fileContent, List<int> positions)
|
private static string? GetVersion(string file, byte[]? fileContent, List<int> positions)
|
||||||
{
|
{
|
||||||
// If we have no content
|
// If we have no content
|
||||||
if (fileContent == null)
|
if (fileContent is null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return Encoding.ASCII.GetString(fileContent, positions[0] + 67, 8);
|
return Encoding.ASCII.GetString(fileContent, positions[0] + 67, 8);
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the .text section strings, if they exist
|
// Get the .text section strings, if they exist
|
||||||
var strs = exe.GetFirstSectionStrings(".rdata");
|
var strs = exe.GetFirstSectionStrings(".rdata");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
// Found in "TFT.exe" in Redump entry 95617.
|
// Found in "TFT.exe" in Redump entry 95617.
|
||||||
if (strs.Exists(s => s.Contains("@KalypsoLauncherXml")))
|
if (strs.Exists(s => s.Contains("@KalypsoLauncherXml")))
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace BinaryObjectScanner.Protection
|
|||||||
|
|
||||||
// Get the .data/DATA section strings, if they exist
|
// Get the .data/DATA section strings, if they exist
|
||||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||||
if (strs != null)
|
if (strs is not null)
|
||||||
{
|
{
|
||||||
// Found in "START.EXE" (Redump entry 95010 and product ID SVWC-7185).
|
// Found in "START.EXE" (Redump entry 95010 and product ID SVWC-7185).
|
||||||
if (strs.Exists(s => s.Contains("LGCD2_LAUNCH")))
|
if (strs.Exists(s => s.Contains("LGCD2_LAUNCH")))
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user