mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-07-10 02:46:55 +00:00
Compare commits
27 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 |
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
|
||||
@@ -12,12 +12,12 @@
|
||||
</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>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="[2.2.1]" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="[2.3.0]" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace BinaryObjectScanner.Test.Data
|
||||
public void PortableExecutableCheckClasses_Populated()
|
||||
{
|
||||
var actual = StaticChecks.PortableExecutableCheckClasses;
|
||||
Assert.Equal(105, actual.Length);
|
||||
Assert.Equal(106, actual.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>3.5.0</Version>
|
||||
<Version>3.6.0</Version>
|
||||
<WarningsNotAsErrors>NU5104</WarningsNotAsErrors>
|
||||
|
||||
<!-- Package Properties -->
|
||||
@@ -46,12 +46,12 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="GrindCore.SharpCompress" Version="0.41.1" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||
<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="SabreTools.Hashing" Version="[1.6.0]" />
|
||||
<PackageReference Include="SabreTools.IO" Version="[1.9.0]" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="[2.2.1]" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="10.0.0" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))" />
|
||||
<PackageReference Include="SabreTools.Hashing" Version="[1.6.1]" />
|
||||
<PackageReference Include="SabreTools.IO" Version="[1.9.1]" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="[2.3.0]" />
|
||||
<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`))" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -13,7 +13,7 @@ namespace BinaryObjectScanner.Data
|
||||
/// <remarks>Handles the proper Add implementation</remarks>
|
||||
public void Append(T key, string? value)
|
||||
{
|
||||
if (value == null || value.Trim().Length == 0)
|
||||
if (value is null || value.Trim().Length == 0)
|
||||
return;
|
||||
|
||||
#if NET20 || NET35
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace BinaryObjectScanner.Data
|
||||
public void Append(string key, string? value)
|
||||
{
|
||||
// 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;
|
||||
|
||||
EnsureKey(key);
|
||||
@@ -47,7 +47,7 @@ namespace BinaryObjectScanner.Data
|
||||
EnsureKey(key);
|
||||
foreach (string value in values)
|
||||
{
|
||||
if (value == null || value.Trim().Length == 0)
|
||||
if (value is null || value.Trim().Length == 0)
|
||||
continue;
|
||||
|
||||
foreach (string subValue in ProcessProtectionString(value))
|
||||
@@ -79,7 +79,7 @@ namespace BinaryObjectScanner.Data
|
||||
public void Append(ProtectionDictionary? addition)
|
||||
{
|
||||
// If the dictionary is missing, just return
|
||||
if (addition == null)
|
||||
if (addition is null)
|
||||
return;
|
||||
|
||||
// Loop through each of the addition keys and add accordingly
|
||||
@@ -106,10 +106,10 @@ namespace BinaryObjectScanner.Data
|
||||
|
||||
// If the key is empty, remove it
|
||||
#if NET20 || NET35
|
||||
if (this[key] == null || this[key].Count == 0)
|
||||
if (this[key] is null || this[key].Count == 0)
|
||||
Remove(key);
|
||||
#else
|
||||
if (this[key] == null || this[key].IsEmpty)
|
||||
if (this[key] is null || this[key].IsEmpty)
|
||||
TryRemove(key, out _);
|
||||
#endif
|
||||
}
|
||||
@@ -189,13 +189,13 @@ namespace BinaryObjectScanner.Data
|
||||
/// <param name="values">Queue to get data from</param>
|
||||
private void AddRangeToKey(string key, IEnumerable<string> values)
|
||||
{
|
||||
if (values == null)
|
||||
if (values is null)
|
||||
return;
|
||||
|
||||
EnsureKey(key);
|
||||
foreach (string value in values)
|
||||
{
|
||||
if (value == null || value.Trim().Length == 0)
|
||||
if (value is null || value.Trim().Length == 0)
|
||||
continue;
|
||||
|
||||
foreach (string subValue in ProcessProtectionString(value))
|
||||
|
||||
@@ -17,8 +17,8 @@ namespace BinaryObjectScanner.Data
|
||||
{
|
||||
get
|
||||
{
|
||||
contentCheckClasses ??= InitCheckClasses<IContentCheck>();
|
||||
return contentCheckClasses;
|
||||
field ??= InitCheckClasses<IContentCheck>();
|
||||
return field;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@ namespace BinaryObjectScanner.Data
|
||||
{
|
||||
get
|
||||
{
|
||||
iso9660CheckClasses ??= InitCheckClasses<IDiskImageCheck<ISO9660>>();
|
||||
return iso9660CheckClasses;
|
||||
field ??= InitCheckClasses<IDiskImageCheck<ISO9660>>();
|
||||
return field;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +41,8 @@ namespace BinaryObjectScanner.Data
|
||||
{
|
||||
get
|
||||
{
|
||||
linearExecutableCheckClasses ??= InitCheckClasses<IExecutableCheck<LinearExecutable>>();
|
||||
return linearExecutableCheckClasses;
|
||||
field ??= InitCheckClasses<IExecutableCheck<LinearExecutable>>();
|
||||
return field;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,8 +53,8 @@ namespace BinaryObjectScanner.Data
|
||||
{
|
||||
get
|
||||
{
|
||||
msdosExecutableCheckClasses ??= InitCheckClasses<IExecutableCheck<MSDOS>>();
|
||||
return msdosExecutableCheckClasses;
|
||||
field ??= InitCheckClasses<IExecutableCheck<MSDOS>>();
|
||||
return field;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,8 +65,8 @@ namespace BinaryObjectScanner.Data
|
||||
{
|
||||
get
|
||||
{
|
||||
newExecutableCheckClasses ??= InitCheckClasses<IExecutableCheck<NewExecutable>>();
|
||||
return newExecutableCheckClasses;
|
||||
field ??= InitCheckClasses<IExecutableCheck<NewExecutable>>();
|
||||
return field;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,8 +77,8 @@ namespace BinaryObjectScanner.Data
|
||||
{
|
||||
get
|
||||
{
|
||||
pathCheckClasses ??= InitCheckClasses<IPathCheck>();
|
||||
return pathCheckClasses;
|
||||
field ??= InitCheckClasses<IPathCheck>();
|
||||
return field;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,52 +89,15 @@ namespace BinaryObjectScanner.Data
|
||||
{
|
||||
get
|
||||
{
|
||||
portableExecutableCheckClasses ??= InitCheckClasses<IExecutableCheck<PortableExecutable>>();
|
||||
return portableExecutableCheckClasses;
|
||||
field ??= InitCheckClasses<IExecutableCheck<PortableExecutable>>();
|
||||
return field;
|
||||
}
|
||||
|
||||
private set;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Instances
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IContentCheck types
|
||||
/// </summary>
|
||||
private static IContentCheck[]? contentCheckClasses;
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IISOCheck<ISO9660> types
|
||||
/// </summary>
|
||||
private static IDiskImageCheck<ISO9660>[]? iso9660CheckClasses;
|
||||
|
||||
/// <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
|
||||
|
||||
/// <summary>
|
||||
@@ -150,7 +113,7 @@ namespace BinaryObjectScanner.Data
|
||||
{
|
||||
// Get information from the type param
|
||||
string? interfaceName = typeof(T).FullName;
|
||||
if (interfaceName == null)
|
||||
if (interfaceName is null)
|
||||
return [];
|
||||
|
||||
// If not all types can be loaded, use the ones that could be
|
||||
@@ -173,7 +136,7 @@ namespace BinaryObjectScanner.Data
|
||||
foreach (Type? type in assemblyTypes)
|
||||
{
|
||||
// Skip invalid types
|
||||
if (type == null)
|
||||
if (type is null)
|
||||
continue;
|
||||
|
||||
// If the type isn't a class
|
||||
@@ -187,7 +150,7 @@ namespace BinaryObjectScanner.Data
|
||||
|
||||
// Try to create a concrete instance of the type
|
||||
var instance = (T?)Activator.CreateInstance(type);
|
||||
if (instance != null)
|
||||
if (instance is not null)
|
||||
classTypes.Add(instance);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
|
||||
#pragma warning disable IDE0290 // Use primary constructor
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
|
||||
#pragma warning disable IDE0290 // Use primary constructor
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
#pragma warning disable IDE0290 // Use primary constructor
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -4,6 +4,7 @@ using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
#pragma warning disable IDE0290 // Use primary constructor
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -6,6 +6,7 @@ using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
#pragma warning disable IDE0290 // Use primary constructor
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
/// <summary>
|
||||
@@ -47,7 +48,7 @@ namespace BinaryObjectScanner.FileType
|
||||
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
fileContent = stream.ReadBytes((int)stream.Length);
|
||||
if (fileContent == null)
|
||||
if (fileContent is null)
|
||||
return protections;
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ using BinaryObjectScanner.Data;
|
||||
using SabreTools.Data.Models.ISO9660;
|
||||
using SabreTools.IO.Extensions;
|
||||
|
||||
#pragma warning disable IDE0290 // Use primary constructor
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
/// <summary>
|
||||
@@ -90,7 +91,7 @@ namespace BinaryObjectScanner.FileType
|
||||
|
||||
int offset = 0;
|
||||
string? potentialAppUseString = applicationUse.ReadNullTerminatedAnsiString(ref offset);
|
||||
if (potentialAppUseString != null && potentialAppUseString.Length > 0) // Some image authoring programs add a starting string to AU data
|
||||
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;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
|
||||
#pragma warning disable IDE0290 // Use primary constructor
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Data;
|
||||
|
||||
#pragma warning disable IDE0290 // Use primary constructor
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Data;
|
||||
|
||||
#pragma warning disable IDE0290 // Use primary constructor
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Data;
|
||||
|
||||
#pragma warning disable IDE0290 // Use primary constructor
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.IO;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
#pragma warning disable IDE0290 // Use primary constructor
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Data;
|
||||
|
||||
#pragma warning disable IDE0290 // Use primary constructor
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
|
||||
#pragma warning disable IDE0290 // Use primary constructor
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
|
||||
#pragma warning disable IDE0290 // Use primary constructor
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
|
||||
#pragma warning disable IDE0290 // Use primary constructor
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -153,7 +153,6 @@ namespace BinaryObjectScanner.FileType
|
||||
protections.Add("SafeDiscLT for Macintosh (Unknown Version - Please report to us on GitHub)");
|
||||
}
|
||||
|
||||
|
||||
// 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.
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
/// <param name="fileContent">Byte array representing the file contents</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <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>
|
||||
/// <returns>Detected file or protection type, null on error</returns>
|
||||
/// <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>
|
||||
/// 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="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,6 @@ namespace BinaryObjectScanner.Interfaces
|
||||
/// <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>
|
||||
string? CheckDiskImage(string file, T diskImage, bool includeDebug);
|
||||
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="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <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="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>
|
||||
List<string> CheckDirectoryPath(string path, List<string>? files);
|
||||
public List<string> CheckDirectoryPath(string path, List<string>? files);
|
||||
|
||||
/// <summary>
|
||||
/// Check a file path for protections based on path name
|
||||
/// </summary>
|
||||
/// <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>
|
||||
string? CheckFilePath(string path);
|
||||
public string? CheckFilePath(string path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace BinaryObjectScanner.Packer
|
||||
return "ASPack 2.29";
|
||||
|
||||
// Use the entry point data, if it exists
|
||||
if (exe.EntryPointData != null)
|
||||
if (exe.EntryPointData is not null)
|
||||
{
|
||||
var matchers = GenerateMatchers();
|
||||
var match = MatchUtil.GetFirstMatch(file, exe.EntryPointData, matchers, includeDebug);
|
||||
@@ -28,7 +28,7 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
// Get the .adata* section, if it exists
|
||||
var adataSectionRaw = exe.GetFirstSectionData(".adata", exact: false);
|
||||
if (adataSectionRaw != null)
|
||||
if (adataSectionRaw is not null)
|
||||
{
|
||||
var matchers = GenerateMatchers();
|
||||
var match = MatchUtil.GetFirstMatch(file, adataSectionRaw, matchers, includeDebug);
|
||||
@@ -38,7 +38,7 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
// Get the .data/DATA section, if it exists
|
||||
var dataSectionRaw = exe.GetFirstSectionData(".data") ?? exe.GetFirstSectionData("DATA");
|
||||
if (dataSectionRaw != null)
|
||||
if (dataSectionRaw is not null)
|
||||
{
|
||||
var matchers = GenerateMatchers();
|
||||
var match = MatchUtil.GetFirstMatch(file, dataSectionRaw, matchers, includeDebug);
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// Get the .rdata section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(".rdata");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("Software\\Caphyon\\Advanced Installer")))
|
||||
return "Caphyon Advanced Installer SFX";
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace BinaryObjectScanner.Packer
|
||||
if (exe.FindResourceByNamedType("99, ").Count == 2)
|
||||
return "CExe";
|
||||
|
||||
if (exe.StubExecutableData != null)
|
||||
if (exe.StubExecutableData is not null)
|
||||
{
|
||||
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
|
||||
|
||||
// Get the last section strings, if they exist
|
||||
var sections = exe.SectionTable ?? [];
|
||||
var sections = exe.SectionTable;
|
||||
var strs = exe.GetSectionStrings(sections.Length - 1);
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("BITARTS")))
|
||||
return "Crunch";
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// Get the .text section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(".text");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("DotfuscatorAttribute")))
|
||||
return "dotFuscator";
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
// Get the .text section, if it exists
|
||||
var textData = exe.GetFirstSectionData(".text");
|
||||
if (textData != null)
|
||||
if (textData is not null)
|
||||
{
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Data.Models.PortableExecutable.Resource.Entries;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
@@ -19,7 +20,7 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
// Check the overlay, if it exists
|
||||
byte[]? overlayData = exe.OverlayData;
|
||||
if (overlayData != null && overlayData.Length > 0)
|
||||
if (overlayData is not null && overlayData.Length > 0)
|
||||
{
|
||||
// Set the output variables
|
||||
int overlayOffset = 0;
|
||||
@@ -111,12 +112,16 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
// Only process the resources if they are recognized
|
||||
var resourceData = exe.ResourceData;
|
||||
if (resourceData != null)
|
||||
if (resourceData is not null)
|
||||
{
|
||||
// Get the resources that have an archive signature
|
||||
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;
|
||||
|
||||
// Set the output variables
|
||||
@@ -162,7 +167,7 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
// Check the overlay, if it exists
|
||||
byte[]? overlayData = exe.OverlayData;
|
||||
if (overlayData != null && overlayData.Length > 0)
|
||||
if (overlayData is not null && overlayData.Length > 0)
|
||||
{
|
||||
// Set the output variables
|
||||
int overlayOffset = 0;
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("Gentee installer")))
|
||||
return "Gentee Installer";
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// <see href="https://www.virustotal.com/gui/file/b2fc4cffe5131195baf419e96c9fa68c3f23208986fb14e3c5b458b1e7d6af89/details"/>
|
||||
var overlayData = exe.OverlayData;
|
||||
if (overlayData != null)
|
||||
if (overlayData is not null)
|
||||
{
|
||||
// GIPEND
|
||||
if (overlayData.EndsWith([0x47, 0x49, 0x50, 0x45, 0x4E, 0x44]))
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// Check for "Inno" in the reserved words
|
||||
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)
|
||||
{
|
||||
@@ -35,10 +35,10 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
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"));
|
||||
if (str != null)
|
||||
if (str is not null)
|
||||
{
|
||||
return str.Replace("Inno Setup Setup Data", "Inno Setup")
|
||||
.Replace("(u)", "[Unicode]")
|
||||
@@ -62,7 +62,7 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
#pragma warning disable CS0618
|
||||
byte[]? data = exe.ReadArbitraryRange();
|
||||
if (data == null)
|
||||
if (data is null)
|
||||
return "Unknown 1.X";
|
||||
|
||||
var matchers = new List<ContentMatchSet>
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("ViseMain")))
|
||||
return "Installer VISE";
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("wextract_cleanup")))
|
||||
return $"Microsoft CAB SFX {GetVersion(exe)}";
|
||||
@@ -31,7 +31,7 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
// Get the .text section strings, if they exist
|
||||
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.
|
||||
// Further research is needed to see if it's just a different version or entirely separate.
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("NullsoftInst")))
|
||||
return "NSIS";
|
||||
@@ -38,7 +38,7 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
// Get the overlay strings, if they exist
|
||||
strs = exe.OverlayStrings;
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("NullsoftInst")))
|
||||
return "NSIS";
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
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"/>
|
||||
if (strs.Exists(s => s.Contains("ReflexiveArcade")))
|
||||
|
||||
@@ -4,6 +4,8 @@ using System.Text.RegularExpressions;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
#pragma warning disable IDE0060 // Remove unused parameter
|
||||
#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
@@ -18,14 +20,14 @@ namespace BinaryObjectScanner.Packer
|
||||
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
||||
{
|
||||
// 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!"));
|
||||
//if (match != null)
|
||||
//if (match is not null)
|
||||
// return "UPX";
|
||||
|
||||
match = exe.HeaderPaddingStrings.Find(s => s.StartsWith("$Id: UPX"));
|
||||
if (match != null)
|
||||
if (match is not null)
|
||||
{
|
||||
var regexMatch = _oldUpxVersionMatch.Match(match);
|
||||
if (regexMatch.Success)
|
||||
@@ -35,7 +37,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
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);
|
||||
if (regexMatch.Success)
|
||||
@@ -43,7 +45,7 @@ namespace BinaryObjectScanner.Packer
|
||||
else
|
||||
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);
|
||||
if (regexMatch.Success)
|
||||
|
||||
@@ -11,14 +11,14 @@ namespace BinaryObjectScanner.Packer
|
||||
public string? CheckExecutable(string file, NewExecutable exe, bool includeDebug)
|
||||
{
|
||||
// If the resident-name table doesnt exist
|
||||
if (exe.ResidentNameTable == null)
|
||||
if (exe.ResidentNameTable is null)
|
||||
return null;
|
||||
|
||||
// Get the resident and non-resident name table strings
|
||||
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 ?? [],
|
||||
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
|
||||
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)
|
||||
{
|
||||
// Check the export directory table, if it exists
|
||||
if (exe.ExportDirectoryTable != null)
|
||||
if (exe.ExportDirectoryTable is not null)
|
||||
{
|
||||
var version = GetPEExportDirectoryVersion(exe);
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace BinaryObjectScanner.Packer
|
||||
return "Wise Installation Wizard Module";
|
||||
|
||||
// If the section header can be found
|
||||
if (exe.WiseSection != null)
|
||||
if (exe.WiseSection is not null)
|
||||
return "Wise Installation Wizard Module";
|
||||
|
||||
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/..."
|
||||
|
||||
// Get the entry point data, if it exists
|
||||
if (exe.EntryPointData != null)
|
||||
if (exe.EntryPointData is not null)
|
||||
{
|
||||
// Found in "Zuma.exe"
|
||||
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
|
||||
var strs = exe.GetLastSectionStrings(".data");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("MPRMMGVA"))
|
||||
&& 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)
|
||||
{
|
||||
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;
|
||||
if (match)
|
||||
return "ActiveMARK";
|
||||
}
|
||||
|
||||
// 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")))
|
||||
return "ActiveMARK";
|
||||
@@ -75,7 +75,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the last .bss section strings, if they exist
|
||||
strs = exe.GetLastSectionStrings(".bss");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("TMSAMVOF")))
|
||||
return "ActiveMARK";
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .data/DATA section, if it exists
|
||||
var dataSectionRaw = exe.GetFirstSectionData(".data") ?? exe.GetFirstSectionData("DATA");
|
||||
if (dataSectionRaw != null)
|
||||
if (dataSectionRaw is not null)
|
||||
{
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@ using SabreTools.Data.Models.ISO9660;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
/// <summary>
|
||||
@@ -62,7 +63,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// TODO: triple-check that length is never below 14
|
||||
int offset = 0;
|
||||
var applicationIdentifierString = pvd.ApplicationIdentifier.ReadNullTerminatedAnsiString(ref offset)?.Trim();
|
||||
if (applicationIdentifierString == null || applicationIdentifierString.Length < 14)
|
||||
if (applicationIdentifierString is null || applicationIdentifierString.Length < 14)
|
||||
return null;
|
||||
|
||||
if (!Regex.IsMatch(applicationIdentifierString, "^[A-Z0-9]*$", RegexOptions.Compiled))
|
||||
@@ -92,15 +93,15 @@ namespace BinaryObjectScanner.Protection
|
||||
if (applicationIdentifierString.Length >= 18 && applicationIdentifierString.Length <= 20)
|
||||
{
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
if (int.TryParse(applicationIdentifierString.AsSpan(0, 4), out int year) == false
|
||||
|| int.TryParse(applicationIdentifierString.AsSpan(4, 2), out int month) == false
|
||||
|| int.TryParse(applicationIdentifierString.AsSpan(6, 2), out int day) == false
|
||||
|| int.TryParse(applicationIdentifierString.AsSpan(8, 6), out int extraTime) == false)
|
||||
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) == false
|
||||
|| int.TryParse(applicationIdentifierString.Substring(4, 2), out int month) == false
|
||||
|| int.TryParse(applicationIdentifierString.Substring(6, 2), out int day) == false
|
||||
|| int.TryParse(applicationIdentifierString.Substring(8, 6), out int extraTime) == false)
|
||||
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;
|
||||
@@ -133,7 +134,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("\\SETTEC")))
|
||||
return "Alpha-ROM";
|
||||
@@ -144,7 +145,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .rdata section strings, if they exist
|
||||
strs = exe.GetFirstSectionStrings(".rdata");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("This Game is Japan Only")))
|
||||
return "Alpha-ROM";
|
||||
@@ -159,7 +160,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
// Get the overlay data, if it exists
|
||||
if (exe.OverlayStrings != null)
|
||||
if (exe.OverlayStrings is not null)
|
||||
{
|
||||
// Found in Redump entry 84122.
|
||||
if (exe.OverlayStrings.Exists(s => s.Contains("SETTEC0000")))
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// Get the section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(sectionName);
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("ARMDEBUG")))
|
||||
return "Armadillo";
|
||||
|
||||
@@ -89,7 +89,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// Found in "LineRider2.exe" in Redump entry 6236
|
||||
if (strs.Exists(s => s.OptionalContains("ByteShield")))
|
||||
@@ -98,7 +98,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .rdata section strings, if they exist
|
||||
strs = exe.GetFirstSectionStrings(".rdata");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// Found in "ByteShield.dll" in Redump entry 6236
|
||||
if (strs.Exists(s => s.OptionalContains("Byte|Shield")))
|
||||
@@ -115,7 +115,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .ret section strings, if they exist
|
||||
strs = exe.GetFirstSectionStrings(".ret");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// TODO: Figure out if this specifically indicates if the file is encrypted
|
||||
// Found in "LineRider2.bbz" in Redump entry 6236
|
||||
|
||||
@@ -8,6 +8,7 @@ using SabreTools.IO.Extensions;
|
||||
using SabreTools.IO.Matching;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
/// <summary>
|
||||
@@ -74,7 +75,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// TODO: Don't read entire file
|
||||
#pragma warning disable CS0618
|
||||
byte[]? data = exe.ReadArbitraryRange();
|
||||
if (data == null)
|
||||
if (data is null)
|
||||
return null;
|
||||
|
||||
// TODO: Figure out what NE section this lives in
|
||||
@@ -121,11 +122,11 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the resident and non-resident name table strings
|
||||
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
|
||||
// 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)
|
||||
{
|
||||
@@ -150,7 +151,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
||||
{
|
||||
// Get the stub executable data, if it exists
|
||||
if (exe.StubExecutableData != null)
|
||||
if (exe.StubExecutableData is not null)
|
||||
{
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
@@ -182,10 +183,10 @@ namespace BinaryObjectScanner.Protection
|
||||
// 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.
|
||||
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, ")));
|
||||
if (match != null)
|
||||
if (match is not null)
|
||||
if (match.Contains("CD-Cops"))
|
||||
return $"CD-Cops {GetVersionString(match)}";
|
||||
else if (match.Contains("DVD-Cops"))
|
||||
@@ -258,7 +259,7 @@ namespace BinaryObjectScanner.Protection
|
||||
private static string? GetVersion(string file, byte[]? fileContent, List<int> positions)
|
||||
{
|
||||
// If we have no content
|
||||
if (fileContent == null)
|
||||
if (fileContent is null)
|
||||
return null;
|
||||
|
||||
string version = Encoding.ASCII.GetString(fileContent, positions[0] + 15, 4);
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// TODO: Investigate the numerous ".guard" sections present in "Randevu.exe" in Redump entry 97142.
|
||||
|
||||
// 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".
|
||||
bool match = exe.ExportDirectoryTable.Name.OptionalEquals("cdguard.dll", StringComparison.OrdinalIgnoreCase);
|
||||
@@ -38,10 +38,10 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
// Get the import directory table
|
||||
if (exe.ImportDirectoryTable != null)
|
||||
if (exe.ImportDirectoryTable is not null)
|
||||
{
|
||||
// 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)
|
||||
return "CD-Guard Copy Protection System";
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// Get the .data/DATA section, if it exists
|
||||
var dataSectionRaw = exe.GetFirstSectionData(".data") ?? exe.GetFirstSectionData("DATA");
|
||||
if (dataSectionRaw != null)
|
||||
if (dataSectionRaw is not null)
|
||||
{
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// TODO: Indicates Hypertech Crack Proof as well?
|
||||
//// 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");
|
||||
// if (match)
|
||||
@@ -19,7 +19,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the code/CODE section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings("code") ?? exe.GetFirstSectionStrings("CODE");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("~0017.tmp")))
|
||||
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.Matching;
|
||||
|
||||
#pragma warning disable IDE0230 // Use UTF-8 string literal
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
public class CactusDataShield : IContentCheck
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
||||
{
|
||||
// Get the export directory table
|
||||
if (exe.ExportDirectoryTable != null)
|
||||
if (exe.ExportDirectoryTable is not null)
|
||||
{
|
||||
// Found in "cenega.dll" in IA item "speed-pack".
|
||||
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
|
||||
var strs = exe.GetFirstSectionStrings(".text");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("CODE-LOCK.OCX")))
|
||||
return "ChosenBytes Code-Lock";
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// Checks for 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.
|
||||
// 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");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// Samples: Redump ID 82475, German Emergency 2 Deluxe, Redump ID 48393
|
||||
if (strs.Exists(s => s.Contains("optgraph.dll")))
|
||||
@@ -90,7 +90,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public List<string> CheckDirectoryPath(string path, List<string>? files)
|
||||
{
|
||||
var protections = new List<string>();
|
||||
if (files == null)
|
||||
if (files is null)
|
||||
return protections;
|
||||
|
||||
// Checks for Light
|
||||
@@ -124,7 +124,7 @@ namespace BinaryObjectScanner.Protection
|
||||
break;
|
||||
}
|
||||
|
||||
if ((lightFiles != null) && (lightFiles.Count > 0))
|
||||
if ((lightFiles is not null) && (lightFiles.Count > 0))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// Get the code/CODE section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings("code") ?? exe.GetFirstSectionStrings("CODE");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// Found in "NECRO95.EXE" in IA item "NBECRORV11".
|
||||
// Full string:
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// Get the .text section, if it exists
|
||||
var textData = exe.GetFirstSectionData(".text");
|
||||
if (textData != null)
|
||||
if (textData is not null)
|
||||
{
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public List<string> CheckDirectoryPath(string path, List<string>? files)
|
||||
{
|
||||
var protections = new List<string>();
|
||||
if (files == null)
|
||||
if (files is null)
|
||||
return protections;
|
||||
|
||||
if (Directory.Exists(Path.Combine(path, "VIDEO_TS")))
|
||||
@@ -20,7 +20,7 @@ namespace BinaryObjectScanner.Protection
|
||||
for (int i = 0; i < bupfiles.Count; i++)
|
||||
{
|
||||
var bupfile = new FileInfo(bupfiles[i]);
|
||||
if (bupfile.DirectoryName == null)
|
||||
if (bupfile.DirectoryName is null)
|
||||
continue;
|
||||
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
|
||||
@@ -7,6 +7,7 @@ using SabreTools.IO.Matching;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
using OHMN = SabreTools.Data.Models.COFF.OptionalHeaderMagicNumber;
|
||||
|
||||
#pragma warning disable IDE0230 // Use UTF-8 string literal
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
/// <summary>
|
||||
@@ -63,7 +64,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// https://github.com/horsicq/Detect-It-Easy/blob/master/db/PE/_denuvoComplete.2.sg
|
||||
|
||||
// Denuvo Protector
|
||||
if (exe.OptionalHeader?.Magic == OHMN.PE32Plus && exe.EntryPointData != null)
|
||||
if (exe.OptionalHeader?.Magic == OHMN.PE32Plus && exe.EntryPointData is not null)
|
||||
{
|
||||
byte?[] denuvoProtector =
|
||||
[
|
||||
|
||||
@@ -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.
|
||||
// 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.
|
||||
// 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:
|
||||
// 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_calcio_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)
|
||||
{
|
||||
@@ -46,7 +52,7 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
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.
|
||||
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("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]"),
|
||||
// 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);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Data.Models.PortableExecutable.Resource.Entries;
|
||||
using SabreTools.IO;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.IO.Matching;
|
||||
@@ -63,7 +64,7 @@ namespace BinaryObjectScanner.Protection
|
||||
return "DiscGuard";
|
||||
|
||||
// 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("The file Dg.vbn was not found."),
|
||||
@@ -75,7 +76,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .vbn section, if it exists
|
||||
var vbnData = exe.GetFirstSectionData(".vbn");
|
||||
if (vbnData != null)
|
||||
if (vbnData is not null)
|
||||
{
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
@@ -195,7 +196,7 @@ namespace BinaryObjectScanner.Protection
|
||||
private string? GetVersion(string file, byte[]? fileContent, List<int> positions)
|
||||
{
|
||||
// If we have no content
|
||||
if (fileContent == null)
|
||||
if (fileContent is null)
|
||||
return null;
|
||||
|
||||
// Check the internal versions
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
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")))
|
||||
return "EA CdKey Registration Module";
|
||||
@@ -39,7 +39,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .rdata section strings, if they exist
|
||||
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")))
|
||||
return "EA DRM Protection";
|
||||
@@ -47,7 +47,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .rdata section strings, if they exist
|
||||
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")))
|
||||
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".
|
||||
|
||||
// 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,
|
||||
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,
|
||||
ihne => ihne?.Name == "InitEngine");
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
// 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 exportNameTableMatch2 = Array.Exists(exe.ExportNameTable.Strings, s => s == "DeinitEngine");
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace BinaryObjectScanner.Protection
|
||||
return $"Games for Windows LIVE {exe.GetInternalVersion()}";
|
||||
|
||||
// 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"))
|
||||
return "Games for Windows LIVE";
|
||||
|
||||
@@ -22,10 +22,10 @@ namespace BinaryObjectScanner.Protection
|
||||
public string? CheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
||||
{
|
||||
// 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"));
|
||||
if (match != null)
|
||||
if (match is not null)
|
||||
return $"Gefest Protection System {GetVersion(match)}";
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .text section strings, if they exist
|
||||
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.
|
||||
if (strs.Exists(s => s.Contains("mfint.dll")))
|
||||
@@ -63,7 +63,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the code/CODE section strings, if they exist
|
||||
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.
|
||||
if (strs.Exists(s => s.Contains("mfint.dll")))
|
||||
@@ -72,7 +72,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the UPX1 section strings, if they exist
|
||||
strs = exe.GetFirstSectionStrings("UPX1");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// Found in "postmanpat.exe" in "Postman Pat" by Compedia.
|
||||
if (strs.Exists(s => s.Contains("mfint.dll")))
|
||||
|
||||
@@ -33,13 +33,13 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// TODO: Check for CVP* instead?
|
||||
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"));
|
||||
|
||||
// Get the .rdata section strings, if they exist
|
||||
bool containsCheck2 = false;
|
||||
var strs = exe.GetFirstSectionStrings(".rdata");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
containsCheck2 = strs.Exists(s => s.EndsWith("ATTLIST"))
|
||||
&& strs.Exists(s => s.Equals("ELEMENT"))
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Text.RegularExpressions;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
public class InterLok : IExecutableCheck<PortableExecutable>
|
||||
@@ -11,13 +12,13 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// Get the .rsrc section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(".rsrc");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// Found in "nfsc_link.exe" in IA item "nfscorigin".
|
||||
// Full string:
|
||||
// (: ) 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"));
|
||||
if (match != null)
|
||||
if (match is not null)
|
||||
return $"PACE Anti-Piracy InterLok {GetVersion(match)}";
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace BinaryObjectScanner.Protection
|
||||
if (exe.ContainsSection(".dcrtext") && importTableMatches)
|
||||
{
|
||||
var dcrtextData = exe.GetFirstSectionData(".dcrtext");
|
||||
if (dcrtextData != null)
|
||||
if (dcrtextData is not null)
|
||||
{
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
@@ -63,7 +63,7 @@ namespace BinaryObjectScanner.Protection
|
||||
private static string? GetVersion(string file, byte[]? fileContent, List<int> positions)
|
||||
{
|
||||
// If we have no content
|
||||
if (fileContent == null)
|
||||
if (fileContent is null)
|
||||
return null;
|
||||
|
||||
return Encoding.ASCII.GetString(fileContent, positions[0] + 67, 8);
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .text section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(".rdata");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// Found in "TFT.exe" in Redump entry 95617.
|
||||
if (strs.Exists(s => s.Contains("@KalypsoLauncherXml")))
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
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).
|
||||
if (strs.Exists(s => s.Contains("LGCD2_LAUNCH")))
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace BinaryObjectScanner.Protection
|
||||
return null;
|
||||
|
||||
string? finalString = reserved653Bytes.ReadNullTerminatedAnsiString(ref firstNonZero);
|
||||
if (finalString == null)
|
||||
if (finalString is null)
|
||||
return null;
|
||||
|
||||
// Redump ID 113120
|
||||
@@ -189,7 +189,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
private static string GetBuild(byte[]? sectionContent, bool versionTwo)
|
||||
{
|
||||
if (sectionContent == null)
|
||||
if (sectionContent is null)
|
||||
return "(Build unknown)";
|
||||
|
||||
// Unkown + (char)0x00 + Unkown
|
||||
@@ -214,7 +214,7 @@ namespace BinaryObjectScanner.Protection
|
||||
private static string? GetVersion(byte[]? sectionContent, int position)
|
||||
{
|
||||
// If we have invalid data
|
||||
if (sectionContent == null)
|
||||
if (sectionContent is null)
|
||||
return null;
|
||||
|
||||
return Encoding.ASCII.GetString(sectionContent, position + 76, 4);
|
||||
|
||||
@@ -5,6 +5,7 @@ using SabreTools.IO.Extensions;
|
||||
using SabreTools.IO.Matching;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
#pragma warning disable IDE0060 // Remove unused parameter
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
/// <summary>
|
||||
@@ -56,7 +57,6 @@ namespace BinaryObjectScanner.Protection
|
||||
// File Description "C-Dilla Windows NT RTS" in "CDILLA05.DLL"/"CDILLA10.EXE"/"CDILLA16.EXE" from C-Dilla LMS version 3.27.000 for Windows NT.
|
||||
// File Description "C-Dilla Windows 16-Bit RTS Installer" in "CdaIns16.dll"/"CdSetup.exe" from C-Dilla LMS version 3.27.000.
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// Found in "DJMixStation\DJMixStation.exe" in IA item "ejay_nestle_trial".
|
||||
if (strs.Exists(s => s.Contains("SOFTWARE\\C-Dilla\\RTS")))
|
||||
|
||||
@@ -7,6 +7,7 @@ using SabreTools.IO.Extensions;
|
||||
using SabreTools.IO.Matching;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
#pragma warning disable IDE0060 // Remove unused parameter
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
/// <summary>
|
||||
@@ -35,7 +36,7 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("\\*.CDS")))
|
||||
return "Cactus Data Shield 200";
|
||||
@@ -113,7 +114,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public static string GetCactusDataShieldVersion(string firstMatchedString, List<string>? files)
|
||||
{
|
||||
// If we have no files
|
||||
if (files == null)
|
||||
if (files is null)
|
||||
return string.Empty;
|
||||
|
||||
// Find the version.txt file first
|
||||
@@ -137,7 +138,7 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
using var sr = new StreamReader(path, Encoding.Default);
|
||||
var line = sr.ReadLine();
|
||||
if (line == null)
|
||||
if (line is null)
|
||||
return null;
|
||||
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
|
||||
@@ -5,6 +5,7 @@ using SabreTools.IO.Extensions;
|
||||
using SabreTools.IO.Matching;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
#pragma warning disable IDE0060 // Remove unused parameter
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
/// <summary>
|
||||
@@ -53,7 +54,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// Found in "FLEXLM.CPL", "INSTALLS.EXE", "LMGR326B.DLL", "LMGRD.EXE", and "TAKEFIVE.EXE" in IA item "prog-17_202403".
|
||||
if (strs.Exists(s => s.Contains("FLEXlm License Manager")))
|
||||
|
||||
@@ -6,6 +6,7 @@ using SabreTools.IO.Extensions;
|
||||
using SabreTools.IO.Matching;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
#pragma warning disable IDE0060 // Remove unused parameter
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -6,6 +6,7 @@ using SabreTools.IO.Extensions;
|
||||
using SabreTools.IO.Matching;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
#pragma warning disable IDE0060 // Remove unused parameter
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
/// <summary>
|
||||
@@ -43,10 +44,10 @@ namespace BinaryObjectScanner.Protection
|
||||
internal static string? SafeCastCheckExecutable(string file, NewExecutable exe, bool includeDebug)
|
||||
{
|
||||
// Check for the CDAC01AA name string.
|
||||
if (exe.ResidentNameTable != null)
|
||||
if (exe.ResidentNameTable is not null)
|
||||
{
|
||||
var residentNames = 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));
|
||||
if (Array.Exists(residentNames, s => s.Contains("CDAC01AA")))
|
||||
return "SafeCast";
|
||||
}
|
||||
@@ -54,7 +55,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// TODO: Don't read entire file
|
||||
#pragma warning disable CS0618
|
||||
byte[]? data = exe.ReadArbitraryRange();
|
||||
if (data == null)
|
||||
if (data is null)
|
||||
return null;
|
||||
|
||||
var neMatchSets = new List<ContentMatchSet>
|
||||
@@ -75,10 +76,10 @@ namespace BinaryObjectScanner.Protection
|
||||
// TODO: Invesitgate if the "AdobeLM.dll" file (along with mentions of "AdobeLM" in executables) uniquely identifies SafeCast, or if it can be used with different DRM. (Found in IA item ccd0605)
|
||||
|
||||
// Get the import directory table, if it exists
|
||||
if (exe.ImportDirectoryTable != null)
|
||||
if (exe.ImportDirectoryTable is not null)
|
||||
{
|
||||
if (Array.Exists(exe.ImportDirectoryTable,
|
||||
idte => idte?.Name != null && idte.Name.Equals("CdaC14BA.dll", StringComparison.OrdinalIgnoreCase)))
|
||||
idte => idte?.Name is not null && idte.Name.Equals("CdaC14BA.dll", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
return "SafeCast";
|
||||
}
|
||||
@@ -91,7 +92,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// Found in "DJMixStation\DJMixStation.exe" in IA item "ejay_nestle_trial".
|
||||
if (strs.Exists(s => s.Contains("SOFTWARE\\C-Dilla\\SafeCast")))
|
||||
|
||||
@@ -7,6 +7,7 @@ using SabreTools.IO.Extensions;
|
||||
using SabreTools.IO.Matching;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
#pragma warning disable IDE0060 // Remove unused parameter
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
/// <summary>
|
||||
@@ -52,14 +53,14 @@ namespace BinaryObjectScanner.Protection
|
||||
internal static string? SafeDiscCheckExecutable(string file, PortableExecutable exe, bool includeDebug)
|
||||
{
|
||||
// Found in Redump entry 57986.
|
||||
if (exe.ImportHintNameTable != null)
|
||||
if (exe.ImportHintNameTable is not null)
|
||||
{
|
||||
if (Array.Exists(exe.ImportHintNameTable, ihne => ihne?.Name == "LTDLL_Authenticate"))
|
||||
return "SafeDisc Lite";
|
||||
}
|
||||
|
||||
// Found in Redump entry 57986.
|
||||
if (exe.ImportDirectoryTable != null)
|
||||
if (exe.ImportDirectoryTable is not null)
|
||||
{
|
||||
if (Array.Exists(exe.ImportDirectoryTable, idte => idte?.Name == "ltdll.dll"))
|
||||
return "SafeDisc Lite";
|
||||
@@ -67,7 +68,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// Found in Redump entries 14928, 25579, 32751.
|
||||
if (strs.Exists(s => s.Contains("LTDLL_Initialise")))
|
||||
@@ -313,7 +314,6 @@ namespace BinaryObjectScanner.Protection
|
||||
new(new FilePathMatch("00001009.016"), GetSafeDiscSplshVersion, "SafeDisc"),
|
||||
new(new FilePathMatch("00001009.256"), GetSafeDiscSplshVersion, "SafeDisc"),
|
||||
|
||||
|
||||
new(new FilePathMatch("DPLAYERX.DLL"), GetSafeDiscDPlayerXVersion, "SafeDisc"),
|
||||
new(new FilePathMatch("drvmgt.dll"), GetSafeDiscDrvmgtVersion, "SafeDisc"),
|
||||
|
||||
@@ -715,7 +715,6 @@ namespace BinaryObjectScanner.Protection
|
||||
// "1.1.43 1999/02/25 -> SafeDisc 1.01.043 (Redump entries 34562 and 63304).
|
||||
// "1.1.44 1999/03/08" -> SafeDisc 1.01.044 (Redump entries 61731 and 81619).
|
||||
|
||||
|
||||
// The hash of every "CLOKSPL.EXE" correlates directly to a specific SafeDisc version.
|
||||
var sha1 = HashTool.GetFileHash(firstMatchedString, HashType.SHA1);
|
||||
return sha1?.ToUpperInvariant() switch
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
#pragma warning disable CA1822 // Mark members as static
|
||||
#pragma warning disable IDE0060 // Remove unused parameter
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -8,6 +8,7 @@ using SabreTools.IO.Extensions;
|
||||
using SabreTools.IO.Matching;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
#pragma warning disable IDE0060 // Remove unused parameter
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
/// <summary>
|
||||
@@ -27,6 +28,26 @@ namespace BinaryObjectScanner.Protection
|
||||
if (diskImage.VolumeDescriptorSet[0] is not PrimaryVolumeDescriptor pvd)
|
||||
return null;
|
||||
|
||||
var applicationUse = pvd.ApplicationUse;
|
||||
var reserved653Bytes = pvd.Reserved653Bytes;
|
||||
|
||||
#region RipGuard
|
||||
|
||||
// Macrovision RipGuard protected DVDs have the string "MVSNRGFP" at the start of the application use, followed
|
||||
// by some other data. The meaning of the rest of the data is unknown, but ultimately not necessary to check.
|
||||
// Meaning of string unknown. Best guess is "Macrovision RipGuard (File?) Protection"
|
||||
// While not checked, this string plus a similar-looking block of data appear near the very end of the image
|
||||
// as well. Possibly part of another standard ISO9660 field?
|
||||
byte[] ripGuardBytes = [0x4D, 0x56, 0x53, 0x4E, 0x52, 0x47, 0x46, 0x50]; // MVSNRGFP
|
||||
int offset = 0;
|
||||
var compareBytes = applicationUse.ReadBytes(ref offset, 8);
|
||||
if (compareBytes.EqualsExactly(ripGuardBytes))
|
||||
return "Macrovision RipGuard";
|
||||
|
||||
#endregion RipGuard
|
||||
|
||||
#region SafeDisc
|
||||
|
||||
if (!FileType.ISO9660.NoteworthyApplicationUse(pvd))
|
||||
return null;
|
||||
|
||||
@@ -36,12 +57,9 @@ namespace BinaryObjectScanner.Protection
|
||||
if (!FileType.ISO9660.NoteworthyReserved653Bytes(pvd))
|
||||
return null;
|
||||
|
||||
var applicationUse = pvd.ApplicationUse;
|
||||
var reserved653Bytes = pvd.Reserved653Bytes;
|
||||
|
||||
#region Read Application Use
|
||||
|
||||
int offset = 0;
|
||||
offset = 0;
|
||||
var appUseZeroBytes = applicationUse.ReadBytes(ref offset, 256);
|
||||
var appUseDataBytesOne = applicationUse.ReadBytes(ref offset, 128);
|
||||
offset += 64; // Some extra values get added here over time. Check is good enough, easier to skip this.
|
||||
@@ -83,6 +101,8 @@ namespace BinaryObjectScanner.Protection
|
||||
return null;
|
||||
|
||||
return "SafeDisc";
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -100,7 +120,7 @@ namespace BinaryObjectScanner.Protection
|
||||
if (!string.IsNullOrEmpty(safeCast))
|
||||
resultsList.Add(safeCast!);
|
||||
|
||||
if (resultsList != null && resultsList.Count > 0)
|
||||
if (resultsList is not null && resultsList.Count > 0)
|
||||
return string.Join(";", [.. resultsList]);
|
||||
|
||||
return null;
|
||||
@@ -136,12 +156,12 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// Check the header padding for protected sections.
|
||||
var sectionMatch = CheckSectionForProtection(file, includeDebug, exe.HeaderPaddingStrings, exe.HeaderPaddingData, true);
|
||||
if (sectionMatch != null)
|
||||
if (sectionMatch is not null)
|
||||
resultsList.Add(sectionMatch);
|
||||
|
||||
// Get the .data section, if it exists, for protected sections.
|
||||
sectionMatch = CheckSectionForProtection(file, includeDebug, exe.GetFirstSectionStrings(".data"), exe.GetFirstSectionData(".data"), true);
|
||||
if (sectionMatch != null)
|
||||
if (sectionMatch is not null)
|
||||
resultsList.Add(sectionMatch!);
|
||||
|
||||
int entryPointIndex = exe.FindEntryPointSectionIndex();
|
||||
@@ -169,12 +189,12 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// Check the header padding for protected sections.
|
||||
var sectionMatch = CheckSectionForProtection(file, includeDebug, exe.HeaderPaddingStrings, exe.HeaderPaddingData, false);
|
||||
if (sectionMatch != null)
|
||||
if (sectionMatch is not null)
|
||||
resultsList.Add(sectionMatch);
|
||||
|
||||
// Check the .data section, if it exists, for protected sections.
|
||||
sectionMatch = CheckSectionForProtection(file, includeDebug, exe.GetFirstSectionStrings(".data"), exe.GetFirstSectionData(".data"), false);
|
||||
if (sectionMatch != null)
|
||||
if (sectionMatch is not null)
|
||||
resultsList.Add(sectionMatch);
|
||||
}
|
||||
|
||||
@@ -210,7 +230,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Clean the result list
|
||||
resultsList = CleanResultList(resultsList);
|
||||
if (resultsList != null && resultsList.Count > 0)
|
||||
if (resultsList is not null && resultsList.Count > 0)
|
||||
return string.Join(";", [.. resultsList]);
|
||||
|
||||
return null;
|
||||
@@ -223,40 +243,40 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Run Macrovision directory checks
|
||||
var macrovision = MacrovisionCheckDirectoryPath(path, files);
|
||||
if (macrovision != null)
|
||||
if (macrovision is not null)
|
||||
results.AddRange(macrovision);
|
||||
|
||||
// Run Cactus Data Shield directory checks
|
||||
var cactusDataShield = CactusDataShieldCheckDirectoryPath(path, files);
|
||||
if (cactusDataShield != null)
|
||||
if (cactusDataShield is not null)
|
||||
results.AddRange(cactusDataShield);
|
||||
|
||||
// Run C-Dilla directory checks
|
||||
var cDilla = CDillaCheckDirectoryPath(path, files);
|
||||
if (cDilla != null)
|
||||
if (cDilla is not null)
|
||||
results.AddRange(cDilla);
|
||||
|
||||
// Run FLEXnet directory checks
|
||||
var flexNet = FLEXNetCheckDirectoryPath(path, files);
|
||||
if (flexNet != null)
|
||||
if (flexNet is not null)
|
||||
results.AddRange(flexNet);
|
||||
|
||||
// Run RipGuard directory checks
|
||||
var ripGuard = RipGuardCheckDirectoryPath(path, files);
|
||||
if (ripGuard != null)
|
||||
if (ripGuard is not null)
|
||||
results.AddRange(ripGuard);
|
||||
|
||||
// Run SafeCast directory checks
|
||||
var safeCast = SafeCastCheckDirectoryPath(path, files);
|
||||
if (safeCast != null)
|
||||
if (safeCast is not null)
|
||||
results.AddRange(safeCast);
|
||||
|
||||
// Run SafeDisc directory checks
|
||||
var safeDisc = SafeDiscCheckDirectoryPath(path, files);
|
||||
if (safeDisc != null)
|
||||
if (safeDisc is not null)
|
||||
results.AddRange(safeDisc);
|
||||
|
||||
if (results != null && results.Count > 0)
|
||||
if (results is not null && results.Count > 0)
|
||||
return results;
|
||||
|
||||
return [];
|
||||
@@ -304,7 +324,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Clean the result list
|
||||
resultsList = CleanResultList(resultsList);
|
||||
if (resultsList != null && resultsList.Count > 0)
|
||||
if (resultsList is not null && resultsList.Count > 0)
|
||||
return string.Join(";", [.. resultsList]);
|
||||
|
||||
return null;
|
||||
@@ -498,7 +518,7 @@ namespace BinaryObjectScanner.Protection
|
||||
private static string? CheckSectionForProtection(string file, bool includeDebug, List<string>? sectionStrings, byte[]? sectionRaw, bool newVersion)
|
||||
{
|
||||
// Get the section strings, if they exist
|
||||
if (sectionStrings != null)
|
||||
if (sectionStrings is not null)
|
||||
{
|
||||
// If we don't have the "BoG_" string, the section isn't protected.
|
||||
if (!sectionStrings.Exists(s => s.Contains("BoG_")))
|
||||
@@ -524,7 +544,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
// Get the section data, if it exists
|
||||
if (sectionRaw != null)
|
||||
if (sectionRaw is not null)
|
||||
{
|
||||
// TODO: Add more checks to help differentiate between SafeDisc and SafeCast.
|
||||
var matchers = new List<ContentMatchSet>
|
||||
@@ -547,7 +567,7 @@ namespace BinaryObjectScanner.Protection
|
||||
internal static string? GetMacrovisionVersion(string file, byte[]? fileContent, List<int> positions)
|
||||
{
|
||||
// If we have no content
|
||||
if (fileContent == null)
|
||||
if (fileContent is null)
|
||||
return null;
|
||||
|
||||
// Begin reading 2 bytes after "BoG_ *90.0&!! Yy>" for older versions
|
||||
@@ -831,7 +851,7 @@ namespace BinaryObjectScanner.Protection
|
||||
private static List<string>? CleanResultList(List<string>? resultsList)
|
||||
{
|
||||
// If we have an invalid result list
|
||||
if (resultsList == null || resultsList.Count == 0)
|
||||
if (resultsList is null || resultsList.Count == 0)
|
||||
return resultsList;
|
||||
|
||||
// Remove duplicates
|
||||
|
||||
@@ -41,14 +41,14 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("CD3 Launch Error")))
|
||||
return "MediaMax CD-3";
|
||||
}
|
||||
|
||||
// Get the export name table
|
||||
if (exe.ExportNameTable?.Strings != null)
|
||||
if (exe.ExportNameTable?.Strings is not null)
|
||||
{
|
||||
if (Array.Exists(exe.ExportNameTable.Strings, s => s == "DllInstallSbcp"))
|
||||
return "MediaMax CD-3";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
public class phenoProtect
|
||||
public class PhenoProtect
|
||||
{
|
||||
// Currently implemented as a text file check, more checks are likely possible but currently unknown.
|
||||
// Current checks based off Redump entry 84082 are found in the InstallShield setup.inx file, but the game also checks if the original disc is present in the drive after installation as well, so it seems unlikely for the InstallShield check to be relevant at that stage.
|
||||
@@ -9,6 +9,7 @@ using SabreTools.IO.Extensions;
|
||||
using SabreTools.IO.Matching;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// This protection was called VOB ProtectCD / ProtectDVD in versions prior to 6
|
||||
@@ -29,7 +30,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
int offset = 0;
|
||||
var copyrightString = pvd.CopyrightFileIdentifier.ReadNullTerminatedAnsiString(ref offset);
|
||||
if (copyrightString == null || copyrightString.Length < 19)
|
||||
if (copyrightString is null || copyrightString.Length < 19)
|
||||
return null;
|
||||
|
||||
// Redump ID 15896 has a trailing space
|
||||
@@ -51,11 +52,14 @@ namespace BinaryObjectScanner.Protection
|
||||
// 7.5.0.61324 and 9.0.1119. ProtectDiSC versioning is very confusing, so this is not the "actual" version
|
||||
// number and should not be printed.
|
||||
// Previous versions just have spaces here, so it doesn't need to be validated beyond that.
|
||||
var abstractIdentifierString = pvd.AbstractFileIdentifier.ReadNullTerminatedAnsiString(ref offset);
|
||||
if (abstractIdentifierString == null || abstractIdentifierString.Trim().Length == 0)
|
||||
return "ProtectDiSC 6-7.x";
|
||||
// Some ProtectDiSC 6 discs also have version number, such as RID 114936 having 1.1.2286.18916, and
|
||||
// 131176 having 1.1.2162.19023. The below check is commented out because there's likely something that
|
||||
// can be done with it, it's just difficult to do anything while ProtectDiSC versioning is still unclear.
|
||||
/*var abstractIdentifierString = pvd.AbstractFileIdentifier.ReadNullTerminatedAnsiString(ref offset);
|
||||
if (abstractIdentifierString is null || abstractIdentifierString.Trim().Length == 0)
|
||||
return "ProtectDiSC 6-7.x";*/
|
||||
|
||||
return "ProtectDiSC 7.x+";
|
||||
return "ProtectDiSC 6+";
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -64,11 +68,11 @@ namespace BinaryObjectScanner.Protection
|
||||
// TODO: Investigate if this can be found by aligning to section containing entry point
|
||||
|
||||
// Get the 4th and 5th sections, if they exist (example names: ACE4/ACE5) (Found in Redump entries 94792, 94793)
|
||||
var sections = exe.SectionTable ?? [];
|
||||
var sections = exe.SectionTable;
|
||||
for (int i = 3; i < sections.Length; i++)
|
||||
{
|
||||
var nthSectionData = exe.GetSectionData(i);
|
||||
if (nthSectionData == null)
|
||||
if (nthSectionData is null)
|
||||
continue;
|
||||
|
||||
var matchers = new List<ContentMatchSet>
|
||||
@@ -84,7 +88,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .data/DATA section, if it exists
|
||||
var dataSectionRaw = exe.GetFirstSectionData(".data") ?? exe.GetFirstSectionData("DATA");
|
||||
if (dataSectionRaw != null)
|
||||
if (dataSectionRaw is not null)
|
||||
{
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
@@ -104,10 +108,10 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// Get the n - 1 section strings, if they exist
|
||||
var strs = exe.GetSectionStrings(sections.Length - 2);
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
var str = strs.Find(s => s.Contains("VOB ProtectCD"));
|
||||
if (str != null)
|
||||
if (str is not null)
|
||||
return $"VOB ProtectCD {GetOldVersion(str)}";
|
||||
}
|
||||
}
|
||||
@@ -118,7 +122,7 @@ namespace BinaryObjectScanner.Protection
|
||||
if (sections.Length > 0)
|
||||
{
|
||||
var lastSectionData = exe.GetSectionData(sections.Length - 1);
|
||||
if (lastSectionData != null)
|
||||
if (lastSectionData is not null)
|
||||
{
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
@@ -201,7 +205,7 @@ namespace BinaryObjectScanner.Protection
|
||||
private static string? GetVersion3till6(string file, byte[]? fileContent, List<int> positions)
|
||||
{
|
||||
// If we have no content
|
||||
if (fileContent == null)
|
||||
if (fileContent is null)
|
||||
return null;
|
||||
|
||||
string version = GetVOBVersion(fileContent, positions[0]);
|
||||
@@ -214,7 +218,7 @@ namespace BinaryObjectScanner.Protection
|
||||
private static string? GetVersion6till8(string file, byte[]? fileContent, List<int> positions)
|
||||
{
|
||||
// If we have no content
|
||||
if (fileContent == null)
|
||||
if (fileContent is null)
|
||||
return null;
|
||||
|
||||
string version;
|
||||
@@ -270,7 +274,7 @@ namespace BinaryObjectScanner.Protection
|
||||
private static string? GetVersion76till10(string file, byte[]? fileContent, List<int> positions)
|
||||
{
|
||||
// If we have no content
|
||||
if (fileContent == null)
|
||||
if (fileContent is null)
|
||||
return null;
|
||||
|
||||
int index = positions[0] + 37;
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public List<string> CheckDirectoryPath(string path, List<string>? files)
|
||||
{
|
||||
var protections = new List<string>();
|
||||
if (files == null)
|
||||
if (files is null)
|
||||
return protections;
|
||||
|
||||
if (Directory.Exists(Path.Combine(path, "VIDEO_TS")))
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// TODO: Don't read entire file
|
||||
#pragma warning disable CS0618
|
||||
byte[]? data = exe.ReadArbitraryRange();
|
||||
if (data == null)
|
||||
if (data is null)
|
||||
return null;
|
||||
|
||||
// TODO: Figure out what NE section this lives in
|
||||
@@ -107,7 +107,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the resident and non-resident name table strings
|
||||
var nrntStrs = Array.ConvertAll(exe.NonResidentNameTable ?? [],
|
||||
rnte => rnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(rnte.NameString));
|
||||
rnte => rnte?.NameString is null ? string.Empty : Encoding.ASCII.GetString(rnte.NameString));
|
||||
|
||||
// Check the nonresident-name table
|
||||
// Found in "SSWIN.dll" in IA item "pcwkcd-1296".
|
||||
@@ -196,7 +196,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// Found in "ADESKSYS.DLL"/"WINADMIN.EXE"/"WINQUERY.EXE" in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]", folder "\netsetup\SUPPORT\IPX".
|
||||
if (strs.Exists(s => s.Contains("Rainbow SentinelSuperPro")))
|
||||
@@ -209,7 +209,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .rdata section strings, if they exist
|
||||
strs = exe.GetFirstSectionStrings(".rdata");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// Found in "SP32W.DLL" in IA item "pcwkcd-1296".
|
||||
if (strs.Exists(s => s.Contains("SentinelPro WIN32 DLL")))
|
||||
@@ -234,7 +234,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .rsrc section strings, if they exist
|
||||
strs = exe.GetFirstSectionStrings(".rsrc");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// Found in "WINMON.exe" in IA item "czchip199707cd".
|
||||
if (strs.Exists(s => s.Contains("NetSentinel Monitor")))
|
||||
@@ -243,7 +243,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .text section strings, if they exist
|
||||
strs = exe.GetFirstSectionStrings(".text");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// Found in "ACLT.HWL" in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]", folder "\aclt\DRV\W95LOCK".
|
||||
// Found in "ACAD.HWL" in BA entry "Autodesk AutoCAD r14 (1997)" and IA item "auto-cad-r14-cdrom".
|
||||
@@ -272,7 +272,6 @@ namespace BinaryObjectScanner.Protection
|
||||
return "Rainbow Sentinel";
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(".data") ?? exe.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// Found in "rebound.exe" in the installation directory for "Rebound" in IA item "Nova_RealArcadeCD_USA".
|
||||
if (strs.Exists(s => s.Contains("RngInterstitialDLL")))
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// Get the code/CODE section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings("code") ?? exe.GetFirstSectionStrings("CODE");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// Found in "Owar.exe" in IA item "game4u-22-cd".
|
||||
if (strs.Exists(s => s.Contains("TRCHANGER.INI")))
|
||||
@@ -28,7 +28,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// Get the .rsrc section strings, if they exist
|
||||
// TODO: Check for these strings specifically within the application-defined resource that they're found in, not just the generic resource section.
|
||||
strs = exe.GetFirstSectionStrings(".rsrc");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// Found in "Owar.exe" in IA items "game4u-22-cd" and "original-war".
|
||||
// These checks are less reliable, as they are still found in a version of the game that appears to have patched out Roxxe (the version present in IA item "original-war").
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// TODO: Investigate the "Debugger or tool for monitoring detected!!!.Application cannot be run with debugger or monitoring tool(s) loaded!. Please unload it and restart the application" strings present in seemingly every version.
|
||||
|
||||
// Get the entry point data, if it exists.
|
||||
if (exe.EntryPointData != null)
|
||||
if (exe.EntryPointData is not null)
|
||||
{
|
||||
// Found in the SVKP 1.05 demo.
|
||||
if (exe.EntryPointData.StartsWith(new byte?[]
|
||||
|
||||
@@ -9,6 +9,7 @@ using SabreTools.IO.Matching;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
using static SabreTools.Data.Models.SecuROM.Constants;
|
||||
|
||||
#pragma warning disable IDE0059 // Unnecessary assignment of value
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// TODO: Investigate SecuROM for Macintosh
|
||||
@@ -22,6 +23,7 @@ namespace BinaryObjectScanner.Protection
|
||||
private static readonly Dictionary<string, string> MatroschkaHashDictionary = new()
|
||||
{
|
||||
{"C6DFF6B08EE126893840E107FD4EC9F6", "Alice - Madness Returns (USA)+(Europe)"},
|
||||
{"890C4DBDB7819D1FC73FE2105CED79FA", "Alice - Madness Returns (Steam v0)"},
|
||||
{"D7703D32B72185358D58448B235BD55E", "Arcania - Gothic 4 (Australia)"}, // International version (English, French, Italian, German, Spanish)
|
||||
// Arcania - Gothic 4 - Polish(/Hungarian?) - known to most likely exist. Likely matches support site exe.
|
||||
{"83CD6225899C08422F860095962287A5", "Arcania - Gothic 4 (Russia)"},
|
||||
@@ -243,15 +245,15 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// Check if executable is a SecuROM PA module
|
||||
var paModule = CheckProductActivation(exe);
|
||||
if (paModule != null)
|
||||
if (paModule is not null)
|
||||
return paModule;
|
||||
|
||||
// Check if executable contains a SecuROM Matroschka Package
|
||||
var package = exe.MatroschkaPackage;
|
||||
if (package != null)
|
||||
if (package is not null)
|
||||
{
|
||||
var packageType = CheckMatroschkaPackage(package, includeDebug);
|
||||
if (packageType != null)
|
||||
if (packageType is not null)
|
||||
return packageType;
|
||||
}
|
||||
|
||||
@@ -285,24 +287,24 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Search after the last section
|
||||
string? v4Version = GetV4Version(exe);
|
||||
if (v4Version != null)
|
||||
if (v4Version is not null)
|
||||
return $"SecuROM {v4Version}";
|
||||
|
||||
// TODO: Investigate if this can be found by aligning to section containing entry point
|
||||
|
||||
// Get the sections 5+, if they exist (example names: .fmqyrx, .vcltz, .iywiak)
|
||||
var sections = exe.SectionTable ?? [];
|
||||
var sections = exe.SectionTable;
|
||||
for (int i = 4; i < sections.Length; i++)
|
||||
{
|
||||
var nthSection = sections[i];
|
||||
if (nthSection == null)
|
||||
if (nthSection is null)
|
||||
continue;
|
||||
|
||||
string nthSectionName = Encoding.ASCII.GetString(nthSection.Name ?? []).TrimEnd('\0');
|
||||
if (nthSectionName != ".idata" && nthSectionName != ".rsrc")
|
||||
{
|
||||
var nthSectionData = exe.GetFirstSectionData(nthSectionName);
|
||||
if (nthSectionData == null)
|
||||
if (nthSectionData is null)
|
||||
continue;
|
||||
|
||||
var matchers = new List<ContentMatchSet>
|
||||
@@ -319,7 +321,7 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Get the .rdata section strings, if they exist
|
||||
var strs = exe.GetFirstSectionStrings(".rdata");
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
// Both have the identifier found within `.rdata` but the version is within `.data`
|
||||
if (strs.Exists(s => s.Contains("/secuexp")))
|
||||
@@ -397,7 +399,7 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// Cache the overlay data for easier access
|
||||
var overlayData = exe.OverlayData;
|
||||
if (overlayData == null || overlayData.Length < 20)
|
||||
if (overlayData is null || overlayData.Length < 20)
|
||||
return null;
|
||||
|
||||
// Search for the "AddD" string in the overlay
|
||||
@@ -421,7 +423,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// Deserialize the AddD header
|
||||
var reader = new SabreTools.Serialization.Readers.SecuROMAddD();
|
||||
var addD = reader.Deserialize(overlayData, index);
|
||||
if (addD == null)
|
||||
if (addD is null)
|
||||
return null;
|
||||
|
||||
// All samples have had 3 entries -- Revisit if needed
|
||||
@@ -443,7 +445,7 @@ namespace BinaryObjectScanner.Protection
|
||||
private static string? GetV5Version(string file, byte[]? fileContent, List<int> positions)
|
||||
{
|
||||
// If we have no content
|
||||
if (fileContent == null)
|
||||
if (fileContent is null)
|
||||
return null;
|
||||
|
||||
int index = positions[0] + 8; // Begin reading after "ÊÝݬ"
|
||||
@@ -485,7 +487,7 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// If SecuROM is stripped, the MS-DOS stub might be shorter.
|
||||
// We then know that SecuROM -was- there, but we don't know what exact version.
|
||||
if (exe.StubExecutableData == null)
|
||||
if (exe.StubExecutableData is null)
|
||||
return "7 remnants";
|
||||
|
||||
//SecuROM 7 new and 8 -- 64 bytes for DOS stub, 236 bytes in total
|
||||
@@ -523,7 +525,7 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// Get the .data/DATA section, if it exists
|
||||
var dataSectionRaw = exe.GetFirstSectionData(".data") ?? exe.GetFirstSectionData("DATA");
|
||||
if (dataSectionRaw == null)
|
||||
if (dataSectionRaw is null)
|
||||
return "8";
|
||||
|
||||
// Search .data for the version indicator
|
||||
@@ -556,16 +558,16 @@ namespace BinaryObjectScanner.Protection
|
||||
private static string? CheckMatroschkaPackage(SecuROMMatroschkaPackage package, bool includeDebug)
|
||||
{
|
||||
// Check for all 0x00 required, as at least one known non-RC matroschka has the field, just empty.
|
||||
if (package.KeyHexString == null || package.KeyHexString.Trim('\0').Length == 0)
|
||||
if (package.KeyHexString is null || package.KeyHexString.Trim('\0').Length == 0)
|
||||
return "SecuROM Matroschka Package";
|
||||
|
||||
if (package.Entries == null || package.Entries.Length == 0)
|
||||
if (package.Entries is null || package.Entries.Length == 0)
|
||||
return "SecuROM Matroschka Package - No Entries? - Please report to us on GitHub";
|
||||
|
||||
// The second entry in a Release Control matroschka package is always the encrypted executable
|
||||
var entry = package.Entries[1];
|
||||
|
||||
if (entry.MD5 == null || entry.MD5.Length == 0)
|
||||
if (entry.MD5 is null || entry.MD5.Length == 0)
|
||||
return "SecuROM Matroschka Package - No MD5? - Please report to us on GitHub";
|
||||
|
||||
string md5String = BitConverter.ToString(entry.MD5!);
|
||||
@@ -581,7 +583,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// If not known, check if encrypted executable is likely an alt signing of a known executable
|
||||
// Filetime could be checked here, but if it was signed at a different time, the time will vary anyways
|
||||
var readPath = entry.Path;
|
||||
if (readPath == null || readPath.Length == 0)
|
||||
if (readPath is null || readPath.Length == 0)
|
||||
return $"SecuROM Release Control - Unknown executable {md5String},{entry.Size} - Please report to us on GitHub!";
|
||||
|
||||
var readPathName = readPath.TrimEnd('\0');
|
||||
|
||||
@@ -19,12 +19,12 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// TODO: Investigate if this can be found by aligning to section containing entry point
|
||||
|
||||
var sections = exe.SectionTable ?? [];
|
||||
var sections = exe.SectionTable;
|
||||
if (sections.Length > 0)
|
||||
{
|
||||
// Get the last section data, if it exists
|
||||
var lastSectionData = exe.GetSectionData(sections.Length - 1);
|
||||
if (lastSectionData != null)
|
||||
if (lastSectionData is not null)
|
||||
{
|
||||
// All sections seen so far are the last sections, so this is "technically"
|
||||
// the only known needed check so far. Others kept as backups if this fails
|
||||
|
||||
@@ -38,6 +38,13 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
name = exe.ProductName;
|
||||
|
||||
// Only observed with Solidshield 3.0.0.0 games such as Redump ID 119211. Extracted from main executable.
|
||||
if (exe.FileDescription.OptionalStartsWith("CORE Library", StringComparison.OrdinalIgnoreCase)
|
||||
&& name.OptionalStartsWith("Solidshield", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return $"SolidShield {exe.GetInternalVersion()}";
|
||||
}
|
||||
|
||||
if (name.OptionalStartsWith("Solidshield Activation Library", StringComparison.OrdinalIgnoreCase))
|
||||
return $"SolidShield Core.dll {exe.GetInternalVersion()}";
|
||||
else if (name.OptionalStartsWith("Solidshield Library", StringComparison.OrdinalIgnoreCase))
|
||||
@@ -54,7 +61,7 @@ namespace BinaryObjectScanner.Protection
|
||||
if (exe.ContainsSection(".init"))
|
||||
{
|
||||
var initData = exe.GetFirstSectionData(".init");
|
||||
if (initData != null)
|
||||
if (initData is not null)
|
||||
{
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
@@ -78,15 +85,15 @@ namespace BinaryObjectScanner.Protection
|
||||
// TODO: Investigate if this can be found by aligning to section containing entry point
|
||||
|
||||
// Search the last two available sections
|
||||
var sections = exe.SectionTable ?? [];
|
||||
var sections = exe.SectionTable;
|
||||
for (int i = Math.Max(sections.Length - 2, 0); i < sections.Length; i++)
|
||||
{
|
||||
// Get the nth section strings, if they exist
|
||||
var strs = exe.GetSectionStrings(i);
|
||||
if (strs != null)
|
||||
if (strs is not null)
|
||||
{
|
||||
var str = strs.Find(s => s.Contains("Solidshield "));
|
||||
if (str != null)
|
||||
if (str is not null)
|
||||
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
|
||||
return $"SolidShield EXE Wrapper {str["Solidshield ".Length..]}";
|
||||
#else
|
||||
@@ -96,7 +103,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
// Get the import directory table, if it exists
|
||||
if (exe.ImportDirectoryTable != null)
|
||||
if (exe.ImportDirectoryTable is not null)
|
||||
{
|
||||
if (Array.Exists(exe.ImportDirectoryTable, idte => idte?.Name == "dvm.dll"))
|
||||
return "SolidShield EXE Wrapper v1";
|
||||
@@ -153,7 +160,7 @@ namespace BinaryObjectScanner.Protection
|
||||
private static string? GetExeWrapperVersion(string file, byte[]? fileContent, List<int> positions)
|
||||
{
|
||||
// If we have no content
|
||||
if (fileContent == null)
|
||||
if (fileContent is null)
|
||||
return null;
|
||||
|
||||
int position = positions[0];
|
||||
@@ -180,7 +187,7 @@ namespace BinaryObjectScanner.Protection
|
||||
private static string? GetVersionPlusTages(string file, byte[]? fileContent, List<int> positions)
|
||||
{
|
||||
// If we have no content
|
||||
if (fileContent == null)
|
||||
if (fileContent is null)
|
||||
return null;
|
||||
|
||||
int position = positions[0];
|
||||
|
||||
@@ -8,6 +8,7 @@ using SabreTools.IO.Extensions;
|
||||
using SabreTools.IO.Matching;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
#pragma warning disable SYSLIB1045 // Convert to 'GeneratedRegexAttribute'
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
public class StarForce : IDiskImageCheck<ISO9660>, IExecutableCheck<PortableExecutable>, IPathCheck
|
||||
@@ -34,7 +35,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// StarForce Keyless check: the key is stored in the Data Preparer identifier.
|
||||
string? dataPreparerIdentiferString = pvd.DataPreparerIdentifier.ReadNullTerminatedAnsiString(ref offset)?.Trim();
|
||||
|
||||
if (dataPreparerIdentiferString != null
|
||||
if (dataPreparerIdentiferString is not null
|
||||
&& dataPreparerIdentiferString.Length != 0
|
||||
&& Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9-]*$", RegexOptions.Compiled))
|
||||
{
|
||||
@@ -45,11 +46,12 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// Thus far, the StarForce Keyless key is always made up of a number of characters, all either capital letters or
|
||||
// numbers, sometimes with dashes in between. Thus far, 4 formats have been observed:
|
||||
// 24 characters has been observed on one single disc (RID 68149). Maybe one is a space?
|
||||
// XXXXXXXXXXXXXXXXXXXXXXXXX (25 characters)
|
||||
// XXXXX-XXXXX-XXXXX-XXXXX-XXXXX (25 characters, plus 4 dashes seperating 5 groups of 5)
|
||||
// XXXXXXXXXXXXXXXXXXXXXXXXXXXX (28 characters)
|
||||
// XXXX-XXXXXX-XXXXXX-XXXXXX-XXXXXX (28 characters, with 4 dashes)
|
||||
if (Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{25}$", RegexOptions.Compiled)
|
||||
if (Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{24,25}$", RegexOptions.Compiled)
|
||||
|| Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}$", RegexOptions.Compiled)
|
||||
|| Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{28}$", RegexOptions.Compiled)
|
||||
|| Regex.IsMatch(dataPreparerIdentiferString, "^[A-Z0-9]{4}-[A-Z0-9]{6}-[A-Z0-9]{6}-[A-Z0-9]{6}-[A-Z0-9]{6}$", RegexOptions.Compiled))
|
||||
@@ -167,7 +169,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// return $"StarForce {Tools.Utilities.GetInternalVersion(exe)}";
|
||||
|
||||
// Check the export name table
|
||||
if (exe.ExportNameTable?.Strings != null)
|
||||
if (exe.ExportNameTable?.Strings is not null)
|
||||
{
|
||||
// TODO: Should we just check for "PSA_*" instead of a single entry?
|
||||
if (Array.Exists(exe.ExportNameTable.Strings, s => s == "PSA_GetDiscLabel"))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user