mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-02-04 13:45:28 +00:00
Compare commits
131 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3de58ff05e | ||
|
|
6e409988a5 | ||
|
|
864fa8d3f8 | ||
|
|
622f36b056 | ||
|
|
efe144313b | ||
|
|
1e3aac6748 | ||
|
|
984ad1f642 | ||
|
|
b379e1781b | ||
|
|
e244d6939c | ||
|
|
b4a781acc7 | ||
|
|
eb7bbdde52 | ||
|
|
f470263196 | ||
|
|
3822cc41f2 | ||
|
|
f04cf25fa9 | ||
|
|
eb8b9daea8 | ||
|
|
33ecc246dc | ||
|
|
7d55c8224a | ||
|
|
0ccae4e4b7 | ||
|
|
1798371513 | ||
|
|
0858437196 | ||
|
|
ece758bf03 | ||
|
|
d9661cd03d | ||
|
|
682529d7ba | ||
|
|
27ef24636c | ||
|
|
f5f3d3d29a | ||
|
|
550fb70952 | ||
|
|
7d6248a3bf | ||
|
|
4575da77bd | ||
|
|
a85aa08117 | ||
|
|
667207761c | ||
|
|
92097222b0 | ||
|
|
5ec90b290a | ||
|
|
5de78ef552 | ||
|
|
57a5531fbd | ||
|
|
f7a4b6b43c | ||
|
|
3de56083d8 | ||
|
|
f998a578cc | ||
|
|
0fc7ce2e07 | ||
|
|
156df10e37 | ||
|
|
9490d06509 | ||
|
|
b8b70a3848 | ||
|
|
42df482ffa | ||
|
|
058dfaeb37 | ||
|
|
1622bcbe60 | ||
|
|
72629ea3a4 | ||
|
|
4ba3c3e3ad | ||
|
|
56c1fd31d4 | ||
|
|
9c27da72bb | ||
|
|
e5dc66b140 | ||
|
|
41e10a4150 | ||
|
|
3c4381049b | ||
|
|
3188c6e922 | ||
|
|
1bfb6cda08 | ||
|
|
86feb930a8 | ||
|
|
5587c79ac5 | ||
|
|
dc2a2e10de | ||
|
|
a2fdcb4f6f | ||
|
|
a355670af9 | ||
|
|
3489c67e2b | ||
|
|
99a64942ea | ||
|
|
5eab12946f | ||
|
|
683cfb6306 | ||
|
|
9a3fde0518 | ||
|
|
26d19aab37 | ||
|
|
08564ed607 | ||
|
|
0f6378cd2c | ||
|
|
34a78fc4b9 | ||
|
|
c9ee45c1d2 | ||
|
|
13f5b4f79b | ||
|
|
e5d0c5bdc4 | ||
|
|
6220382531 | ||
|
|
165896e335 | ||
|
|
284d0ea108 | ||
|
|
b04feab5da | ||
|
|
4e0442d526 | ||
|
|
d8aa4d230d | ||
|
|
07a7fd05d2 | ||
|
|
671e1ee2b6 | ||
|
|
d627e8a4c9 | ||
|
|
6ee90b28cd | ||
|
|
8dc2b019b6 | ||
|
|
f151563e28 | ||
|
|
edbbbb011d | ||
|
|
e3fd44134b | ||
|
|
71fb7318e3 | ||
|
|
aba4395139 | ||
|
|
1fd69f101f | ||
|
|
aa4c72fb90 | ||
|
|
150b9a0d67 | ||
|
|
b08921a94a | ||
|
|
3406f3c4b3 | ||
|
|
ffca156209 | ||
|
|
b842599006 | ||
|
|
86b639b04f | ||
|
|
570602aac6 | ||
|
|
4989956a91 | ||
|
|
14849f45da | ||
|
|
28ebc14fe1 | ||
|
|
54cb996fce | ||
|
|
8df58fa4d4 | ||
|
|
422add9827 | ||
|
|
59435903eb | ||
|
|
95ee417e00 | ||
|
|
df913372bf | ||
|
|
2f1c76b7f9 | ||
|
|
18e57c8182 | ||
|
|
b4e2117c4b | ||
|
|
1bb5ff9e18 | ||
|
|
a46cae469d | ||
|
|
b564ff214d | ||
|
|
0744a10de0 | ||
|
|
343ca9497e | ||
|
|
861958527d | ||
|
|
a6b9dca291 | ||
|
|
18c05cb49d | ||
|
|
ed3e58af6c | ||
|
|
e3eed76826 | ||
|
|
7eb86b223f | ||
|
|
a4ee4529ca | ||
|
|
abc68d8503 | ||
|
|
aaff4bad1b | ||
|
|
d5c81857c3 | ||
|
|
c2594cdd2d | ||
|
|
2412042cef | ||
|
|
1f5c1a8100 | ||
|
|
78cc67f30e | ||
|
|
5b78ba5621 | ||
|
|
c4734cfc3d | ||
|
|
dd45384226 | ||
|
|
3e75d9fa3b | ||
|
|
aa690ab602 |
2
.github/workflows/build_nupkg.yml
vendored
2
.github/workflows/build_nupkg.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.x
|
||||
dotnet-version: 9.0.x
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Build Test
|
||||
name: Build Programs
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -10,10 +10,10 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
project: [Test]
|
||||
runtime: [win-x86, win-x64, linux-x64, osx-x64] #[win-x86, win-x64, win-arm64, linux-x64, linux-arm64, osx-x64]
|
||||
framework: [net8.0] #[net20, net35, net40, net452, net472, net48, netcoreapp3.1, net5.0, net6.0, net7.0, net8.0]
|
||||
conf: [Release, Debug]
|
||||
project: [ExtractionTool, ProtectionScan]
|
||||
runtime: [win-x86, win-x64, win-arm64, linux-x64, linux-arm64, osx-x64]
|
||||
framework: [net9.0] #[net20, net35, net40, net452, net472, net48, netcoreapp3.1, net5.0, net6.0, net7.0, net8.0, net9.0]
|
||||
conf: [Debug] #[Release, Debug]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -23,16 +23,18 @@ jobs:
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.x
|
||||
dotnet-version: 9.0.x
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
|
||||
- name: Build
|
||||
run: dotnet publish ${{ matrix.project }}/${{ matrix.project }}.csproj -f ${{ matrix.framework }} -r ${{ matrix.runtime }} -c ${{ matrix.conf == 'Release' && 'Release -p:DebugType=None -p:DebugSymbols=false' || 'Debug'}} --self-contained true --version-suffix ${{ github.sha }} ${{ (startsWith(matrix.framework, 'net5') || startsWith(matrix.framework, 'net6') || startsWith(matrix.framework, 'net7') || startsWith(matrix.framework, 'net8')) && '-p:PublishSingleFile=true' || ''}}
|
||||
run: dotnet publish ${{ matrix.project }}/${{ matrix.project }}.csproj -f ${{ matrix.framework }} -r ${{ matrix.runtime }} -c ${{ matrix.conf == 'Release' && 'Release -p:DebugType=None -p:DebugSymbols=false' || 'Debug'}} --self-contained true --version-suffix ${{ github.sha }} ${{ (startsWith(matrix.framework, 'net5') || startsWith(matrix.framework, 'net6') || startsWith(matrix.framework, 'net7') || startsWith(matrix.framework, 'net8') || startsWith(matrix.framework, 'net9')) && '-p:PublishSingleFile=true' || ''}}
|
||||
|
||||
- name: Archive build
|
||||
run: zip -r ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_${{ matrix.conf }}.zip ${{ matrix.project }}/bin/${{ matrix.conf }}/${{ matrix.framework }}/${{ matrix.runtime }}/publish/
|
||||
run: |
|
||||
cd ${{ matrix.project }}/bin/Debug/${{ matrix.framework }}/${{ matrix.runtime }}/publish/
|
||||
zip -r ${{ github.workspace }}/${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_${{ matrix.conf }}.zip ./
|
||||
|
||||
- name: Upload build
|
||||
uses: actions/upload-artifact@v4
|
||||
2
.github/workflows/check_pr.yml
vendored
2
.github/workflows/check_pr.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.x
|
||||
dotnet-version: 9.0.x
|
||||
|
||||
- name: Build
|
||||
run: dotnet build
|
||||
19
.vscode/launch.json
vendored
19
.vscode/launch.json
vendored
@@ -5,14 +5,27 @@
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": ".NET Core Launch (Test)",
|
||||
"name": ".NET Core Launch (ProtectionScan)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/Test/bin/Debug/net8.0/Test.dll",
|
||||
"program": "${workspaceFolder}/ProtectionScan/bin/Debug/net9.0/ProtectionScan.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/Test",
|
||||
"cwd": "${workspaceFolder}/ProtectionScan",
|
||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
},
|
||||
{
|
||||
"name": ".NET Core Launch (ExtractionTool)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/ExtractionTool/bin/Debug/net9.0/ExtractionTool.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/ExtractionTool",
|
||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
|
||||
@@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.1.32407.343
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{88735BA2-778D-4192-8EB2-FFF6843719E2}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{68D10531-99CB-40B1-8912-73FA286C9433}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
appveyor.yml = appveyor.yml
|
||||
@@ -18,20 +16,28 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BinaryObjectScanner", "BinaryObjectScanner\BinaryObjectScanner.csproj", "{341EA3F5-847C-4739-B86F-2B051FFE4EF2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProtectionScan", "ProtectionScan\ProtectionScan.csproj", "{14CC56E0-7D56-497C-BF3D-4C06FA169831}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtractionTool", "ExtractionTool\ExtractionTool.csproj", "{89767A19-043F-4251-805B-B2CBC48E2B79}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{88735BA2-778D-4192-8EB2-FFF6843719E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{88735BA2-778D-4192-8EB2-FFF6843719E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{88735BA2-778D-4192-8EB2-FFF6843719E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{88735BA2-778D-4192-8EB2-FFF6843719E2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{341EA3F5-847C-4739-B86F-2B051FFE4EF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{341EA3F5-847C-4739-B86F-2B051FFE4EF2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{341EA3F5-847C-4739-B86F-2B051FFE4EF2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{341EA3F5-847C-4739-B86F-2B051FFE4EF2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{14CC56E0-7D56-497C-BF3D-4C06FA169831}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{14CC56E0-7D56-497C-BF3D-4C06FA169831}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{14CC56E0-7D56-497C-BF3D-4C06FA169831}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{14CC56E0-7D56-497C-BF3D-4C06FA169831}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{89767A19-043F-4251-805B-B2CBC48E2B79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{89767A19-043F-4251-805B-B2CBC48E2B79}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{89767A19-043F-4251-805B-B2CBC48E2B79}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{89767A19-043F-4251-805B-B2CBC48E2B79}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -1,96 +1,111 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>3.1.10</Version>
|
||||
<!-- Mostly added due to external libraries -->
|
||||
<WarningsNotAsErrors>CS0162;CS0612;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8618;CS8625;CS8634;CS8765;IL3000;NU5100</WarningsNotAsErrors>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
<Description>Protection scanning library</Description>
|
||||
<Copyright>Copyright (c)2018-2024 Matt Nadareski</Copyright>
|
||||
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/SabreTools/BinaryObjectScanner</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageTags>protection copy-protection scanning packer</PackageTags>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>3.2.0</Version>
|
||||
<!-- Mostly added due to external libraries -->
|
||||
<WarningsNotAsErrors>CS0162;CS0612;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8618;CS8625;CS8634;CS8765;IL3000;NU5100</WarningsNotAsErrors>
|
||||
|
||||
<!-- Set a build flag for Windows specifically -->
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)'=='win-x86'">
|
||||
<DefineConstants>$(DefineConstants);WIN</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
<Description>Protection scanning library</Description>
|
||||
<Copyright>Copyright (c)2018-2024 Matt Nadareski</Copyright>
|
||||
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/SabreTools/BinaryObjectScanner</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageTags>protection copy-protection scanning packer</PackageTags>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Exclude certain parts of external modules for .NET Framework 4.5.2 and above -->
|
||||
<PropertyGroup>
|
||||
<DefaultItemExcludes>
|
||||
$(DefaultItemExcludes);
|
||||
**\AssemblyInfo.cs;
|
||||
_EXTERNAL\LessIO\src\LessIO.Tests\**;
|
||||
_EXTERNAL\libmspack4n\lib\**;
|
||||
_EXTERNAL\libmspack4n\libmspack4ntest\**;
|
||||
_EXTERNAL\stormlibsharp\lib\**;
|
||||
_EXTERNAL\stormlibsharp\src\TestConsole\**
|
||||
</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
<!-- Support All Frameworks -->
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net4`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(RuntimeIdentifier.StartsWith(`osx-arm`))">
|
||||
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Exclude all external modules for .NET Framework 2.0, .NET Framework 3.5, .NET Framework 4.0 or non-Windows builds -->
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net40`)) OR !$(RuntimeIdentifier.StartsWith(`win-`))">
|
||||
<DefaultItemExcludes>
|
||||
$(DefaultItemExcludes);
|
||||
_EXTERNAL\**
|
||||
</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
<!-- Set a build flag for Windows specifically -->
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)'=='win-x86'">
|
||||
<DefineConstants>$(DefineConstants);WIN</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- These are needed for dealing with native Windows DLLs -->
|
||||
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`))">
|
||||
<Content Include="*.dll">
|
||||
<Pack>true</Pack>
|
||||
<PackagePath>contentFiles;content</PackagePath>
|
||||
<IncludeInPackage>true</IncludeInPackage>
|
||||
<CopyToOutput>true</CopyToOutput>
|
||||
<BuildAction>Content</BuildAction>
|
||||
<copyToOutput>true</copyToOutput>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<!-- Exclude certain parts of external modules for by default -->
|
||||
<PropertyGroup>
|
||||
<DefaultItemExcludes>
|
||||
$(DefaultItemExcludes);
|
||||
**\AssemblyInfo.cs;
|
||||
_EXTERNAL\LessIO\src\LessIO.Tests\**;
|
||||
_EXTERNAL\libmspack4n\lib\**;
|
||||
_EXTERNAL\libmspack4n\libmspack4ntest\**;
|
||||
_EXTERNAL\stormlibsharp\lib\**;
|
||||
_EXTERNAL\stormlibsharp\src\TestConsole\**
|
||||
</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Support for old .NET versions -->
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net40`))">
|
||||
<PackageReference Include="MinThreadingBridge" Version="0.11.4" />
|
||||
<PackageReference Include="MinTasksExtensionsBridge" Version="0.3.4" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`))">
|
||||
<PackageReference Include="OpenMcdf" Version="2.3.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))">
|
||||
<PackageReference Include="SharpCompress" Version="0.37.2" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="$(TargetFramework.StartsWith(`net4`)) AND !$(TargetFramework.StartsWith(`net40`))">
|
||||
<PackageReference Include="System.Memory" Version="4.5.5" />
|
||||
</ItemGroup>
|
||||
<!-- Exclude all StormLibSharp for .NET Framework 4.0 -->
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net40`))">
|
||||
<DefaultItemExcludes>
|
||||
$(DefaultItemExcludes);
|
||||
_EXTERNAL\stormlibsharp\src\**
|
||||
</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.Compression" Version="0.5.1" />
|
||||
<PackageReference Include="SabreTools.Hashing" Version="1.2.0" />
|
||||
<PackageReference Include="SabreTools.IO" Version="1.4.10" />
|
||||
<PackageReference Include="SabreTools.Matching" Version="1.3.1" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.4.5" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.6.3" />
|
||||
<PackageReference Include="UnshieldSharp" Version="1.8.2" />
|
||||
<PackageReference Include="WiseUnpacker" Version="1.4.2" />
|
||||
</ItemGroup>
|
||||
<!-- Exclude all external modules for .NET Framework 2.0, .NET Framework 3.5, or non-Windows
|
||||
builds -->
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR !$(RuntimeIdentifier.StartsWith(`win-x86`))">
|
||||
<DefaultItemExcludes>
|
||||
$(DefaultItemExcludes);
|
||||
_EXTERNAL\**
|
||||
</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
<!-- These are needed for dealing with native Windows DLLs -->
|
||||
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND $(RuntimeIdentifier.StartsWith(`win-x86`))">
|
||||
<Content Include="*.dll">
|
||||
<Pack>true</Pack>
|
||||
<PackagePath>contentFiles;content</PackagePath>
|
||||
<IncludeInPackage>true</IncludeInPackage>
|
||||
<CopyToOutput>true</CopyToOutput>
|
||||
<BuildAction>Content</BuildAction>
|
||||
<copyToOutput>true</copyToOutput>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Support for old .NET versions -->
|
||||
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`))">
|
||||
<PackageReference Include="OpenMcdf" Version="2.3.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`)) AND !$(TargetFramework.StartsWith(`net452`))">
|
||||
<PackageReference Include="SharpCompress" Version="0.38.0" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.Compression" Version="0.6.0" />
|
||||
<PackageReference Include="SabreTools.Hashing" Version="1.4.0" />
|
||||
<PackageReference Include="SabreTools.IO" Version="1.5.0" />
|
||||
<PackageReference Include="SabreTools.Matching" Version="1.4.0" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.5.0" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.7.0" />
|
||||
<PackageReference Include="UnshieldSharp" Version="1.9.0" />
|
||||
<PackageReference Include="WiseUnpacker" Version="1.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
26
BinaryObjectScanner/CheckDictionary.cs
Normal file
26
BinaryObjectScanner/CheckDictionary.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace BinaryObjectScanner
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a mapping from checker to detected protection
|
||||
/// </summary>
|
||||
#if NET20 || NET35
|
||||
public class CheckDictionary<T> : System.Collections.Generic.Dictionary<T, string> where T : notnull
|
||||
#else
|
||||
public class CheckDictionary<T> : System.Collections.Concurrent.ConcurrentDictionary<T, string> where T : notnull
|
||||
#endif
|
||||
{
|
||||
/// <inheritdoc cref="System.Collections.Generic.Dictionary{TKey, TValue}.Add(TKey, TValue)"/>
|
||||
/// <remarks>Handles the proper Add implementation</remarks>
|
||||
public void Append(T key, string? value)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
#if NET20 || NET35
|
||||
this[key] = value;
|
||||
#else
|
||||
TryAdd(key, value);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
181
BinaryObjectScanner/Data/StaticChecks.cs
Normal file
181
BinaryObjectScanner/Data/StaticChecks.cs
Normal file
@@ -0,0 +1,181 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Data
|
||||
{
|
||||
internal static class StaticChecks
|
||||
{
|
||||
#region Public Collections
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IContentCheck types
|
||||
/// </summary>
|
||||
public static List<IContentCheck> ContentCheckClasses
|
||||
{
|
||||
get
|
||||
{
|
||||
contentCheckClasses ??= InitCheckClasses<IContentCheck>();
|
||||
return contentCheckClasses ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IExecutableCheck<LinearExecutable> types
|
||||
/// </summary>
|
||||
public static List<IExecutableCheck<LinearExecutable>> LinearExecutableCheckClasses
|
||||
{
|
||||
get
|
||||
{
|
||||
linearExecutableCheckClasses ??= InitCheckClasses<IExecutableCheck<LinearExecutable>>();
|
||||
return linearExecutableCheckClasses ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IExecutableCheck<MSDOS> types
|
||||
/// </summary>
|
||||
public static List<IExecutableCheck<MSDOS>> MSDOSExecutableCheckClasses
|
||||
{
|
||||
get
|
||||
{
|
||||
msdosExecutableCheckClasses ??= InitCheckClasses<IExecutableCheck<MSDOS>>();
|
||||
return msdosExecutableCheckClasses ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IExecutableCheck<NewExecutable> types
|
||||
/// </summary>
|
||||
public static List<IExecutableCheck<NewExecutable>> NewExecutableCheckClasses
|
||||
{
|
||||
get
|
||||
{
|
||||
newExecutableCheckClasses ??= InitCheckClasses<IExecutableCheck<NewExecutable>>();
|
||||
return newExecutableCheckClasses ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IPathCheck types
|
||||
/// </summary>
|
||||
public static List<IPathCheck> PathCheckClasses
|
||||
{
|
||||
get
|
||||
{
|
||||
pathCheckClasses ??= InitCheckClasses<IPathCheck>();
|
||||
return pathCheckClasses ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IExecutableCheck<PortableExecutable> types
|
||||
/// </summary>
|
||||
public static List<IExecutableCheck<PortableExecutable>> PortableExecutableCheckClasses
|
||||
{
|
||||
get
|
||||
{
|
||||
portableExecutableCheckClasses ??= InitCheckClasses<IExecutableCheck<PortableExecutable>>();
|
||||
return portableExecutableCheckClasses ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Instances
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IContentCheck types
|
||||
/// </summary>
|
||||
private static List<IContentCheck>? contentCheckClasses;
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IExecutableCheck<LinearExecutable> types
|
||||
/// </summary>
|
||||
private static List<IExecutableCheck<LinearExecutable>>? linearExecutableCheckClasses;
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IExecutableCheck<MSDOS> types
|
||||
/// </summary>
|
||||
private static List<IExecutableCheck<MSDOS>>? msdosExecutableCheckClasses;
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IExecutableCheck<NewExecutable> types
|
||||
/// </summary>
|
||||
private static List<IExecutableCheck<NewExecutable>>? newExecutableCheckClasses;
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IPathCheck types
|
||||
/// </summary>
|
||||
private static List<IPathCheck>? pathCheckClasses;
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IExecutableCheck<PortableExecutable> types
|
||||
/// </summary>
|
||||
private static List<IExecutableCheck<PortableExecutable>>? portableExecutableCheckClasses;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Initialize all implementations of a type
|
||||
/// </summary>
|
||||
private static List<T>? InitCheckClasses<T>() =>
|
||||
InitCheckClasses<T>(Assembly.GetExecutingAssembly()) ?? [];
|
||||
|
||||
/// <summary>
|
||||
/// Initialize all implementations of a type
|
||||
/// </summary>
|
||||
private static List<T>? InitCheckClasses<T>(Assembly assembly)
|
||||
{
|
||||
List<T> classTypes = [];
|
||||
|
||||
// If not all types can be loaded, use the ones that could be
|
||||
Type?[] assemblyTypes = [];
|
||||
try
|
||||
{
|
||||
assemblyTypes = assembly.GetTypes();
|
||||
}
|
||||
catch (ReflectionTypeLoadException rtle)
|
||||
{
|
||||
assemblyTypes = [.. rtle.Types];
|
||||
}
|
||||
|
||||
// Get information from the type param
|
||||
string interfaceName = typeof(T)!.FullName!;
|
||||
|
||||
// Loop through all types
|
||||
foreach (Type? type in assemblyTypes)
|
||||
{
|
||||
// Skip invalid types
|
||||
if (type == null)
|
||||
continue;
|
||||
|
||||
// If the type isn't a class
|
||||
if (!type.IsClass)
|
||||
continue;
|
||||
|
||||
// If the type isn't a class or doesn't implement the interface
|
||||
bool interfaceFound = false;
|
||||
foreach (var ii in type.GetInterfaces())
|
||||
{
|
||||
if (ii.FullName != interfaceName)
|
||||
continue;
|
||||
|
||||
interfaceFound = true;
|
||||
break;
|
||||
}
|
||||
if (!interfaceFound)
|
||||
continue;
|
||||
|
||||
// Try to create a concrete instance of the type
|
||||
var instance = (T?)Activator.CreateInstance(type);
|
||||
if (instance != null)
|
||||
classTypes.Add(instance);
|
||||
}
|
||||
|
||||
return classTypes;
|
||||
}
|
||||
}
|
||||
}
|
||||
27
BinaryObjectScanner/EnumerableExtensions.cs
Normal file
27
BinaryObjectScanner/EnumerableExtensions.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BinaryObjectScanner
|
||||
{
|
||||
internal static class EnumerableExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Wrap iterating through an enumerable with an action
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// .NET Frameworks 2.0 and 3.5 process in series.
|
||||
/// .NET Frameworks 4.0 onward process in parallel.
|
||||
/// </remarks>
|
||||
public static void IterateWithAction<T>(this IEnumerable<T> source, Action<T> action)
|
||||
{
|
||||
#if NET20 || NET35
|
||||
foreach (var item in source)
|
||||
{
|
||||
action(item);
|
||||
}
|
||||
#else
|
||||
System.Threading.Tasks.Parallel.ForEach(source, action);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,22 +10,22 @@ namespace BinaryObjectScanner
|
||||
/// </summary>
|
||||
public static IDetectable? CreateDetectable(WrapperType fileType)
|
||||
{
|
||||
switch (fileType)
|
||||
return fileType switch
|
||||
{
|
||||
case WrapperType.AACSMediaKeyBlock: return new FileType.AACSMediaKeyBlock();
|
||||
case WrapperType.BDPlusSVM: return new FileType.BDPlusSVM();
|
||||
//case WrapperType.CIA: return new FileType.CIA();
|
||||
case WrapperType.Executable: return new FileType.Executable();
|
||||
case WrapperType.LDSCRYPT: return new FileType.LDSCRYPT();
|
||||
//case WrapperType.N3DS: return new FileType.N3DS();
|
||||
//case WrapperType.Nitro: return new FileType.Nitro();
|
||||
case WrapperType.PlayJAudioFile: return new FileType.PLJ();
|
||||
case WrapperType.RealArcadeInstaller: return new FileType.RealArcadeInstaller();
|
||||
case WrapperType.RealArcadeMezzanine: return new FileType.RealArcadeMezzanine();
|
||||
case WrapperType.SFFS: return new FileType.SFFS();
|
||||
case WrapperType.Textfile: return new FileType.Textfile();
|
||||
default: return null;
|
||||
}
|
||||
WrapperType.AACSMediaKeyBlock => new FileType.AACSMediaKeyBlock(),
|
||||
WrapperType.BDPlusSVM => new FileType.BDPlusSVM(),
|
||||
//WrapperType.CIA => new FileType.CIA(),
|
||||
WrapperType.Executable => new FileType.Executable(),
|
||||
WrapperType.LDSCRYPT => new FileType.LDSCRYPT(),
|
||||
//WrapperType.N3DS => new FileType.N3DS(),
|
||||
//WrapperType.Nitro => new FileType.Nitro(),
|
||||
WrapperType.PlayJAudioFile => new FileType.PLJ(),
|
||||
WrapperType.RealArcadeInstaller => new FileType.RealArcadeInstaller(),
|
||||
WrapperType.RealArcadeMezzanine => new FileType.RealArcadeMezzanine(),
|
||||
WrapperType.SFFS => new FileType.SFFS(),
|
||||
WrapperType.Textfile => new FileType.Textfile(),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -33,40 +33,40 @@ namespace BinaryObjectScanner
|
||||
/// </summary>
|
||||
public static IExtractable? CreateExtractable(WrapperType fileType)
|
||||
{
|
||||
switch (fileType)
|
||||
return fileType switch
|
||||
{
|
||||
case WrapperType.BFPK: return new FileType.BFPK();
|
||||
case WrapperType.BSP: return new FileType.BSP();
|
||||
case WrapperType.BZip2: return new FileType.BZip2();
|
||||
case WrapperType.CFB: return new FileType.CFB();
|
||||
//case WrapperType.CIA: return new FileType.CIA();
|
||||
case WrapperType.GCF: return new FileType.GCF();
|
||||
case WrapperType.GZIP: return new FileType.GZIP();
|
||||
case WrapperType.InstallShieldArchiveV3: return new FileType.InstallShieldArchiveV3();
|
||||
case WrapperType.InstallShieldCAB: return new FileType.InstallShieldCAB();
|
||||
case WrapperType.MicrosoftCAB: return new FileType.MicrosoftCAB();
|
||||
case WrapperType.MicrosoftLZ: return new FileType.MicrosoftLZ();
|
||||
case WrapperType.MoPaQ: return new FileType.MPQ();
|
||||
//case WrapperType.N3DS: return new FileType.N3DS();
|
||||
//case WrapperType.NCF: return new FileType.NCF();
|
||||
//case WrapperType.Nitro: return new FileType.Nitro();
|
||||
case WrapperType.PAK: return new FileType.PAK();
|
||||
case WrapperType.PFF: return new FileType.PFF();
|
||||
case WrapperType.PKZIP: return new FileType.PKZIP();
|
||||
//case WrapperType.PlayJAudioFile: return new FileType.PLJ();
|
||||
//case WrapperType.Quantum: return new FileType.Quantum();
|
||||
case WrapperType.RAR: return new FileType.RAR();
|
||||
case WrapperType.SevenZip: return new FileType.SevenZip();
|
||||
case WrapperType.SFFS: return new FileType.SFFS();
|
||||
case WrapperType.SGA: return new FileType.SGA();
|
||||
case WrapperType.TapeArchive: return new FileType.TapeArchive();
|
||||
case WrapperType.VBSP: return new FileType.VBSP();
|
||||
case WrapperType.VPK: return new FileType.VPK();
|
||||
case WrapperType.WAD: return new FileType.WAD();
|
||||
case WrapperType.XZ: return new FileType.XZ();
|
||||
case WrapperType.XZP: return new FileType.XZP();
|
||||
default: return null;
|
||||
}
|
||||
WrapperType.BFPK => new FileType.BFPK(),
|
||||
WrapperType.BSP => new FileType.BSP(),
|
||||
WrapperType.BZip2 => new FileType.BZip2(),
|
||||
WrapperType.CFB => new FileType.CFB(),
|
||||
//WrapperType.CIA => new FileType.CIA(),
|
||||
WrapperType.GCF => new FileType.GCF(),
|
||||
WrapperType.GZIP => new FileType.GZIP(),
|
||||
WrapperType.InstallShieldArchiveV3 => new FileType.InstallShieldArchiveV3(),
|
||||
WrapperType.InstallShieldCAB => new FileType.InstallShieldCAB(),
|
||||
WrapperType.MicrosoftCAB => new FileType.MicrosoftCAB(),
|
||||
WrapperType.MicrosoftLZ => new FileType.MicrosoftLZ(),
|
||||
WrapperType.MoPaQ => new FileType.MPQ(),
|
||||
//WrapperType.N3DS => new FileType.N3DS(),
|
||||
//WrapperType.NCF => new FileType.NCF(),
|
||||
//WrapperType.Nitro => new FileType.Nitro(),
|
||||
WrapperType.PAK => new FileType.PAK(),
|
||||
WrapperType.PFF => new FileType.PFF(),
|
||||
WrapperType.PKZIP => new FileType.PKZIP(),
|
||||
//WrapperType.PlayJAudioFile => new FileType.PLJ(),
|
||||
//WrapperType.Quantum => new FileType.Quantum(),
|
||||
WrapperType.RAR => new FileType.RAR(),
|
||||
WrapperType.SevenZip => new FileType.SevenZip(),
|
||||
WrapperType.SFFS => new FileType.SFFS(),
|
||||
WrapperType.SGA => new FileType.SGA(),
|
||||
WrapperType.TapeArchive => new FileType.TapeArchive(),
|
||||
WrapperType.VBSP => new FileType.VBSP(),
|
||||
WrapperType.VPK => new FileType.VPK(),
|
||||
WrapperType.WAD => new FileType.WAD(),
|
||||
WrapperType.XZ => new FileType.XZ(),
|
||||
WrapperType.XZP => new FileType.XZP(),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
@@ -16,10 +15,8 @@ namespace BinaryObjectScanner.FileType
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -34,7 +31,7 @@ namespace BinaryObjectScanner.FileType
|
||||
return null;
|
||||
|
||||
// Derive the version, if possible
|
||||
var typeAndVersion = mkb.Model.Records?.FirstOrDefault(r => r?.RecordType == SabreTools.Models.AACS.RecordType.TypeAndVersion);
|
||||
var typeAndVersion = Array.Find(mkb.Model.Records ?? [], r => r?.RecordType == SabreTools.Models.AACS.RecordType.TypeAndVersion);
|
||||
if (typeAndVersion == null)
|
||||
return "AACS (Unknown Version)";
|
||||
else
|
||||
|
||||
@@ -15,10 +15,8 @@ namespace BinaryObjectScanner.FileType
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -14,38 +14,35 @@ namespace BinaryObjectScanner.FileType
|
||||
public class BFPK : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create the wrapper
|
||||
var bfpk = SabreTools.Serialization.Wrappers.BFPK.Create(stream);
|
||||
if (bfpk == null)
|
||||
return null;
|
||||
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
return false;
|
||||
|
||||
// Extract all files
|
||||
ExtractAll(bfpk, tempPath);
|
||||
Directory.CreateDirectory(outDir);
|
||||
ExtractAll(bfpk, outDir);
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,41 +11,36 @@ namespace BinaryObjectScanner.FileType
|
||||
public class BSP : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create the wrapper
|
||||
var bsp = SabreTools.Serialization.Wrappers.BSP.Create(stream);
|
||||
if (bsp == null)
|
||||
return null;
|
||||
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
return false;
|
||||
|
||||
// Loop through and extract all files
|
||||
ExtractAllLumps(bsp, tempPath);
|
||||
ExtractAllTextures(bsp, tempPath);
|
||||
Directory.CreateDirectory(outDir);
|
||||
ExtractAllLumps(bsp, outDir);
|
||||
ExtractAllTextures(bsp, outDir);
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,46 +14,44 @@ namespace BinaryObjectScanner.FileType
|
||||
public class BZip2 : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (stream == null)
|
||||
return null;
|
||||
if (stream == null || !stream.CanRead)
|
||||
return false;
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
// Try opening the stream
|
||||
using var bz2File = new BZip2Stream(stream, CompressionMode.Decompress, true);
|
||||
|
||||
using (BZip2Stream bz2File = new BZip2Stream(stream, CompressionMode.Decompress, true))
|
||||
{
|
||||
string tempFile = Path.Combine(tempPath, Guid.NewGuid().ToString());
|
||||
using (FileStream fs = File.OpenWrite(tempFile))
|
||||
{
|
||||
bz2File.CopyTo(fs);
|
||||
}
|
||||
}
|
||||
// Create the output file path
|
||||
Directory.CreateDirectory(outDir);
|
||||
string tempFile = Path.Combine(outDir, Guid.NewGuid().ToString());
|
||||
|
||||
return tempPath;
|
||||
// Extract the file
|
||||
using FileStream fs = File.OpenWrite(tempFile);
|
||||
bz2File.CopyTo(fs);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return null;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,79 +14,75 @@ namespace BinaryObjectScanner.FileType
|
||||
public class CFB : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
#if NET20 || NET35
|
||||
// Not supported for .NET Framework 2.0 or .NET Framework 3.5 due to library support
|
||||
return null;
|
||||
return false;
|
||||
#else
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (CompoundFile msi = new CompoundFile(stream, CFSUpdateMode.ReadOnly, CFSConfiguration.Default))
|
||||
using var msi = new CompoundFile(stream, CFSUpdateMode.ReadOnly, CFSConfiguration.Default);
|
||||
msi.RootStorage.VisitEntries((e) =>
|
||||
{
|
||||
msi.RootStorage.VisitEntries((e) =>
|
||||
try
|
||||
{
|
||||
try
|
||||
if (!e.IsStream)
|
||||
return;
|
||||
|
||||
var str = msi.RootStorage.GetStream(e.Name);
|
||||
if (str == null)
|
||||
return;
|
||||
|
||||
byte[] strData = str.GetData();
|
||||
if (strData == null)
|
||||
return;
|
||||
|
||||
var decoded = DecodeStreamName(e.Name)?.TrimEnd('\0');
|
||||
if (decoded == null)
|
||||
return;
|
||||
|
||||
byte[] nameBytes = Encoding.UTF8.GetBytes(e.Name);
|
||||
|
||||
// UTF-8 encoding of 0x4840.
|
||||
if (nameBytes[0] == 0xe4 && nameBytes[1] == 0xa1 && nameBytes[2] == 0x80)
|
||||
decoded = decoded.Substring(3);
|
||||
|
||||
foreach (char c in Path.GetInvalidFileNameChars())
|
||||
{
|
||||
if (!e.IsStream)
|
||||
return;
|
||||
|
||||
var str = msi.RootStorage.GetStream(e.Name);
|
||||
if (str == null)
|
||||
return;
|
||||
|
||||
byte[] strData = str.GetData();
|
||||
if (strData == null)
|
||||
return;
|
||||
|
||||
var decoded = DecodeStreamName(e.Name)?.TrimEnd('\0');
|
||||
if (decoded == null)
|
||||
return;
|
||||
|
||||
byte[] nameBytes = Encoding.UTF8.GetBytes(e.Name);
|
||||
|
||||
// UTF-8 encoding of 0x4840.
|
||||
if (nameBytes[0] == 0xe4 && nameBytes[1] == 0xa1 && nameBytes[2] == 0x80)
|
||||
decoded = decoded.Substring(3);
|
||||
|
||||
foreach (char c in Path.GetInvalidFileNameChars())
|
||||
{
|
||||
decoded = decoded.Replace(c, '_');
|
||||
}
|
||||
|
||||
string filename = Path.Combine(tempPath, decoded);
|
||||
using (Stream fs = File.OpenWrite(filename))
|
||||
{
|
||||
fs.Write(strData, 0, strData.Length);
|
||||
}
|
||||
decoded = decoded.Replace(c, '_');
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}, recursive: true);
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
string tempFile = Path.Combine(outDir, decoded);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
using Stream fs = File.OpenWrite(tempFile);
|
||||
fs.Write(strData, 0, strData.Length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}, recursive: true);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
using System;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Collections.Concurrent;
|
||||
#endif
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Threading.Tasks;
|
||||
#endif
|
||||
using BinaryObjectScanner.Data;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Utilities;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
@@ -19,10 +13,6 @@ namespace BinaryObjectScanner.FileType
|
||||
/// <summary>
|
||||
/// Executable or library
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Due to the complexity of executables, all extraction handling
|
||||
/// another class that is used by the scanner
|
||||
/// </remarks>
|
||||
public class Executable : IDetectable
|
||||
{
|
||||
#region Properties
|
||||
@@ -37,95 +27,6 @@ namespace BinaryObjectScanner.FileType
|
||||
/// </summary>
|
||||
public bool IncludePackers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IContentCheck types
|
||||
/// </summary>
|
||||
public static IEnumerable<IContentCheck> ContentCheckClasses
|
||||
{
|
||||
get
|
||||
{
|
||||
contentCheckClasses ??= InitCheckClasses<IContentCheck>();
|
||||
return contentCheckClasses ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all ILinearExecutableCheck types
|
||||
/// </summary>
|
||||
public static IEnumerable<ILinearExecutableCheck> LinearExecutableCheckClasses
|
||||
{
|
||||
get
|
||||
{
|
||||
linearExecutableCheckClasses ??= InitCheckClasses<ILinearExecutableCheck>();
|
||||
return linearExecutableCheckClasses ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IMSDOSExecutableCheck types
|
||||
/// </summary>
|
||||
public static IEnumerable<IMSDOSExecutableCheck> MSDOSExecutableCheckClasses
|
||||
{
|
||||
get
|
||||
{
|
||||
msdosExecutableCheckClasses ??= InitCheckClasses<IMSDOSExecutableCheck>();
|
||||
return msdosExecutableCheckClasses ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all INewExecutableCheck types
|
||||
/// </summary>
|
||||
public static IEnumerable<INewExecutableCheck> NewExecutableCheckClasses
|
||||
{
|
||||
get
|
||||
{
|
||||
newExecutableCheckClasses ??= InitCheckClasses<INewExecutableCheck>();
|
||||
return newExecutableCheckClasses ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IPortableExecutableCheck types
|
||||
/// </summary>
|
||||
public static IEnumerable<IPortableExecutableCheck> PortableExecutableCheckClasses
|
||||
{
|
||||
get
|
||||
{
|
||||
portableExecutableCheckClasses ??= InitCheckClasses<IPortableExecutableCheck>();
|
||||
return portableExecutableCheckClasses ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Instances
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IContentCheck types
|
||||
/// </summary>
|
||||
private static IEnumerable<IContentCheck>? contentCheckClasses;
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all ILinearExecutableCheck types
|
||||
/// </summary>
|
||||
private static IEnumerable<ILinearExecutableCheck>? linearExecutableCheckClasses;
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IMSDOSExecutableCheck types
|
||||
/// </summary>
|
||||
private static IEnumerable<IMSDOSExecutableCheck>? msdosExecutableCheckClasses;
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all INewExecutableCheck types
|
||||
/// </summary>
|
||||
private static IEnumerable<INewExecutableCheck>? newExecutableCheckClasses;
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IPortableExecutableCheck types
|
||||
/// </summary>
|
||||
private static IEnumerable<IPortableExecutableCheck>? portableExecutableCheckClasses;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -141,52 +42,97 @@ namespace BinaryObjectScanner.FileType
|
||||
/// <inheritdoc/>
|
||||
public string? Detect(Stream stream, string file, bool includeDebug)
|
||||
{
|
||||
// Try to create a wrapper for the proper executable type
|
||||
var wrapper = WrapperFactory.CreateExecutableWrapper(stream);
|
||||
if (wrapper == null)
|
||||
// Get all non-nested protections
|
||||
var protections = DetectDict(stream, file, getProtections: null, includeDebug);
|
||||
if (protections.Count == 0)
|
||||
return null;
|
||||
|
||||
// Create the internal queue
|
||||
#if NET20 || NET35
|
||||
var protections = new Queue<string>();
|
||||
#else
|
||||
var protections = new ConcurrentQueue<string>();
|
||||
#endif
|
||||
// Create the internal list
|
||||
var protectionList = new List<string>();
|
||||
foreach (string key in protections.Keys)
|
||||
{
|
||||
protectionList.AddRange(protections[key]);
|
||||
}
|
||||
|
||||
return string.Join(";", [.. protectionList]);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IDetectable.Detect(Stream, string, bool)"/>
|
||||
/// <remarks>
|
||||
/// Ideally, we wouldn't need to circumvent the proper handling of file types just for Executable,
|
||||
/// but due to the complexity of scanning, this is not currently possible.
|
||||
/// </remarks>
|
||||
public ProtectionDictionary DetectDict(Stream stream,
|
||||
string file,
|
||||
Func<string, ProtectionDictionary>? getProtections,
|
||||
bool includeDebug)
|
||||
{
|
||||
// Create the output dictionary
|
||||
var protections = new ProtectionDictionary();
|
||||
|
||||
// Try to create a wrapper for the proper executable type
|
||||
IWrapper? wrapper;
|
||||
try
|
||||
{
|
||||
wrapper = WrapperFactory.CreateExecutableWrapper(stream);
|
||||
if (wrapper == null)
|
||||
return protections;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return protections;
|
||||
}
|
||||
|
||||
// Only use generic content checks if we're in debug mode
|
||||
if (includeDebug)
|
||||
{
|
||||
var subProtections = RunContentChecks(file, stream, includeDebug);
|
||||
if (subProtections != null)
|
||||
protections.AddRange(subProtections.Values.ToArray());
|
||||
protections.Append(file, subProtections.Values);
|
||||
}
|
||||
|
||||
if (wrapper is MSDOS mz)
|
||||
{
|
||||
var subProtections = RunMSDOSExecutableChecks(file, stream, mz, includeDebug);
|
||||
if (subProtections != null)
|
||||
protections.AddRange(subProtections.Values.ToArray());
|
||||
// Standard checks
|
||||
var subProtections = RunExecutableChecks(file, mz, StaticChecks.MSDOSExecutableCheckClasses, includeDebug);
|
||||
protections.Append(file, subProtections.Values);
|
||||
|
||||
// Extractable checks
|
||||
var extractedProtections = HandleExtractableProtections(file, mz, subProtections.Keys, getProtections, includeDebug);
|
||||
protections.Append(extractedProtections);
|
||||
}
|
||||
else if (wrapper is LinearExecutable lex)
|
||||
{
|
||||
var subProtections = RunLinearExecutableChecks(file, stream, lex, includeDebug);
|
||||
if (subProtections != null)
|
||||
protections.AddRange(subProtections.Values.ToArray());
|
||||
// Standard checks
|
||||
var subProtections = RunExecutableChecks(file, lex, StaticChecks.LinearExecutableCheckClasses, includeDebug);
|
||||
protections.Append(file, subProtections.Values);
|
||||
|
||||
// Extractable checks
|
||||
var extractedProtections = HandleExtractableProtections(file, lex, subProtections.Keys, getProtections, includeDebug);
|
||||
protections.Append(extractedProtections);
|
||||
}
|
||||
else if (wrapper is NewExecutable nex)
|
||||
{
|
||||
var subProtections = RunNewExecutableChecks(file, stream, nex, includeDebug);
|
||||
if (subProtections != null)
|
||||
protections.AddRange(subProtections.Values.ToArray());
|
||||
// Standard checks
|
||||
var subProtections = RunExecutableChecks(file, nex, StaticChecks.NewExecutableCheckClasses, includeDebug);
|
||||
protections.Append(file, subProtections.Values);
|
||||
|
||||
// Extractable checks
|
||||
var extractedProtections = HandleExtractableProtections(file, nex, subProtections.Keys, getProtections, includeDebug);
|
||||
protections.Append(extractedProtections);
|
||||
}
|
||||
else if (wrapper is PortableExecutable pex)
|
||||
{
|
||||
var subProtections = RunPortableExecutableChecks(file, stream, pex, includeDebug);
|
||||
if (subProtections != null)
|
||||
protections.AddRange(subProtections.Values.ToArray());
|
||||
// Standard checks
|
||||
var subProtections = RunExecutableChecks(file, pex, StaticChecks.PortableExecutableCheckClasses, includeDebug);
|
||||
protections.Append(file, subProtections.Values);
|
||||
|
||||
// Extractable checks
|
||||
var extractedProtections = HandleExtractableProtections(file, pex, subProtections.Keys, getProtections, includeDebug);
|
||||
protections.Append(extractedProtections);
|
||||
}
|
||||
|
||||
return string.Join(";", [.. protections]);
|
||||
return protections;
|
||||
}
|
||||
|
||||
#region Check Runners
|
||||
@@ -197,382 +143,182 @@ namespace BinaryObjectScanner.FileType
|
||||
/// <param name="file">Name of the source file of the stream, for tracking</param>
|
||||
/// <param name="stream">Stream to scan the contents of</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
public Dictionary<IContentCheck, string>? RunContentChecks(string? file, Stream stream, bool includeDebug)
|
||||
#else
|
||||
public ConcurrentDictionary<IContentCheck, string>? RunContentChecks(string? file, Stream stream, bool includeDebug)
|
||||
#endif
|
||||
/// <returns>Set of protections in file, empty on error</returns>
|
||||
public IDictionary<IContentCheck, string> RunContentChecks(string? file, Stream stream, bool includeDebug)
|
||||
{
|
||||
// Create the output dictionary
|
||||
var protections = new CheckDictionary<IContentCheck>();
|
||||
|
||||
// If we have an invalid file
|
||||
if (string.IsNullOrEmpty(file))
|
||||
return null;
|
||||
return protections;
|
||||
else if (!File.Exists(file))
|
||||
return null;
|
||||
return protections;
|
||||
|
||||
// Read the file contents
|
||||
byte[] fileContent = [];
|
||||
try
|
||||
{
|
||||
#if NET20 || NET35 || NET40
|
||||
using var br = new BinaryReader(stream, Encoding.Default);
|
||||
#else
|
||||
using var br = new BinaryReader(stream, Encoding.Default, true);
|
||||
#endif
|
||||
fileContent = br.ReadBytes((int)stream.Length);
|
||||
fileContent = stream.ReadBytes((int)stream.Length);
|
||||
if (fileContent == null)
|
||||
return null;
|
||||
return protections;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return protections;
|
||||
}
|
||||
|
||||
// Create the output dictionary
|
||||
#if NET20 || NET35
|
||||
var protections = new Dictionary<IContentCheck, string>();
|
||||
#else
|
||||
var protections = new ConcurrentDictionary<IContentCheck, string>();
|
||||
#endif
|
||||
|
||||
// Iterate through all checks
|
||||
#if NET20 || NET35
|
||||
foreach (var checkClass in ContentCheckClasses)
|
||||
#else
|
||||
Parallel.ForEach(ContentCheckClasses, checkClass =>
|
||||
#endif
|
||||
StaticChecks.ContentCheckClasses.IterateWithAction(checkClass =>
|
||||
{
|
||||
// Get the protection for the class, if possible
|
||||
var protection = checkClass.CheckContents(file!, fileContent, includeDebug);
|
||||
if (string.IsNullOrEmpty(protection))
|
||||
#if NET20 || NET35
|
||||
continue;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
// If we are filtering on game engines
|
||||
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
|
||||
#if NET20 || NET35
|
||||
continue;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
// If we are filtering on packers
|
||||
if (CheckIfPacker(checkClass) && !IncludePackers)
|
||||
#if NET20 || NET35
|
||||
continue;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if NET20 || NET35
|
||||
protections[checkClass] = protection!;
|
||||
}
|
||||
#else
|
||||
protections.TryAdd(checkClass, protection!);
|
||||
protections.Append(checkClass, protection);
|
||||
});
|
||||
#endif
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle a single file based on all linear executable check implementations
|
||||
/// Handle a single file based on all executable check implementations
|
||||
/// </summary>
|
||||
/// <param name="file">Name of the source file of the executable, for tracking</param>
|
||||
/// <param name="lex">Executable to scan</param>
|
||||
/// <param name="exe">Executable to scan</param>
|
||||
/// <param name="checks">Set of checks to use</param>
|
||||
/// <param name="scanner">Scanner for handling recursive protections</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
public Dictionary<ILinearExecutableCheck, string> RunLinearExecutableChecks(string file, Stream stream, LinearExecutable lex, bool includeDebug)
|
||||
#else
|
||||
public ConcurrentDictionary<ILinearExecutableCheck, string> RunLinearExecutableChecks(string file, Stream stream, LinearExecutable lex, bool includeDebug)
|
||||
#endif
|
||||
/// <returns>Set of protections in file, empty on error</returns>
|
||||
public IDictionary<U, string> RunExecutableChecks<T, U>(string file, T exe, List<U> checks, bool includeDebug)
|
||||
where T : WrapperBase
|
||||
where U : IExecutableCheck<T>
|
||||
{
|
||||
// Create the output dictionary
|
||||
#if NET20 || NET35
|
||||
var protections = new Dictionary<ILinearExecutableCheck, string>();
|
||||
#else
|
||||
var protections = new ConcurrentDictionary<ILinearExecutableCheck, string>();
|
||||
#endif
|
||||
var protections = new CheckDictionary<U>();
|
||||
|
||||
// Iterate through all checks
|
||||
#if NET20 || NET35
|
||||
foreach (var checkClass in LinearExecutableCheckClasses)
|
||||
#else
|
||||
Parallel.ForEach(LinearExecutableCheckClasses, checkClass =>
|
||||
#endif
|
||||
checks.IterateWithAction(checkClass =>
|
||||
{
|
||||
// Get the protection for the class, if possible
|
||||
var protection = checkClass.CheckLinearExecutable(file, lex, includeDebug);
|
||||
var protection = checkClass.CheckExecutable(file, exe, includeDebug);
|
||||
if (string.IsNullOrEmpty(protection))
|
||||
#if NET20 || NET35
|
||||
continue;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
// If we are filtering on game engines
|
||||
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
|
||||
#if NET20 || NET35
|
||||
continue;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
// If we are filtering on packers
|
||||
if (CheckIfPacker(checkClass) && !IncludePackers)
|
||||
#if NET20 || NET35
|
||||
continue;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if NET20 || NET35
|
||||
protections[checkClass] = protection!;
|
||||
}
|
||||
#else
|
||||
protections.TryAdd(checkClass, protection!);
|
||||
protections.Append(checkClass, protection);
|
||||
});
|
||||
#endif
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle a single file based on all MS-DOS executable check implementations
|
||||
/// Handle extractable protections, such as executable packers
|
||||
/// </summary>
|
||||
/// <param name="file">Name of the source file of the executable, for tracking</param>
|
||||
/// <param name="mz">Executable to scan</param>
|
||||
/// <param name="file">Name of the source file of the stream, for tracking</param>
|
||||
/// <param name="exe">Executable to scan the contents of</param>
|
||||
/// <param name="checks">Set of classes returned from Exectuable scans</param>
|
||||
/// <param name="getProtections">Optional function for handling recursive protections</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
public Dictionary<IMSDOSExecutableCheck, string> RunMSDOSExecutableChecks(string file, Stream stream, MSDOS mz, bool includeDebug)
|
||||
#else
|
||||
public ConcurrentDictionary<IMSDOSExecutableCheck, string> RunMSDOSExecutableChecks(string file, Stream stream, MSDOS mz, bool includeDebug)
|
||||
#endif
|
||||
/// <returns>Set of protections found from extraction, empty on error</returns>
|
||||
private static ProtectionDictionary HandleExtractableProtections<T, U>(string file,
|
||||
T exe,
|
||||
IEnumerable<U> checks,
|
||||
Func<string, ProtectionDictionary>? getProtections,
|
||||
bool includeDebug)
|
||||
where T : WrapperBase
|
||||
where U : IExecutableCheck<T>
|
||||
{
|
||||
// Create the output dictionary
|
||||
#if NET20 || NET35
|
||||
var protections = new Dictionary<IMSDOSExecutableCheck, string>();
|
||||
#else
|
||||
var protections = new ConcurrentDictionary<IMSDOSExecutableCheck, string>();
|
||||
#endif
|
||||
var protections = new ProtectionDictionary();
|
||||
|
||||
// Iterate through all checks
|
||||
#if NET20 || NET35
|
||||
foreach (var checkClass in MSDOSExecutableCheckClasses)
|
||||
#else
|
||||
Parallel.ForEach(MSDOSExecutableCheckClasses, checkClass =>
|
||||
#endif
|
||||
// If we have an invalid set of classes
|
||||
if (checks == null)
|
||||
return protections;
|
||||
|
||||
// If we have any extractable packers
|
||||
var extractables = checks
|
||||
.Where(c => c is IExtractableExecutable<T>)
|
||||
.Select(c => c as IExtractableExecutable<T>);
|
||||
extractables.IterateWithAction(extractable =>
|
||||
{
|
||||
// Get the protection for the class, if possible
|
||||
var protection = checkClass.CheckMSDOSExecutable(file, mz, includeDebug);
|
||||
if (string.IsNullOrEmpty(protection))
|
||||
#if NET20 || NET35
|
||||
continue;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
// If we are filtering on game engines
|
||||
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
|
||||
#if NET20 || NET35
|
||||
continue;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
// If we are filtering on packers
|
||||
if (CheckIfPacker(checkClass) && !IncludePackers)
|
||||
#if NET20 || NET35
|
||||
continue;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if NET20 || NET35
|
||||
protections[checkClass] = protection!;
|
||||
}
|
||||
#else
|
||||
protections.TryAdd(checkClass, protection!);
|
||||
var subProtections = PerformExtractableCheck(extractable!, file, exe, getProtections, includeDebug);
|
||||
protections.Append(subProtections);
|
||||
});
|
||||
#endif
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle a single file based on all new executable check implementations
|
||||
/// Handle files based on an IExtractableExecutable implementation
|
||||
/// </summary>
|
||||
/// <param name="file">Name of the source file of the executable, for tracking</param>
|
||||
/// <param name="nex">Executable to scan</param>
|
||||
/// <param name="file">Name of the source file of the stream, for tracking</param>
|
||||
/// <param name="exe">Executable to scan the contents of</param>
|
||||
/// <param name="impl">IExtractableExecutable class representing the file type</param>
|
||||
/// <param name="getProtections">Optional function for handling recursive protections</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
public Dictionary<INewExecutableCheck, string> RunNewExecutableChecks(string file, Stream stream, NewExecutable nex, bool includeDebug)
|
||||
#else
|
||||
public ConcurrentDictionary<INewExecutableCheck, string> RunNewExecutableChecks(string file, Stream stream, NewExecutable nex, bool includeDebug)
|
||||
#endif
|
||||
/// <returns>Set of protections in path, empty on error</returns>
|
||||
private static ProtectionDictionary PerformExtractableCheck<T>(IExtractableExecutable<T> impl,
|
||||
string file,
|
||||
T exe,
|
||||
Func<string, ProtectionDictionary>? getProtections,
|
||||
bool includeDebug)
|
||||
where T : WrapperBase
|
||||
{
|
||||
// Create the output dictionary
|
||||
#if NET20 || NET35
|
||||
var protections = new Dictionary<INewExecutableCheck, string>();
|
||||
#else
|
||||
var protections = new ConcurrentDictionary<INewExecutableCheck, string>();
|
||||
#endif
|
||||
// If we have an invalid extractable somehow
|
||||
if (impl == null)
|
||||
return [];
|
||||
|
||||
// Iterate through all checks
|
||||
#if NET20 || NET35
|
||||
foreach (var checkClass in NewExecutableCheckClasses)
|
||||
#else
|
||||
Parallel.ForEach(NewExecutableCheckClasses, checkClass =>
|
||||
#endif
|
||||
{
|
||||
// Get the protection for the class, if possible
|
||||
var protection = checkClass.CheckNewExecutable(file, nex, includeDebug);
|
||||
if (string.IsNullOrEmpty(protection))
|
||||
#if NET20 || NET35
|
||||
continue;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
// If we are filtering on game engines
|
||||
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
|
||||
#if NET20 || NET35
|
||||
continue;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
// If we are filtering on packers
|
||||
if (CheckIfPacker(checkClass) && !IncludePackers)
|
||||
#if NET20 || NET35
|
||||
continue;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if NET20 || NET35
|
||||
protections[checkClass] = protection!;
|
||||
}
|
||||
#else
|
||||
protections.TryAdd(checkClass, protection!);
|
||||
});
|
||||
#endif
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle a single file based on all portable executable check implementations
|
||||
/// </summary>
|
||||
/// <param name="file">Name of the source file of the executable, for tracking</param>
|
||||
/// <param name="pex">Executable to scan</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
public Dictionary<IPortableExecutableCheck, string> RunPortableExecutableChecks(string file, Stream stream, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public ConcurrentDictionary<IPortableExecutableCheck, string> RunPortableExecutableChecks(string file, Stream stream, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Create the output dictionary
|
||||
#if NET20 || NET35
|
||||
var protections = new Dictionary<IPortableExecutableCheck, string>();
|
||||
#else
|
||||
var protections = new ConcurrentDictionary<IPortableExecutableCheck, string>();
|
||||
#endif
|
||||
|
||||
// Iterate through all checks
|
||||
#if NET20 || NET35
|
||||
foreach (var checkClass in PortableExecutableCheckClasses)
|
||||
#else
|
||||
Parallel.ForEach(PortableExecutableCheckClasses, checkClass =>
|
||||
#endif
|
||||
{
|
||||
// Get the protection for the class, if possible
|
||||
var protection = checkClass.CheckPortableExecutable(file, pex, includeDebug);
|
||||
if (string.IsNullOrEmpty(protection))
|
||||
#if NET20 || NET35
|
||||
continue;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
// If we are filtering on game engines
|
||||
if (CheckIfGameEngine(checkClass) && !IncludeGameEngines)
|
||||
#if NET20 || NET35
|
||||
continue;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
// If we are filtering on packers
|
||||
if (CheckIfPacker(checkClass) && !IncludePackers)
|
||||
#if NET20 || NET35
|
||||
continue;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
||||
#if NET20 || NET35
|
||||
protections[checkClass] = protection!;
|
||||
}
|
||||
#else
|
||||
protections.TryAdd(checkClass, protection!);
|
||||
});
|
||||
#endif
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Initializers
|
||||
|
||||
/// <summary>
|
||||
/// Initialize all implementations of a type
|
||||
/// </summary>
|
||||
private static IEnumerable<T>? InitCheckClasses<T>() =>
|
||||
InitCheckClasses<T>(Assembly.GetExecutingAssembly()) ?? [];
|
||||
|
||||
/// <summary>
|
||||
/// Initialize all implementations of a type
|
||||
/// </summary>
|
||||
private static IEnumerable<T>? InitCheckClasses<T>(Assembly assembly)
|
||||
{
|
||||
List<T> classTypes = [];
|
||||
|
||||
// If not all types can be loaded, use the ones that could be
|
||||
List<Type> assemblyTypes = [];
|
||||
// If the extractable file itself fails
|
||||
try
|
||||
{
|
||||
assemblyTypes = assembly.GetTypes().ToList<Type>();
|
||||
// Extract and get the output path
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
bool extracted = impl.Extract(file, exe, tempPath, includeDebug);
|
||||
|
||||
// Collect and format all found protections
|
||||
ProtectionDictionary? subProtections = null;
|
||||
if (extracted && getProtections != null)
|
||||
subProtections = getProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(tempPath))
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
// Prepare the returned protections
|
||||
subProtections?.StripFromKeys(tempPath);
|
||||
subProtections?.PrependToKeys(file);
|
||||
return subProtections ?? [];
|
||||
}
|
||||
catch (ReflectionTypeLoadException rtle)
|
||||
catch (Exception ex)
|
||||
{
|
||||
assemblyTypes = rtle.Types.Where(t => t != null)!.ToList<Type>();
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return [];
|
||||
}
|
||||
|
||||
// Loop through all types
|
||||
foreach (Type type in assemblyTypes)
|
||||
{
|
||||
// If the type isn't a class or doesn't implement the interface
|
||||
if (!type.IsClass || type.GetInterface(typeof(T).Name) == null)
|
||||
continue;
|
||||
|
||||
// Try to create a concrete instance of the type
|
||||
var instance = (T?)Activator.CreateInstance(type);
|
||||
if (instance != null)
|
||||
classTypes.Add(instance);
|
||||
}
|
||||
|
||||
return classTypes;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -585,7 +331,7 @@ namespace BinaryObjectScanner.FileType
|
||||
/// <param name="impl">Implementation that was last used to check</param>
|
||||
private static bool CheckIfGameEngine(object impl)
|
||||
{
|
||||
return impl?.GetType()?.Namespace?.ToLowerInvariant()?.Contains("gameengine") ?? false;
|
||||
return impl.GetType().Namespace?.ToLowerInvariant()?.Contains("gameengine") ?? false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -594,7 +340,7 @@ namespace BinaryObjectScanner.FileType
|
||||
/// <param name="impl">Implementation that was last used to check</param>
|
||||
private static bool CheckIfPacker(object impl)
|
||||
{
|
||||
return impl.GetType()?.Namespace?.ToLowerInvariant()?.Contains("packer") ?? false;
|
||||
return impl.GetType().Namespace?.ToLowerInvariant()?.Contains("packer") ?? false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -11,40 +11,35 @@ namespace BinaryObjectScanner.FileType
|
||||
public class GCF : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create the wrapper
|
||||
var gcf = SabreTools.Serialization.Wrappers.GCF.Create(stream);
|
||||
if (gcf == null)
|
||||
return null;
|
||||
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
return false;
|
||||
|
||||
// Loop through and extract all files
|
||||
ExtractAll(gcf, tempPath);
|
||||
Directory.CreateDirectory(outDir);
|
||||
ExtractAll(gcf, outDir);
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,61 +14,59 @@ namespace BinaryObjectScanner.FileType
|
||||
public class GZIP : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (stream == null)
|
||||
return null;
|
||||
if (stream == null || !stream.CanRead)
|
||||
return false;
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (GZipArchive zipFile = GZipArchive.Open(stream))
|
||||
using var zipFile = GZipArchive.Open(stream);
|
||||
foreach (var entry in zipFile.Entries)
|
||||
{
|
||||
foreach (var entry in zipFile.Entries)
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
string tempFile = Path.Combine(outDir, entry.Key);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return null;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using ISv3 = UnshieldSharp.Archive.InstallShieldArchiveV3;
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
@@ -10,35 +11,31 @@ namespace BinaryObjectScanner.FileType
|
||||
public class InstallShieldArchiveV3 : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
UnshieldSharp.Archive.InstallShieldArchiveV3 archive = new UnshieldSharp.Archive.InstallShieldArchiveV3(file);
|
||||
var archive = new ISv3(file);
|
||||
foreach (var cfile in archive.Files)
|
||||
{
|
||||
try
|
||||
{
|
||||
string tempFile = Path.Combine(tempPath, cfile.Key);
|
||||
string tempFile = Path.Combine(outDir, cfile.Key);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
(byte[]? fileContents, string? error) = archive.Extract(cfile.Key);
|
||||
byte[]? fileContents = archive.Extract(cfile.Key, out string? error);
|
||||
if (fileContents == null || !string.IsNullOrEmpty(error))
|
||||
continue;
|
||||
|
||||
@@ -53,12 +50,12 @@ namespace BinaryObjectScanner.FileType
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,17 +12,17 @@ namespace BinaryObjectScanner.FileType
|
||||
public class InstallShieldCAB : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
// Get the name of the first cabinet file or header
|
||||
var directory = Path.GetDirectoryName(file);
|
||||
@@ -50,17 +50,13 @@ namespace BinaryObjectScanner.FileType
|
||||
|
||||
// If we have anything but the first file
|
||||
if (!shouldScanCabinet)
|
||||
return null;
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
var cabfile = InstallShieldCabinet.Open(file);
|
||||
if (cabfile?.HeaderList == null)
|
||||
return null;
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < cabfile.HeaderList.FileCount; i++)
|
||||
{
|
||||
@@ -74,11 +70,11 @@ namespace BinaryObjectScanner.FileType
|
||||
try
|
||||
{
|
||||
string? filename = cabfile.HeaderList.GetFileName(i);
|
||||
tempFile = Path.Combine(tempPath, filename ?? string.Empty);
|
||||
tempFile = Path.Combine(outDir, filename ?? string.Empty);
|
||||
}
|
||||
catch
|
||||
{
|
||||
tempFile = Path.Combine(tempPath, $"BAD_FILENAME{i}");
|
||||
tempFile = Path.Combine(outDir, $"BAD_FILENAME{i}");
|
||||
}
|
||||
|
||||
cabfile.FileSave(i, tempFile);
|
||||
@@ -89,12 +85,12 @@ namespace BinaryObjectScanner.FileType
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,8 @@ namespace BinaryObjectScanner.FileType
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -28,10 +26,14 @@ namespace BinaryObjectScanner.FileType
|
||||
try
|
||||
{
|
||||
byte[] magic = new byte[16];
|
||||
stream.Read(magic, 0, 16);
|
||||
int read = stream.Read(magic, 0, 16);
|
||||
|
||||
#if NET20
|
||||
if (Extensions.StartsWith(magic, new byte?[] { 0x4C, 0x44, 0x53, 0x43, 0x52, 0x59, 0x50, 0x54 }))
|
||||
#else
|
||||
if (magic.StartsWith(new byte?[] { 0x4C, 0x44, 0x53, 0x43, 0x52, 0x59, 0x50, 0x54 }))
|
||||
return "Link Data Security encrypted file";
|
||||
#endif
|
||||
return "Link Data Security encrypted file";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
#if ((NETFRAMEWORK && !NET20 && !NET35 && !NET40) || NETCOREAPP) && WIN
|
||||
#if (NET452_OR_GREATER || NETCOREAPP) && WIN
|
||||
using StormLibSharp;
|
||||
#endif
|
||||
|
||||
@@ -13,71 +12,68 @@ namespace BinaryObjectScanner.FileType
|
||||
public class MPQ : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
// TODO: Add stream opening support
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
#if NET20 || NET35 || NET40 || !WIN
|
||||
// Not supported for old .NET due to feature requirements
|
||||
// Not supported in non-Windows builds due to DLL requirements
|
||||
return null;
|
||||
return false;
|
||||
#else
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
// Try to open the archive and listfile
|
||||
var mpqArchive = new MpqArchive(file, FileAccess.Read);
|
||||
string? listfile = null;
|
||||
MpqFileStream listStream = mpqArchive.OpenFile("(listfile)");
|
||||
|
||||
using (var mpqArchive = new MpqArchive(file, FileAccess.Read))
|
||||
// If we can't read the listfile, we just return
|
||||
if (!listStream.CanRead)
|
||||
return false;
|
||||
|
||||
// Read the listfile in for processing
|
||||
using (var sr = new StreamReader(listStream))
|
||||
{
|
||||
// Try to open the listfile
|
||||
string? listfile = null;
|
||||
MpqFileStream listStream = mpqArchive.OpenFile("(listfile)");
|
||||
listfile = sr.ReadToEnd();
|
||||
}
|
||||
|
||||
// If we can't read the listfile, we just return
|
||||
if (!listStream.CanRead)
|
||||
return null;
|
||||
// Split the listfile by newlines
|
||||
string[] listfileLines = listfile.Replace("\r\n", "\n").Split('\n');
|
||||
|
||||
// Read the listfile in for processing
|
||||
using (var sr = new StreamReader(listStream))
|
||||
// Loop over each entry
|
||||
foreach (string sub in listfileLines)
|
||||
{
|
||||
try
|
||||
{
|
||||
listfile = sr.ReadToEnd();
|
||||
string tempFile = Path.Combine(outDir, sub);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
mpqArchive.ExtractFile(sub, tempFile);
|
||||
}
|
||||
|
||||
// Split the listfile by newlines
|
||||
string[] listfileLines = listfile.Replace("\r\n", "\n").Split('\n');
|
||||
|
||||
// Loop over each entry
|
||||
foreach (string sub in listfileLines)
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
try
|
||||
{
|
||||
string tempFile = Path.Combine(tempPath, sub);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(tempFile));
|
||||
mpqArchive.ExtractFile(sub, tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
if (includeDebug) System.Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
if (includeDebug) System.Console.WriteLine(ex);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
#if ((NETFRAMEWORK && !NET20 && !NET35 && !NET40) || NETCOREAPP) && WIN
|
||||
#if (NET40_OR_GREATER || NETCOREAPP) && WIN
|
||||
using LibMSPackN;
|
||||
#endif
|
||||
|
||||
@@ -16,53 +14,50 @@ namespace BinaryObjectScanner.FileType
|
||||
public class MicrosoftCAB : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
#if NET20 || NET35 || NET40 || !WIN
|
||||
#if NET20 || NET35 || !WIN
|
||||
// Not supported for old .NET due to feature requirements
|
||||
// Not supported in non-Windows builds due to DLL requirements
|
||||
return null;
|
||||
return false;
|
||||
#else
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (var cabArchive = new MSCabinet(file))
|
||||
// Loop over each entry
|
||||
var cabArchive = new MSCabinet(file);
|
||||
foreach (var compressedFile in cabArchive.GetFiles())
|
||||
{
|
||||
// Loop over each entry
|
||||
foreach (var compressedFile in cabArchive.GetFiles())
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
string tempFile = Path.Combine(tempPath, compressedFile.Filename);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(tempFile));
|
||||
compressedFile.ExtractTo(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
string tempFile = Path.Combine(outDir, compressedFile.Filename);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
compressedFile.ExtractTo(tempFile);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
if (includeDebug) System.Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
if (includeDebug) System.Console.WriteLine(ex);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -12,29 +12,23 @@ namespace BinaryObjectScanner.FileType
|
||||
public class MicrosoftLZ : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
var data = Decompressor.Decompress(stream);
|
||||
if (data == null)
|
||||
return null;
|
||||
return false;
|
||||
|
||||
// Create the temp filename
|
||||
string tempFile = "temp.bin";
|
||||
@@ -49,20 +43,20 @@ namespace BinaryObjectScanner.FileType
|
||||
tempFile += "l";
|
||||
}
|
||||
|
||||
tempFile = Path.Combine(tempPath, tempFile);
|
||||
tempFile = Path.Combine(outDir, tempFile);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
// Write the file data to a temp file
|
||||
using (Stream tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
|
||||
{
|
||||
tempStream.Write(data, 0, data.Length);
|
||||
}
|
||||
using Stream tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
|
||||
tempStream.Write(data, 0, data.Length);
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,40 +10,35 @@ namespace BinaryObjectScanner.FileType
|
||||
public class PAK : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create the wrapper
|
||||
var pak = SabreTools.Serialization.Wrappers.PAK.Create(stream);
|
||||
if (pak == null)
|
||||
return null;
|
||||
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
return false;
|
||||
|
||||
// Loop through and extract all files
|
||||
ExtractAll(pak, tempPath);
|
||||
Directory.CreateDirectory(outDir);
|
||||
ExtractAll(pak, outDir);
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,40 +10,35 @@ namespace BinaryObjectScanner.FileType
|
||||
public class PFF : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create the wrapper
|
||||
var pff = SabreTools.Serialization.Wrappers.PFF.Create(stream);
|
||||
if (pff == null)
|
||||
return null;
|
||||
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
return false;
|
||||
|
||||
// Extract all files
|
||||
ExtractAll(pff, tempPath);
|
||||
Directory.CreateDirectory(outDir);
|
||||
ExtractAll(pff, outDir);
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex.Message);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using BinaryObjectScanner.Interfaces;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Zip;
|
||||
using SharpCompress.Readers;
|
||||
#endif
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
@@ -14,68 +15,72 @@ namespace BinaryObjectScanner.FileType
|
||||
public class PKZIP : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
=> Extract(file, outDir, lookForHeader: false, includeDebug);
|
||||
|
||||
/// <inheritdoc cref="IExtractable.Extract(string, string, bool)"/>
|
||||
public bool Extract(string file, string outDir, bool lookForHeader, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
return Extract(fs, file, outDir, lookForHeader, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
=> Extract(stream, file, outDir, lookForHeader: false, includeDebug);
|
||||
|
||||
/// <inheritdoc cref="IExtractable.Extract(Stream?, string, string, bool)"/>
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool lookForHeader, bool includeDebug)
|
||||
{
|
||||
if (stream == null)
|
||||
return null;
|
||||
if (stream == null || !stream.CanRead)
|
||||
return false;
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (ZipArchive zipFile = ZipArchive.Open(stream))
|
||||
var readerOptions = new ReaderOptions() { LookForHeader = lookForHeader };
|
||||
using var zipFile = ZipArchive.Open(stream, readerOptions);
|
||||
foreach (var entry in zipFile.Entries)
|
||||
{
|
||||
foreach (var entry in zipFile.Entries)
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
|
||||
// If the entry is partial due to an incomplete multi-part archive, skip it
|
||||
if (!entry.IsComplete)
|
||||
continue;
|
||||
// If the entry is partial due to an incomplete multi-part archive, skip it
|
||||
if (!entry.IsComplete)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
string tempFile = Path.Combine(outDir, entry.Key);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return null;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,8 @@ namespace BinaryObjectScanner.FileType
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -28,9 +26,13 @@ namespace BinaryObjectScanner.FileType
|
||||
try
|
||||
{
|
||||
byte[] magic = new byte[16];
|
||||
stream.Read(magic, 0, 16);
|
||||
int read = stream.Read(magic, 0, 16);
|
||||
|
||||
#if NET20
|
||||
if (Extensions.StartsWith(magic, new byte?[] { 0xFF, 0x9D, 0x53, 0x4B }))
|
||||
#else
|
||||
if (magic.StartsWith(new byte?[] { 0xFF, 0x9D, 0x53, 0x4B }))
|
||||
#endif
|
||||
return "PlayJ Audio File";
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -10,40 +10,35 @@ namespace BinaryObjectScanner.FileType
|
||||
public class Quantum : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create the wrapper
|
||||
var quantum = SabreTools.Serialization.Wrappers.Quantum.Create(stream);
|
||||
if (quantum == null)
|
||||
return null;
|
||||
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
return false;
|
||||
|
||||
// Extract all files
|
||||
ExtractAll(quantum, tempPath);
|
||||
Directory.CreateDirectory(outDir);
|
||||
ExtractAll(quantum, outDir);
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex.Message);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using BinaryObjectScanner.Interfaces;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Rar;
|
||||
using SharpCompress.Readers;
|
||||
#endif
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
@@ -14,61 +15,75 @@ namespace BinaryObjectScanner.FileType
|
||||
public class RAR : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
=> Extract(file, outDir, lookForHeader: false, includeDebug);
|
||||
|
||||
/// <inheritdoc cref="IExtractable.Extract(string, string, bool)"/>
|
||||
public bool Extract(string file, string outDir, bool lookForHeader, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
return Extract(fs, file, outDir, lookForHeader, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
=> Extract(stream, file, outDir, lookForHeader: false, includeDebug);
|
||||
|
||||
/// <inheritdoc cref="IExtractable.Extract(Stream?, string, string, bool)"/>
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool lookForHeader, bool includeDebug)
|
||||
{
|
||||
if (stream == null)
|
||||
return null;
|
||||
if (stream == null || !stream.CanRead)
|
||||
return false;
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
var readerOptions = new ReaderOptions() { LookForHeader = lookForHeader };
|
||||
using RarArchive rarFile = RarArchive.Open(stream, readerOptions);
|
||||
if (!rarFile.IsComplete)
|
||||
return false;
|
||||
|
||||
using (RarArchive rarFile = RarArchive.Open(stream))
|
||||
foreach (var entry in rarFile.Entries)
|
||||
{
|
||||
foreach (var entry in rarFile.Entries)
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
// If we have a partial entry due to an incomplete multi-part archive, skip it
|
||||
if (!entry.IsComplete)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(outDir, entry.Key);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return null;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,8 @@ namespace BinaryObjectScanner.FileType
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -30,11 +28,15 @@ namespace BinaryObjectScanner.FileType
|
||||
try
|
||||
{
|
||||
byte[] magic = new byte[16];
|
||||
stream.Read(magic, 0, 16);
|
||||
int read = stream.Read(magic, 0, 16);
|
||||
|
||||
// RASGI2.0
|
||||
// Found in the ".rgs" files in IA item "Nova_RealArcadeCD_USA".
|
||||
#if NET20
|
||||
if (Extensions.StartsWith(magic, new byte?[] { 0x52, 0x41, 0x53, 0x47, 0x49, 0x32, 0x2E, 0x30 }))
|
||||
#else
|
||||
if (magic.StartsWith(new byte?[] { 0x52, 0x41, 0x53, 0x47, 0x49, 0x32, 0x2E, 0x30 }))
|
||||
#endif
|
||||
return "RealArcade Installer";
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -18,10 +18,8 @@ namespace BinaryObjectScanner.FileType
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -30,11 +28,15 @@ namespace BinaryObjectScanner.FileType
|
||||
try
|
||||
{
|
||||
byte[] magic = new byte[16];
|
||||
stream.Read(magic, 0, 16);
|
||||
int read = stream.Read(magic, 0, 16);
|
||||
|
||||
// XZip2.0
|
||||
// Found in the ".mez" files in IA item "Nova_RealArcadeCD_USA".
|
||||
#if NET20
|
||||
if (Extensions.StartsWith(magic, new byte?[] { 0x58, 0x5A, 0x69, 0x70, 0x32, 0x2E, 0x30 }))
|
||||
#else
|
||||
if (magic.StartsWith(new byte?[] { 0x58, 0x5A, 0x69, 0x70, 0x32, 0x2E, 0x30 }))
|
||||
#endif
|
||||
return "RealArcade Mezzanine";
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -17,10 +17,8 @@ namespace BinaryObjectScanner.FileType
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -29,10 +27,14 @@ namespace BinaryObjectScanner.FileType
|
||||
try
|
||||
{
|
||||
byte[] magic = new byte[16];
|
||||
stream.Read(magic, 0, 16);
|
||||
int read = stream.Read(magic, 0, 16);
|
||||
|
||||
#if NET20
|
||||
if (Extensions.StartsWith(magic, new byte?[] { 0x53, 0x46, 0x46, 0x53 }))
|
||||
#else
|
||||
if (magic.StartsWith(new byte?[] { 0x53, 0x46, 0x46, 0x53 }))
|
||||
return "StarForce Filesystem Container";
|
||||
#endif
|
||||
return "StarForce Filesystem Container";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -43,21 +45,19 @@ namespace BinaryObjectScanner.FileType
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Compression.zlib;
|
||||
|
||||
@@ -13,38 +12,35 @@ namespace BinaryObjectScanner.FileType
|
||||
public class SGA : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create the wrapper
|
||||
var sga = SabreTools.Serialization.Wrappers.SGA.Create(stream);
|
||||
if (sga == null)
|
||||
return null;
|
||||
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
return false;
|
||||
|
||||
// Loop through and extract all files
|
||||
ExtractAll(sga, tempPath);
|
||||
Directory.CreateDirectory(outDir);
|
||||
ExtractAll(sga, outDir);
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,16 +51,15 @@ namespace BinaryObjectScanner.FileType
|
||||
/// <returns>True if all files extracted, false otherwise</returns>
|
||||
public static bool ExtractAll(SabreTools.Serialization.Wrappers.SGA item, string outputDirectory)
|
||||
{
|
||||
// Get the number of files
|
||||
int filesLength;
|
||||
switch (item.Model.Header?.MajorVersion)
|
||||
// Get the file count
|
||||
int filesLength = item.Model.Directory switch
|
||||
{
|
||||
case 4: filesLength = (item.Model.Directory as SabreTools.Models.SGA.Directory4)?.Files?.Length ?? 0; break;
|
||||
case 5: filesLength = (item.Model.Directory as SabreTools.Models.SGA.Directory5)?.Files?.Length ?? 0; break;
|
||||
case 6: filesLength = (item.Model.Directory as SabreTools.Models.SGA.Directory6)?.Files?.Length ?? 0; break;
|
||||
case 7: filesLength = (item.Model.Directory as SabreTools.Models.SGA.Directory7)?.Files?.Length ?? 0; break;
|
||||
default: return false;
|
||||
}
|
||||
SabreTools.Models.SGA.Directory4 d4 => filesLength = d4.Files?.Length ?? 0,
|
||||
SabreTools.Models.SGA.Directory5 d5 => filesLength = d5.Files?.Length ?? 0,
|
||||
SabreTools.Models.SGA.Directory6 d6 => filesLength = d6.Files?.Length ?? 0,
|
||||
SabreTools.Models.SGA.Directory7 d7 => filesLength = d7.Files?.Length ?? 0,
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
// If we have no files
|
||||
if (filesLength == 0)
|
||||
@@ -88,16 +83,15 @@ namespace BinaryObjectScanner.FileType
|
||||
/// <returns>True if the file extracted, false otherwise</returns>
|
||||
public static bool ExtractFile(SabreTools.Serialization.Wrappers.SGA item, int index, string outputDirectory)
|
||||
{
|
||||
// Get the number of files
|
||||
int filesLength;
|
||||
switch (item.Model.Header?.MajorVersion)
|
||||
// Get the file count
|
||||
int filesLength = item.Model.Directory switch
|
||||
{
|
||||
case 4: filesLength = (item.Model.Directory as SabreTools.Models.SGA.Directory4)?.Files?.Length ?? 0; break;
|
||||
case 5: filesLength = (item.Model.Directory as SabreTools.Models.SGA.Directory5)?.Files?.Length ?? 0; break;
|
||||
case 6: filesLength = (item.Model.Directory as SabreTools.Models.SGA.Directory6)?.Files?.Length ?? 0; break;
|
||||
case 7: filesLength = (item.Model.Directory as SabreTools.Models.SGA.Directory7)?.Files?.Length ?? 0; break;
|
||||
default: return false;
|
||||
}
|
||||
SabreTools.Models.SGA.Directory4 d4 => filesLength = d4.Files?.Length ?? 0,
|
||||
SabreTools.Models.SGA.Directory5 d5 => filesLength = d5.Files?.Length ?? 0,
|
||||
SabreTools.Models.SGA.Directory6 d6 => filesLength = d6.Files?.Length ?? 0,
|
||||
SabreTools.Models.SGA.Directory7 d7 => filesLength = d7.Files?.Length ?? 0,
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
// If we have no files
|
||||
if (filesLength == 0)
|
||||
@@ -108,55 +102,53 @@ namespace BinaryObjectScanner.FileType
|
||||
return false;
|
||||
|
||||
// Get the files
|
||||
object? file;
|
||||
switch (item.Model.Header?.MajorVersion)
|
||||
object? file = item.Model.Directory switch
|
||||
{
|
||||
case 4: file = (item.Model.Directory as SabreTools.Models.SGA.Directory4)?.Files?[index]; break;
|
||||
case 5: file = (item.Model.Directory as SabreTools.Models.SGA.Directory5)?.Files?[index]; break;
|
||||
case 6: file = (item.Model.Directory as SabreTools.Models.SGA.Directory6)?.Files?[index]; break;
|
||||
case 7: file = (item.Model.Directory as SabreTools.Models.SGA.Directory7)?.Files?[index]; break;
|
||||
default: return false;
|
||||
}
|
||||
SabreTools.Models.SGA.Directory4 d4 => d4.Files![index],
|
||||
SabreTools.Models.SGA.Directory5 d5 => d5.Files![index],
|
||||
SabreTools.Models.SGA.Directory6 d6 => d6.Files![index],
|
||||
SabreTools.Models.SGA.Directory7 d7 => d7.Files![index],
|
||||
_ => null,
|
||||
};
|
||||
|
||||
// If the file is invalid
|
||||
if (file == null)
|
||||
return false;
|
||||
|
||||
// Create the filename
|
||||
var filename = string.Empty;
|
||||
switch (item.Model.Header?.MajorVersion)
|
||||
var filename = file switch
|
||||
{
|
||||
case 4:
|
||||
case 5: filename = (file as SabreTools.Models.SGA.File4)?.Name; break;
|
||||
case 6: filename = (file as SabreTools.Models.SGA.File6)?.Name; break;
|
||||
case 7: filename = (file as SabreTools.Models.SGA.File7)?.Name; break;
|
||||
default: return false;
|
||||
}
|
||||
SabreTools.Models.SGA.File4 f4 => f4.Name,
|
||||
_ => null,
|
||||
};
|
||||
|
||||
// If the filename is invalid
|
||||
if (filename == null)
|
||||
return false;
|
||||
|
||||
// Loop through and get all parent directories
|
||||
var parentNames = new List<string?> { filename };
|
||||
var parentNames = new List<string> { filename };
|
||||
|
||||
// Get the parent directory
|
||||
var folder = default(object);
|
||||
switch (item.Model.Header?.MajorVersion)
|
||||
var folder = item.Model.Directory switch
|
||||
{
|
||||
case 4: folder = (item.Model.Directory as SabreTools.Models.SGA.Directory4)?.Folders?.FirstOrDefault(f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex); break;
|
||||
case 5: folder = (item.Model.Directory as SabreTools.Models.SGA.Directory5)?.Folders?.FirstOrDefault(f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex); break;
|
||||
case 6: folder = (item.Model.Directory as SabreTools.Models.SGA.Directory6)?.Folders?.FirstOrDefault(f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex); break;
|
||||
case 7: folder = (item.Model.Directory as SabreTools.Models.SGA.Directory7)?.Folders?.FirstOrDefault(f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex); break;
|
||||
default: return false;
|
||||
}
|
||||
SabreTools.Models.SGA.Directory4 d4 => Array.Find(d4.Folders ?? [], f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex),
|
||||
SabreTools.Models.SGA.Directory5 d5 => Array.Find(d5.Folders ?? [], f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex),
|
||||
SabreTools.Models.SGA.Directory6 d6 => Array.Find(d6.Folders ?? [], f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex),
|
||||
SabreTools.Models.SGA.Directory7 d7 => Array.Find(d7.Folders ?? [], f => f != null && index >= f.FileStartIndex && index <= f.FileEndIndex),
|
||||
_ => default(object),
|
||||
};
|
||||
|
||||
// If we have a parent folder
|
||||
if (folder != null)
|
||||
{
|
||||
switch (item.Model.Header?.MajorVersion)
|
||||
string folderName = folder switch
|
||||
{
|
||||
case 4: parentNames.Add((folder as SabreTools.Models.SGA.Folder4)?.Name); break;
|
||||
case 5:
|
||||
case 6:
|
||||
case 7: parentNames.Add((folder as SabreTools.Models.SGA.Folder5)?.Name); break;
|
||||
default: return false;
|
||||
}
|
||||
SabreTools.Models.SGA.Folder4 f4 => f4.Name ?? string.Empty,
|
||||
SabreTools.Models.SGA.Folder5 f5 => f5.Name ?? string.Empty,
|
||||
_ => string.Empty,
|
||||
};
|
||||
parentNames.Add(folderName);
|
||||
}
|
||||
|
||||
// TODO: Should the section name/alias be used in the path as well?
|
||||
@@ -164,55 +156,45 @@ namespace BinaryObjectScanner.FileType
|
||||
// Reverse and assemble the filename
|
||||
parentNames.Reverse();
|
||||
#if NET20 || NET35
|
||||
var parentNamesArray = parentNames.Cast<string>().ToArray();
|
||||
filename = parentNamesArray[0];
|
||||
for (int i = 1; i < parentNamesArray.Length; i++)
|
||||
filename = parentNames[0];
|
||||
for (int i = 1; i < parentNames.Count; i++)
|
||||
{
|
||||
filename = Path.Combine(filename, parentNamesArray[i]);
|
||||
filename = Path.Combine(filename, parentNames[i]);
|
||||
}
|
||||
#else
|
||||
filename = Path.Combine(parentNames.Cast<string>().ToArray());
|
||||
filename = Path.Combine([.. parentNames]);
|
||||
#endif
|
||||
|
||||
// Get the file offset
|
||||
long fileOffset;
|
||||
switch (item.Model.Header?.MajorVersion)
|
||||
long fileOffset = file switch
|
||||
{
|
||||
case 4:
|
||||
case 5: fileOffset = (file as SabreTools.Models.SGA.File4)?.Offset ?? 0; break;
|
||||
case 6: fileOffset = (file as SabreTools.Models.SGA.File6)?.Offset ?? 0; break;
|
||||
case 7: fileOffset = (file as SabreTools.Models.SGA.File7)?.Offset ?? 0; break;
|
||||
default: return false;
|
||||
}
|
||||
SabreTools.Models.SGA.File4 f4 => f4.Offset,
|
||||
_ => -1,
|
||||
};
|
||||
|
||||
// Adjust the file offset
|
||||
switch (item.Model.Header?.MajorVersion)
|
||||
fileOffset += item.Model.Header switch
|
||||
{
|
||||
case 4: fileOffset += (item.Model.Header as SabreTools.Models.SGA.Header4)?.FileDataOffset ?? 0; break;
|
||||
case 5: fileOffset += (item.Model.Header as SabreTools.Models.SGA.Header4)?.FileDataOffset ?? 0; break;
|
||||
case 6: fileOffset += (item.Model.Header as SabreTools.Models.SGA.Header6)?.FileDataOffset ?? 0; break;
|
||||
case 7: fileOffset += (item.Model.Header as SabreTools.Models.SGA.Header6)?.FileDataOffset ?? 0; break;
|
||||
default: return false;
|
||||
SabreTools.Models.SGA.Header4 h4 => h4.FileDataOffset,
|
||||
SabreTools.Models.SGA.Header6 h6 => h6.FileDataOffset,
|
||||
_ => -1,
|
||||
};
|
||||
|
||||
// If the offset is invalid
|
||||
if (fileOffset < 0)
|
||||
return false;
|
||||
|
||||
// Get the file sizes
|
||||
long fileSize, outputFileSize;
|
||||
switch (item.Model.Header?.MajorVersion)
|
||||
switch (file)
|
||||
{
|
||||
case 4:
|
||||
case 5:
|
||||
fileSize = (file as SabreTools.Models.SGA.File4)?.SizeOnDisk ?? 0;
|
||||
outputFileSize = (file as SabreTools.Models.SGA.File4)?.Size ?? 0;
|
||||
case SabreTools.Models.SGA.File4 f4:
|
||||
fileSize = f4.SizeOnDisk;
|
||||
outputFileSize = f4.Size;
|
||||
break;
|
||||
case 6:
|
||||
fileSize = (file as SabreTools.Models.SGA.File6)?.SizeOnDisk ?? 0;
|
||||
outputFileSize = (file as SabreTools.Models.SGA.File6)?.Size ?? 0;
|
||||
break;
|
||||
case 7:
|
||||
fileSize = (file as SabreTools.Models.SGA.File7)?.SizeOnDisk ?? 0;
|
||||
outputFileSize = (file as SabreTools.Models.SGA.File7)?.Size ?? 0;
|
||||
break;
|
||||
default: return false;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the compressed data directly
|
||||
|
||||
@@ -4,6 +4,7 @@ using BinaryObjectScanner.Interfaces;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.SevenZip;
|
||||
using SharpCompress.Readers;
|
||||
#endif
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
@@ -14,61 +15,72 @@ namespace BinaryObjectScanner.FileType
|
||||
public class SevenZip : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
=> Extract(file, outDir, lookForHeader: false, includeDebug);
|
||||
|
||||
/// <inheritdoc cref="IExtractable.Extract(string, string, bool)"/>
|
||||
public bool Extract(string file, string outDir, bool lookForHeader, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
return Extract(fs, file, outDir, lookForHeader, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
=> Extract(stream, file, outDir, lookForHeader: false, includeDebug);
|
||||
|
||||
/// <inheritdoc cref="IExtractable.Extract(Stream?, string, string, bool)"/>
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool lookForHeader, bool includeDebug)
|
||||
{
|
||||
if (stream == null)
|
||||
return null;
|
||||
if (stream == null || !stream.CanRead)
|
||||
return false;
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (SevenZipArchive sevenZipFile = SevenZipArchive.Open(stream))
|
||||
var readerOptions = new ReaderOptions() { LookForHeader = lookForHeader };
|
||||
using var sevenZip = SevenZipArchive.Open(stream, readerOptions);
|
||||
foreach (var entry in sevenZip.Entries)
|
||||
{
|
||||
foreach (var entry in sevenZipFile.Entries)
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
// If we have a partial entry due to an incomplete multi-part archive, skip it
|
||||
if (!entry.IsComplete)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(outDir, entry.Key);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return null;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,61 +14,63 @@ namespace BinaryObjectScanner.FileType
|
||||
public class TapeArchive : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (stream == null)
|
||||
return null;
|
||||
if (stream == null || !stream.CanRead)
|
||||
return false;
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (TarArchive tarFile = TarArchive.Open(stream))
|
||||
using var tarFile = TarArchive.Open(stream);
|
||||
foreach (var entry in tarFile.Entries)
|
||||
{
|
||||
foreach (var entry in tarFile.Entries)
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
// If we have a partial entry due to an incomplete multi-part archive, skip it
|
||||
if (!entry.IsComplete)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(outDir, entry.Key);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return null;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,14 @@ namespace BinaryObjectScanner.FileType
|
||||
else if (fileContent.Contains("Please enter a valid registration number"))
|
||||
protections.Add("CD-Key / Serial");
|
||||
|
||||
// Channelware
|
||||
// Found in "README.TXT" in Redump entry 116358.
|
||||
if (fileContent.Contains("This application is a Channelware-activated product."))
|
||||
protections.Add("Channelware");
|
||||
// Found in "Swr.dat" in the "TOYSTORY" installation folder from Redump entry 12354.
|
||||
if (fileContent.Contains("cwsw.com/authts"))
|
||||
protections.Add("Channelware");
|
||||
|
||||
// CopyKiller
|
||||
// Found in "autorun.dat" in CopyKiller versions 3.62 and 3.64.
|
||||
if (fileContent.Contains("CopyKiller CD-Protection V3.6x"))
|
||||
@@ -100,8 +108,14 @@ namespace BinaryObjectScanner.FileType
|
||||
protections.Add("MediaMax CD-3");
|
||||
|
||||
// phenoProtect
|
||||
// Found in Redump entry 84082.
|
||||
if (fileContent.Contains("phenoProtect"))
|
||||
protections.Add("phenoProtect");
|
||||
// Additional check to minimize overmatching.
|
||||
if (fileContent.Contains("InstallSHIELD Software Coporation"))
|
||||
// Found in Redump entry 102493.
|
||||
if (fileContent.Contains("COPYPROTECTION_FAILEDR"))
|
||||
protections.Add("phenoProtect");
|
||||
|
||||
// Rainbow Sentinel
|
||||
// Found in "SENTW95.HLP" and "SENTINEL.HLP" in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]".
|
||||
@@ -117,6 +131,11 @@ namespace BinaryObjectScanner.FileType
|
||||
if (fileContent.Contains("Sentinel Driver Disk"))
|
||||
protections.Add("Rainbow Sentinel");
|
||||
|
||||
// SafeCast
|
||||
// Found in "AdlmLog.xml" in IA item game-programming-in-c-start-to-finish-2006 after installing "3dsMax8_Demo.zip".
|
||||
if (fileContent.Contains("<NAME>SAFECAST</NAME>"))
|
||||
protections.Add("SafeCast");
|
||||
|
||||
// SafeDisc
|
||||
// TODO: Add better version parsing.
|
||||
// Found in "Info.plist" in Redump entries 23983, 42762, 72713, 73070, and 89603.
|
||||
|
||||
@@ -10,40 +10,35 @@ namespace BinaryObjectScanner.FileType
|
||||
public class VBSP : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create the wrapper
|
||||
var vbsp = SabreTools.Serialization.Wrappers.VBSP.Create(stream);
|
||||
if (vbsp == null)
|
||||
return null;
|
||||
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
return false;
|
||||
|
||||
// Loop through and extract all files
|
||||
ExtractAllLumps(vbsp, tempPath);
|
||||
Directory.CreateDirectory(outDir);
|
||||
ExtractAllLumps(vbsp, outDir);
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex.ToString());
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.IO.Extensions;
|
||||
|
||||
@@ -12,40 +11,35 @@ namespace BinaryObjectScanner.FileType
|
||||
public class VPK : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create the wrapper
|
||||
var vpk = SabreTools.Serialization.Wrappers.VPK.Create(stream);
|
||||
if (vpk == null)
|
||||
return null;
|
||||
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
return false;
|
||||
|
||||
// Loop through and extract all files
|
||||
ExtractAll(vpk, tempPath);
|
||||
Directory.CreateDirectory(outDir);
|
||||
ExtractAll(vpk, outDir);
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +137,7 @@ namespace BinaryObjectScanner.FileType
|
||||
|
||||
// If we have preload data, prepend it
|
||||
if (data != null && directoryItem.PreloadData != null)
|
||||
data = directoryItem.PreloadData.Concat(data).ToArray();
|
||||
data = [.. directoryItem.PreloadData, .. data];
|
||||
}
|
||||
|
||||
// If there is nothing to write out
|
||||
|
||||
@@ -10,40 +10,35 @@ namespace BinaryObjectScanner.FileType
|
||||
public class WAD : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create the wrapper
|
||||
var wad = SabreTools.Serialization.Wrappers.WAD.Create(stream);
|
||||
if (wad == null)
|
||||
return null;
|
||||
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
return false;
|
||||
|
||||
// Loop through and extract all files
|
||||
ExtractAllLumps(wad, tempPath);
|
||||
Directory.CreateDirectory(outDir);
|
||||
ExtractAllLumps(wad, outDir);
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,43 +13,41 @@ namespace BinaryObjectScanner.FileType
|
||||
public class XZ : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
// Try opening the stream
|
||||
using var xzFile = new XZStream(stream);
|
||||
|
||||
using (XZStream xzFile = new XZStream(stream))
|
||||
{
|
||||
string tempFile = Path.Combine(tempPath, Guid.NewGuid().ToString());
|
||||
using (FileStream fs = File.OpenWrite(tempFile))
|
||||
{
|
||||
xzFile.CopyTo(fs);
|
||||
}
|
||||
}
|
||||
// Create the output file path
|
||||
Directory.CreateDirectory(outDir);
|
||||
string tempFile = Path.Combine(outDir, Guid.NewGuid().ToString());
|
||||
|
||||
return tempPath;
|
||||
// Extract the file
|
||||
using FileStream fs = File.OpenWrite(tempFile);
|
||||
xzFile.CopyTo(fs);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return null;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
@@ -11,40 +10,35 @@ namespace BinaryObjectScanner.FileType
|
||||
public class XZP : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
public bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
return false;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, outDir, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
public bool Extract(Stream? stream, string file, string outDir, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create the wrapper
|
||||
var xzp = SabreTools.Serialization.Wrappers.XZP.Create(stream);
|
||||
if (xzp == null)
|
||||
return null;
|
||||
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
return false;
|
||||
|
||||
// Loop through and extract all files
|
||||
ExtractAll(xzp, tempPath);
|
||||
Directory.CreateDirectory(outDir);
|
||||
ExtractAll(xzp, outDir);
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +89,7 @@ namespace BinaryObjectScanner.FileType
|
||||
return false;
|
||||
|
||||
// Get the associated directory item
|
||||
var directoryItem = item.Model.DirectoryItems.Where(di => di?.FileNameCRC == directoryEntry.FileNameCRC).FirstOrDefault();
|
||||
var directoryItem = Array.Find(item.Model.DirectoryItems, di => di?.FileNameCRC == directoryEntry.FileNameCRC);
|
||||
if (directoryItem == null)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -15,10 +15,10 @@ namespace BinaryObjectScanner.GameEngine
|
||||
/// RenderWare 3.7 SDK: https://github.com/sigmaco/rwsdk-v37-pc
|
||||
/// Wikipedia list of RenderWare games: https://en.wikipedia.org/wiki/Category:RenderWare_games
|
||||
/// </summary>
|
||||
public class RenderWare : IPortableExecutableCheck
|
||||
public class RenderWare : IExecutableCheck<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
|
||||
@@ -1,478 +0,0 @@
|
||||
using System;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Collections.Concurrent;
|
||||
#endif
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Utilities;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
using static BinaryObjectScanner.Utilities.Dictionary;
|
||||
|
||||
namespace BinaryObjectScanner
|
||||
{
|
||||
internal static class Handler
|
||||
{
|
||||
#region Public Collections
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IPathCheck types
|
||||
/// </summary>
|
||||
public static IEnumerable<IPathCheck?> PathCheckClasses
|
||||
{
|
||||
get
|
||||
{
|
||||
pathCheckClasses ??= InitCheckClasses<IPathCheck>();
|
||||
return pathCheckClasses;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Internal Instances
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IPathCheck types
|
||||
/// </summary>
|
||||
private static IEnumerable<IPathCheck?>? pathCheckClasses;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Multiple Implementation Wrappers
|
||||
|
||||
/// <summary>
|
||||
/// Handle a single path based on all path check implementations
|
||||
/// </summary>
|
||||
/// <param name="path">Path of the file or directory to check</param>
|
||||
/// <param name="scanner">Scanner object to use for options and scanning</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
public static Dictionary<string, Queue<string>> HandlePathChecks(string path, IEnumerable<string>? files)
|
||||
#else
|
||||
public static ConcurrentDictionary<string, ConcurrentQueue<string>> HandlePathChecks(string path, IEnumerable<string>? files)
|
||||
#endif
|
||||
{
|
||||
// Create the output dictionary
|
||||
#if NET20 || NET35
|
||||
var protections = new Dictionary<string, Queue<string>>();
|
||||
#else
|
||||
var protections = new ConcurrentDictionary<string, ConcurrentQueue<string>>();
|
||||
#endif
|
||||
|
||||
// Preprocess the list of files
|
||||
files = files?.Select(f => f.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar))?.ToList();
|
||||
|
||||
// Iterate through all checks
|
||||
#if NET20 || NET35
|
||||
foreach (var checkClass in PathCheckClasses)
|
||||
#else
|
||||
Parallel.ForEach(PathCheckClasses, checkClass =>
|
||||
#endif
|
||||
{
|
||||
var subProtections = checkClass?.PerformCheck(path, files);
|
||||
if (subProtections != null)
|
||||
AppendToDictionary(protections, path, subProtections);
|
||||
#if NET20 || NET35
|
||||
}
|
||||
#else
|
||||
});
|
||||
#endif
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Single Implementation Handlers
|
||||
|
||||
/// <summary>
|
||||
/// Handle files based on an IDetectable implementation
|
||||
/// </summary>
|
||||
/// <param name="impl">IDetectable class representing the file type</param>
|
||||
/// <param name="fileName">Name of the source file of the stream, for tracking</param>
|
||||
/// <param name="stream">Stream to scan the contents of</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
public static Queue<string>? HandleDetectable(IDetectable impl, string fileName, Stream stream, bool includeDebug)
|
||||
#else
|
||||
public static ConcurrentQueue<string>? HandleDetectable(IDetectable impl, string fileName, Stream stream, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
var protection = impl.Detect(stream, fileName, includeDebug);
|
||||
return ProcessProtectionString(protection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle files based on an IExtractable implementation
|
||||
/// </summary>
|
||||
/// <param name="impl">IExtractable class representing the file type</param>
|
||||
/// <param name="fileName">Name of the source file of the stream, for tracking</param>
|
||||
/// <param name="stream">Stream to scan the contents of</param>
|
||||
/// <param name="scanner">Scanner object to use on extractable contents</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
public static Dictionary<string, Queue<string>>? HandleExtractable(IExtractable impl, string fileName, Stream? stream, Scanner scanner)
|
||||
#else
|
||||
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractable impl, string fileName, Stream? stream, Scanner scanner)
|
||||
#endif
|
||||
{
|
||||
// If the extractable file itself fails
|
||||
try
|
||||
{
|
||||
// Extract and get the output path
|
||||
var tempPath = impl.Extract(stream, fileName, scanner.IncludeDebug);
|
||||
if (tempPath == null)
|
||||
return null;
|
||||
|
||||
// Collect and format all found protections
|
||||
var subProtections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
// Prepare the returned protections
|
||||
StripFromKeys(subProtections, tempPath);
|
||||
PrependToKeys(subProtections, fileName);
|
||||
return subProtections;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle files based on an IExtractableMSDOSExecutable implementation
|
||||
/// </summary>
|
||||
/// <param name="impl">IExtractableMSDOSExecutable class representing the file type</param>
|
||||
/// <param name="fileName">Name of the source file of the stream, for tracking</param>
|
||||
/// <param name="mz">MSDOS to scan the contents of</param>
|
||||
/// <param name="scanner">Scanner object to use on extractable contents</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
public static Dictionary<string, Queue<string>>? HandleExtractable(IExtractableMSDOSExecutable impl, string fileName, MSDOS mz, Scanner scanner)
|
||||
#else
|
||||
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractableMSDOSExecutable impl, string fileName, MSDOS mz, Scanner scanner)
|
||||
#endif
|
||||
{
|
||||
// If the extractable file itself fails
|
||||
try
|
||||
{
|
||||
// Extract and get the output path
|
||||
var tempPath = impl.Extract(fileName, mz, scanner.IncludeDebug);
|
||||
if (tempPath == null)
|
||||
return null;
|
||||
|
||||
// Collect and format all found protections
|
||||
var subProtections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
// Prepare the returned protections
|
||||
StripFromKeys(subProtections, tempPath);
|
||||
PrependToKeys(subProtections, fileName);
|
||||
return subProtections;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle files based on an IExtractableLinearExecutable implementation
|
||||
/// </summary>
|
||||
/// <param name="impl">IExtractableLinearExecutable class representing the file type</param>
|
||||
/// <param name="fileName">Name of the source file of the stream, for tracking</param>
|
||||
/// <param name="lex">LinearExecutable to scan the contents of</param>
|
||||
/// <param name="scanner">Scanner object to use on extractable contents</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
public static Dictionary<string, Queue<string>>? HandleExtractable(IExtractableLinearExecutable impl, string fileName, LinearExecutable lex, Scanner scanner)
|
||||
#else
|
||||
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractableLinearExecutable impl, string fileName, LinearExecutable lex, Scanner scanner)
|
||||
#endif
|
||||
{
|
||||
// If the extractable file itself fails
|
||||
try
|
||||
{
|
||||
// Extract and get the output path
|
||||
var tempPath = impl.Extract(fileName, lex, scanner.IncludeDebug);
|
||||
if (tempPath == null)
|
||||
return null;
|
||||
|
||||
// Collect and format all found protections
|
||||
var subProtections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
// Prepare the returned protections
|
||||
StripFromKeys(subProtections, tempPath);
|
||||
PrependToKeys(subProtections, fileName);
|
||||
return subProtections;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle files based on an IExtractableNewExecutable implementation
|
||||
/// </summary>
|
||||
/// <param name="impl">IExtractableNewExecutable class representing the file type</param>
|
||||
/// <param name="fileName">Name of the source file of the stream, for tracking</param>
|
||||
/// <param name="nex">NewExecutable to scan the contents of</param>
|
||||
/// <param name="scanner">Scanner object to use on extractable contents</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
public static Dictionary<string, Queue<string>>? HandleExtractable(IExtractableNewExecutable impl, string fileName, NewExecutable nex, Scanner scanner)
|
||||
#else
|
||||
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractableNewExecutable impl, string fileName, NewExecutable nex, Scanner scanner)
|
||||
#endif
|
||||
{
|
||||
// If the extractable file itself fails
|
||||
try
|
||||
{
|
||||
// Extract and get the output path
|
||||
var tempPath = impl.Extract(fileName, nex, scanner.IncludeDebug);
|
||||
if (tempPath == null)
|
||||
return null;
|
||||
|
||||
// Collect and format all found protections
|
||||
var subProtections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
// Prepare the returned protections
|
||||
StripFromKeys(subProtections, tempPath);
|
||||
PrependToKeys(subProtections, fileName);
|
||||
return subProtections;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle files based on an IExtractablePortableExecutable implementation
|
||||
/// </summary>
|
||||
/// <param name="impl">IExtractablePortableExecutable class representing the file type</param>
|
||||
/// <param name="fileName">Name of the source file of the stream, for tracking</param>
|
||||
/// <param name="pex">PortableExecutable to scan the contents of</param>
|
||||
/// <param name="scanner">Scanner object to use on extractable contents</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
public static Dictionary<string, Queue<string>>? HandleExtractable(IExtractablePortableExecutable impl, string fileName, PortableExecutable pex, Scanner scanner)
|
||||
#else
|
||||
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractablePortableExecutable impl, string fileName, PortableExecutable pex, Scanner scanner)
|
||||
#endif
|
||||
{
|
||||
// If the extractable file itself fails
|
||||
try
|
||||
{
|
||||
// Extract and get the output path
|
||||
var tempPath = impl.Extract(fileName, pex, scanner.IncludeDebug);
|
||||
if (tempPath == null)
|
||||
return null;
|
||||
|
||||
// Collect and format all found protections
|
||||
var subProtections = scanner.GetProtections(tempPath);
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
// Prepare the returned protections
|
||||
StripFromKeys(subProtections, tempPath);
|
||||
PrependToKeys(subProtections, fileName);
|
||||
return subProtections;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (scanner.IncludeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle files based on an IPathCheck implementation
|
||||
/// </summary>
|
||||
/// <param name="impl">IPathCheck class representing the file type</param>
|
||||
/// <param name="path">Path of the file or directory to check</param>
|
||||
/// <returns>Set of protections in path, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
private static Queue<string>? PerformCheck(this IPathCheck impl, string? path, IEnumerable<string>? files)
|
||||
#else
|
||||
private static ConcurrentQueue<string>? PerformCheck(this IPathCheck impl, string? path, IEnumerable<string>? files)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid path
|
||||
if (string.IsNullOrEmpty(path))
|
||||
return null;
|
||||
|
||||
// Setup the output dictionary
|
||||
#if NET20 || NET35
|
||||
var protections = new Queue<string>();
|
||||
#else
|
||||
var protections = new ConcurrentQueue<string>();
|
||||
#endif
|
||||
|
||||
// If we have a file path
|
||||
if (File.Exists(path))
|
||||
{
|
||||
var protection = impl.CheckFilePath(path!);
|
||||
var subProtections = ProcessProtectionString(protection);
|
||||
if (subProtections != null)
|
||||
protections.AddRange(subProtections);
|
||||
}
|
||||
|
||||
// If we have a directory path
|
||||
if (Directory.Exists(path) && files?.Any() == true)
|
||||
{
|
||||
var subProtections = impl.CheckDirectoryPath(path!, files);
|
||||
if (subProtections != null)
|
||||
protections.AddRange(subProtections);
|
||||
}
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Initializers
|
||||
|
||||
/// <summary>
|
||||
/// Initialize all implementations of a type
|
||||
/// </summary>
|
||||
private static IEnumerable<T?> InitCheckClasses<T>() =>
|
||||
InitCheckClasses<T>(Assembly.GetExecutingAssembly());
|
||||
|
||||
/// <summary>
|
||||
/// Initialize all implementations of a type
|
||||
/// </summary>
|
||||
private static IEnumerable<T?> InitCheckClasses<T>(Assembly assembly)
|
||||
{
|
||||
List<T?> classTypes = [];
|
||||
|
||||
// If not all types can be loaded, use the ones that could be
|
||||
List<Type> assemblyTypes = [];
|
||||
try
|
||||
{
|
||||
assemblyTypes = assembly.GetTypes().ToList<Type>();
|
||||
}
|
||||
catch (ReflectionTypeLoadException rtle)
|
||||
{
|
||||
assemblyTypes = rtle.Types.Where(t => t != null)!.ToList<Type>();
|
||||
}
|
||||
|
||||
// Loop through all types
|
||||
foreach (Type type in assemblyTypes)
|
||||
{
|
||||
// If the type isn't a class or doesn't implement the interface
|
||||
if (!type.IsClass || type.GetInterface(typeof(T).Name) == null)
|
||||
continue;
|
||||
|
||||
// Try to create a concrete instance of the type
|
||||
var instance = (T?)Activator.CreateInstance(type);
|
||||
if (instance != null)
|
||||
classTypes.Add(instance);
|
||||
}
|
||||
|
||||
return classTypes;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Process a protection string if it includes multiple protections
|
||||
/// </summary>
|
||||
/// <param name="protection">Protection string to process</param>
|
||||
/// <returns>Set of protections parsed, null on error</returns>
|
||||
#if NET20 || NET35
|
||||
private static Queue<string>? ProcessProtectionString(string? protection)
|
||||
#else
|
||||
private static ConcurrentQueue<string>? ProcessProtectionString(string? protection)
|
||||
#endif
|
||||
{
|
||||
// If we have an invalid protection string
|
||||
if (string.IsNullOrEmpty(protection))
|
||||
return null;
|
||||
|
||||
// Setup the output queue
|
||||
#if NET20 || NET35
|
||||
var protections = new Queue<string>();
|
||||
#else
|
||||
var protections = new ConcurrentQueue<string>();
|
||||
#endif
|
||||
|
||||
// If we have an indicator of multiple protections
|
||||
if (protection!.Contains(";"))
|
||||
{
|
||||
var splitProtections = protection.Split(';');
|
||||
protections.AddRange(splitProtections);
|
||||
}
|
||||
else
|
||||
{
|
||||
protections.Enqueue(protection);
|
||||
}
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,19 @@
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Check a MS-DOS Executable (MZ) for protection
|
||||
/// Check an executable for protection
|
||||
/// </summary>
|
||||
public interface IMSDOSExecutableCheck
|
||||
public interface IExecutableCheck<T> where T : WrapperBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Check a path for protections based on file contents
|
||||
/// </summary>
|
||||
/// <param name="file">File to check for protection indicators</param>
|
||||
/// <param name="mz">MSDOS representing the read-in file</param>
|
||||
/// <param name="exe">Executable representing the read-in file</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>String containing any protections found in the file</returns>
|
||||
string? CheckMSDOSExecutable(string file, MSDOS mz, bool includeDebug);
|
||||
string? CheckExecutable(string file, T exe, bool includeDebug);
|
||||
}
|
||||
}
|
||||
@@ -5,26 +5,26 @@ namespace BinaryObjectScanner.Interfaces
|
||||
/// <summary>
|
||||
/// Mark a file type as being able to be extracted
|
||||
/// </summary>
|
||||
/// TODO: Change to have output directory passed in
|
||||
/// TODO: Change to return a bool
|
||||
public interface IExtractable
|
||||
{
|
||||
/// <summary>
|
||||
/// Extract a file to a temporary path, if possible
|
||||
/// </summary>
|
||||
/// <param name="file">Path to the input file</param>
|
||||
/// <param name="outDir">Path to the output directory</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Path to extracted files, null on error</returns>
|
||||
/// <returns>Indicates if the extractable was successfully extracted</returns>
|
||||
/// <remarks>Ideally, this should just point to the other extract implementation.</remarks>
|
||||
string? Extract(string file, bool includeDebug);
|
||||
bool Extract(string file, string outDir, bool includeDebug);
|
||||
|
||||
/// <summary>
|
||||
/// Extract a stream to a temporary path, if possible
|
||||
/// </summary>
|
||||
/// <param name="stream">Stream representing the input file</param>
|
||||
/// <param name="file">Path to the input file</param>
|
||||
/// <param name="outDir">Path to the output directory</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Path to extracted files, null on error</returns>
|
||||
string? Extract(Stream? stream, string file, bool includeDebug);
|
||||
/// <returns>Indicates if the extractable was successfully extracted</returns>
|
||||
bool Extract(Stream? stream, string file, string outDir, bool includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
20
BinaryObjectScanner/Interfaces/IExtractableExecutable.cs
Normal file
20
BinaryObjectScanner/Interfaces/IExtractableExecutable.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Mark an executable type as being able to be extracted
|
||||
/// </summary>
|
||||
public interface IExtractableExecutable<T> : IExecutableCheck<T> where T : WrapperBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Extract an Executable to a path, if possible
|
||||
/// </summary>
|
||||
/// <param name="file">Path to the input file</param>
|
||||
/// <param name="exe">Executable representing the read-in file</param>
|
||||
/// <param name="outDir">Path to the output directory</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Path to extracted files, null on error</returns>
|
||||
bool Extract(string file, T exe, string outDir, bool includeDebug);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Mark a LinearExecutable type as being able to be extracted
|
||||
/// </summary>
|
||||
public interface IExtractableLinearExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// Extract a LinearExecutable to a temporary path, if possible
|
||||
/// </summary>
|
||||
/// <param name="file">Path to the input file</param>
|
||||
/// <param name="lex">LinearExecutable representing the read-in file</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Path to extracted files, null on error</returns>
|
||||
string? Extract(string file, LinearExecutable lex, bool includeDebug);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Mark a MSDOS type as being able to be extracted
|
||||
/// </summary>
|
||||
public interface IExtractableMSDOSExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// Extract a MSDOS to a temporary path, if possible
|
||||
/// </summary>
|
||||
/// <param name="file">Path to the input file</param>
|
||||
/// <param name="mz">MSDOS representing the read-in file</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Path to extracted files, null on error</returns>
|
||||
string? Extract(string file, MSDOS mz, bool includeDebug);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Mark a NewExecutable type as being able to be extracted
|
||||
/// </summary>
|
||||
public interface IExtractableNewExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// Extract a NewExecutable to a temporary path, if possible
|
||||
/// </summary>
|
||||
/// <param name="file">Path to the input file</param>
|
||||
/// <param name="nex">NewExecutable representing the read-in file</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Path to extracted files, null on error</returns>
|
||||
string? Extract(string file, NewExecutable nex, bool includeDebug);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Mark a PortableExecutable type as being able to be extracted
|
||||
/// </summary>
|
||||
public interface IExtractablePortableExecutable
|
||||
{
|
||||
/// <summary>
|
||||
/// Extract a PortableExecutable to a temporary path, if possible
|
||||
/// </summary>
|
||||
/// <param name="file">Path to the input file</param>
|
||||
/// <param name="pex">PortableExecutable representing the read-in file</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Path to extracted files, null on error</returns>
|
||||
string? Extract(string file, PortableExecutable pex, bool includeDebug);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Check a Linear Executable (LE) for protection
|
||||
/// </summary>
|
||||
public interface ILinearExecutableCheck
|
||||
{
|
||||
/// <summary>
|
||||
/// Check a path for protections based on file contents
|
||||
/// </summary>
|
||||
/// <param name="file">File to check for protection indicators</param>
|
||||
/// <param name="lex">LinearExecutable 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? CheckLinearExecutable(string file, LinearExecutable lex, bool includeDebug);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Check a New Executable (NE) for protection
|
||||
/// </summary>
|
||||
public interface INewExecutableCheck
|
||||
{
|
||||
/// <summary>
|
||||
/// Check a path for protections based on file contents
|
||||
/// </summary>
|
||||
/// <param name="file">File to check for protection indicators</param>
|
||||
/// <param name="nex">NewExecutable 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? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,4 @@
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Collections.Concurrent;
|
||||
#endif
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BinaryObjectScanner.Interfaces
|
||||
{
|
||||
@@ -19,11 +16,7 @@ namespace BinaryObjectScanner.Interfaces
|
||||
/// <param name="path">Path to check for protection indicators</param>
|
||||
/// <param name="files">Enumerable of strings representing files in a directory</param>
|
||||
/// <remarks>This can do some limited content checking as well, but it's suggested to use a content check instead, if possible</remarks>
|
||||
#if NET20 || NET35
|
||||
Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files);
|
||||
#else
|
||||
ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files);
|
||||
#endif
|
||||
IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files);
|
||||
|
||||
/// <summary>
|
||||
/// Check a file path for protections based on path name
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Check a Portable Executable (PE) for protection
|
||||
/// </summary>
|
||||
public interface IPortableExecutableCheck
|
||||
{
|
||||
/// <summary>
|
||||
/// Check a path for protections based on file contents
|
||||
/// </summary>
|
||||
/// <param name="file">File to check for protection indicators</param>
|
||||
/// <param name="pex">PortableExecutable 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? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug);
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,16 @@ using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
public class ASPack : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class ASPack : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -50,9 +51,9 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
@@ -6,10 +5,10 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
// TODO: Verify that all versions are detected
|
||||
public class AdvancedInstaller : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class AdvancedInstaller : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -20,7 +19,7 @@ namespace BinaryObjectScanner.Packer
|
||||
var strs = pex.GetFirstSectionStrings(".rdata");
|
||||
if (strs != null)
|
||||
{
|
||||
if (strs.Any(s => s.Contains("Software\\Caphyon\\Advanced Installer")))
|
||||
if (strs.Exists(s => s.Contains("Software\\Caphyon\\Advanced Installer")))
|
||||
return "Caphyon Advanced Installer";
|
||||
}
|
||||
|
||||
@@ -28,9 +27,9 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
// TODO: Add version checking, if possible
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class Armadillo : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
// Get the .nicode section, if it exists
|
||||
bool nicodeSection = pex.ContainsSection(".nicode", exact: true);
|
||||
if (nicodeSection)
|
||||
return "Armadillo";
|
||||
|
||||
// Loop through all "extension" sections -- usually .data1 or .text1
|
||||
if (pex.SectionNames != null)
|
||||
{
|
||||
foreach (var sectionName in pex.SectionNames.Where(s => s != null && s.EndsWith("1")))
|
||||
{
|
||||
// Get the section strings, if they exist
|
||||
var strs = pex.GetFirstSectionStrings(sectionName);
|
||||
if (strs != null)
|
||||
{
|
||||
if (strs.Any(s => s.Contains("ARMDEBUG")))
|
||||
return "Armadillo";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,10 +7,10 @@ namespace BinaryObjectScanner.Packer
|
||||
// Created by IndigoRose (creators of Setup Factory), primarily to be used to create autorun menus for various media.
|
||||
// Official website: https://www.autoplay.org/
|
||||
// TODO: Add extraction
|
||||
public class AutoPlayMediaStudio : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class AutoPlayMediaStudio : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -33,9 +33,9 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private string GetVersion(PortableExecutable pex)
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Compression.zlib;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
@@ -12,10 +13,10 @@ namespace BinaryObjectScanner.Packer
|
||||
// The official website for CExe also includes the source code (which does have to be retrieved by the Wayback Machine)
|
||||
// http://www.scottlu.com/Content/CExe.html
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class CExe : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class CExe : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -50,14 +51,14 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get the first resource of type 99 with index 2
|
||||
var payload = pex.FindResourceByNamedType("99, 2").FirstOrDefault();
|
||||
if (payload == null || payload.Length == 0)
|
||||
return null;
|
||||
return false;
|
||||
|
||||
// Determine which compression was used
|
||||
bool zlib = pex.FindResourceByNamedType("99, 1").Any();
|
||||
@@ -93,12 +94,12 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
// Trim the buffer to the proper size
|
||||
uint read = zstream.total_out;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
data = new ReadOnlySpan<byte>(data, 0, (int)read).ToArray();
|
||||
#else
|
||||
#if NETFRAMEWORK
|
||||
var temp = new byte[read];
|
||||
Array.Copy(data, 0, temp, 0, read);
|
||||
data = temp;
|
||||
#else
|
||||
data = new ReadOnlySpan<byte>(data, 0, (int)read).ToArray();
|
||||
#endif
|
||||
}
|
||||
catch
|
||||
@@ -124,27 +125,25 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
// If we have no data
|
||||
if (data == null)
|
||||
return null;
|
||||
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
return false;
|
||||
|
||||
// Create the temp filename
|
||||
string tempFile = string.IsNullOrEmpty(file) ? "temp.sxe" : $"{Path.GetFileNameWithoutExtension(file)}.sxe";
|
||||
tempFile = Path.Combine(tempPath, tempFile);
|
||||
tempFile = Path.Combine(outDir, tempFile);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
// Write the file data to a temp file
|
||||
using (Stream tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
|
||||
{
|
||||
tempStream.Write(data, 0, data.Length);
|
||||
}
|
||||
var tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
|
||||
tempStream.Write(data, 0, data.Length);
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
public class dotFuscator : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class DotFuscator : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -19,7 +18,7 @@ namespace BinaryObjectScanner.Packer
|
||||
var strs = pex.GetFirstSectionStrings(".text");
|
||||
if (strs != null)
|
||||
{
|
||||
if (strs.Any(s => s.Contains("DotfuscatorAttribute")))
|
||||
if (strs.Exists(s => s.Contains("DotfuscatorAttribute")))
|
||||
return "dotFuscator";
|
||||
}
|
||||
|
||||
@@ -27,9 +26,9 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
106
BinaryObjectScanner/Packer/DotNetReactor.cs
Normal file
106
BinaryObjectScanner/Packer/DotNetReactor.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
using System.Collections.Generic;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
/// <summary>
|
||||
/// .NET Reactor is a .NET obfuscator that was original released in 2004. https://web.archive.org/web/20040828162124/http://eziriz.com:80/
|
||||
/// It is currently still being updated and supported. https://www.eziriz.com/dotnet_reactor.htm
|
||||
/// While ProtectionID does detect .NET Reactor, it's currently unknown exactly how.
|
||||
/// It seems to simply check for the string "<PrivateImplementationDetails>" in specific, and currently unknown, conditions but appears to be prone to false positives.
|
||||
/// A "Demo/Nag Screen" version is available for free, and may be able to be used to make samples to improve detections. https://www.eziriz.com/reactor_download.htm
|
||||
///
|
||||
/// Resource that could be useful for extraction: https://github.com/SychicBoy/NETReactorSlayer
|
||||
/// </summary>
|
||||
public class DotNetReactor : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// TODO: Detect version
|
||||
// TODO: Further refine checks using https://github.com/horsicq/Detect-It-Easy/blob/075a70b1484d1d84d1dc37c86aac16188d5a84e7/db/PE/NetReactor.2.sg and https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
// Get the .text section, if it exists
|
||||
if (pex.ContainsSection(".text"))
|
||||
{
|
||||
var textData = pex.GetFirstSectionData(".text");
|
||||
if (textData != null)
|
||||
{
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
// Adapted from https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar and confirmed to work with "KalypsoLauncher.dll" from Redump entry 95617.
|
||||
// <PrivateImplementationDetails>{[8]-[4]-[4]-[4]-[12]}
|
||||
new(new byte?[]
|
||||
{
|
||||
0x3C, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65,
|
||||
0x49, 0x6D, 0x70, 0x6C, 0x65, 0x6D, 0x65, 0x6E,
|
||||
0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 0x65,
|
||||
0x74, 0x61, 0x69, 0x6C, 0x73, 0x3E, 0x7B, null,
|
||||
null, null, null, null, null, null, null, 0x2D,
|
||||
null, null, null, null, 0x2D, null, null, null,
|
||||
null, 0x2D, null, null, null, null, 0x2D, null,
|
||||
null, null, null, null, null, null, null, null,
|
||||
null, null, null, 0x7D
|
||||
}, ".NET Reactor"),
|
||||
|
||||
// Modified from the previous detection to detect a presumably newer version of .NET Reactor found in "KalypsoLauncher.dll" version 2.0.4.2.
|
||||
// TODO: Check if this can/should be made more specific.
|
||||
// <PrivateImplementationDetails>.RSA
|
||||
new(new byte?[]
|
||||
{
|
||||
0x3C, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65,
|
||||
0x49, 0x6D, 0x70, 0x6C, 0x65, 0x6D, 0x65, 0x6E,
|
||||
0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 0x65,
|
||||
0x74, 0x61, 0x69, 0x6C, 0x73, 0x3E, 0x00, 0x52,
|
||||
0x53, 0x41
|
||||
}, ".NET Reactor"),
|
||||
|
||||
// Adapted from https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar and confirmed to work with "KalypsoLauncher.dll" from Redump entry 95617.
|
||||
// 3{.[9].-.[9].-.[9].}
|
||||
new(new byte?[]
|
||||
{
|
||||
0x33, 0x7B, 0x00, null, null, null, null, null,
|
||||
null, null, null, null, 0x00, 0x2D, 0x00, null,
|
||||
null, null, null, null, null, null, null, null,
|
||||
0x00, 0x2D, 0x00, null, null, null, null, null,
|
||||
null, null, null, null, 0x00, 0x2D, 0x00, null,
|
||||
null, null, null, null, null, null, null, null,
|
||||
0x00, 0x7D, 0x00
|
||||
}, ".NET Reactor (Unconfirmed - Please report to us on GitHub)"),
|
||||
|
||||
// Adapted from https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar and confirmed to work with "KalypsoLauncher.dll" from Redump entry 95617.
|
||||
// <Module>{[8]-[4]-[4]-[4]-[12]}
|
||||
new(new byte?[]
|
||||
{
|
||||
0x3C, 0x4D, 0x6F, 0x64, 0x75, 0x6C, 0x65, 0x3E,
|
||||
0x7B, null, null, null, null, null, null, null,
|
||||
null, 0x2D, null, null, null, null, 0x2D, null,
|
||||
null, null, null, 0x2D, null, null, null, null,
|
||||
0x2D, null, null, null, null, null, null, null,
|
||||
null, null, null, null, null, 0x7D
|
||||
}, ".NET Reactor (Unconfirmed - Please report to us on GitHub)")
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(file, textData, matchers, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
// TODO: Add extraction
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
@@ -9,7 +10,7 @@ namespace BinaryObjectScanner.Packer
|
||||
// TODO: Detect 3.15 and up (maybe looking for `Metamorphism`)
|
||||
// TODO: Add extraction
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class EXEStealth : IContentCheck, IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class EXEStealth : IContentCheck, IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckContents(string file, byte[] fileContent, bool includeDebug)
|
||||
@@ -37,7 +38,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -74,9 +75,9 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,10 +11,10 @@ namespace BinaryObjectScanner.Packer
|
||||
/// Though not technically a packer, this detection is for any executables that include
|
||||
/// others in their resources in some uncompressed manner to be used at runtime.
|
||||
/// </summary>
|
||||
public class EmbeddedExecutable : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class EmbeddedExecutable : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -22,31 +22,39 @@ namespace BinaryObjectScanner.Packer
|
||||
return null;
|
||||
|
||||
// Get the resources that have an executable signature
|
||||
if (pex.ResourceData?.Any(kvp => kvp.Value is byte[] ba && ba.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes)) == true)
|
||||
if (pex.ResourceData?.Any(kvp => kvp.Value is byte[] ba
|
||||
#if NET20
|
||||
&& Extensions.StartsWith(ba, SabreTools.Models.MSDOS.Constants.SignatureBytes)) == true)
|
||||
#else
|
||||
&& ba.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes)) == true)
|
||||
#endif
|
||||
{
|
||||
return "Embedded Executable";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
// If there are no resources
|
||||
if (pex.ResourceData == null)
|
||||
return null;
|
||||
return false;
|
||||
|
||||
// Get the resources that have an executable signature
|
||||
var resources = pex.ResourceData
|
||||
.Where(kvp => kvp.Value != null && kvp.Value is byte[])
|
||||
.Select(kvp => kvp.Value as byte[])
|
||||
#if NET20
|
||||
.Where(b => b != null && Extensions.StartsWith(b, SabreTools.Models.MSDOS.Constants.SignatureBytes))
|
||||
#else
|
||||
.Where(b => b != null && b.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes))
|
||||
#endif
|
||||
.ToList();
|
||||
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
for (int i = 0; i < resources.Count; i++)
|
||||
{
|
||||
try
|
||||
@@ -58,7 +66,10 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
// Create the temp filename
|
||||
string tempFile = $"embedded_resource_{i}.bin";
|
||||
tempFile = Path.Combine(tempPath, tempFile);
|
||||
tempFile = Path.Combine(outDir, tempFile);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
// Write the resource data to a temp file
|
||||
using var tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
|
||||
@@ -70,12 +81,12 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
@@ -6,10 +5,10 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class GenteeInstaller : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class GenteeInstaller : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -20,10 +19,10 @@ namespace BinaryObjectScanner.Packer
|
||||
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
{
|
||||
if (strs.Any(s => s.Contains("Gentee installer")))
|
||||
if (strs.Exists(s => s.Contains("Gentee installer")))
|
||||
return "Gentee Installer";
|
||||
|
||||
if (strs.Any(s => s.Contains("ginstall.dll")))
|
||||
if (strs.Exists(s => s.Contains("ginstall.dll")))
|
||||
return "Gentee Installer";
|
||||
}
|
||||
|
||||
@@ -31,9 +30,9 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
@@ -9,10 +9,10 @@ namespace BinaryObjectScanner.Packer
|
||||
// https://www.reddit.com/r/riseofincarnates/comments/m3vbnm/subreddit_revival_does_anyone_still_have_rise_of/
|
||||
// https://steamcommunity.com/app/310950/discussions/0/4224890554455490819/
|
||||
// https://github.com/horsicq/Detect-It-Easy/blob/63a1aa8bb23ca02d8a7fd5936db8dbc5c5d52dea/db/PE/HyperTech%20Crackproof.2.sg
|
||||
public class HyperTechCrackProof : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class HyperTechCrackProof : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -22,7 +22,8 @@ namespace BinaryObjectScanner.Packer
|
||||
// This check may be overly limiting, as it excludes the sample provided to DiE (https://github.com/horsicq/Detect-It-Easy/issues/102).
|
||||
// TODO: Find further samples and invesitgate if the "peC" section is only present on specific versions.
|
||||
bool peCSection = pex.ContainsSection("peC", exact: true);
|
||||
bool importTableMatch = (pex.Model.ImportTable?.ImportDirectoryTable?.Any(idte => idte?.Name == "KeRnEl32.dLl") ?? false);
|
||||
bool importTableMatch = Array.Exists(pex.Model.ImportTable?.ImportDirectoryTable ?? [],
|
||||
idte => idte?.Name == "KeRnEl32.dLl");
|
||||
|
||||
if (peCSection && importTableMatch)
|
||||
return "HyperTech CrackProof";
|
||||
@@ -31,9 +32,9 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction - https://github.com/dscharrer/InnoExtract
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class InnoSetup : IExtractablePortableExecutable, INewExecutableCheck, IPortableExecutableCheck
|
||||
public class InnoSetup : IExecutableCheck<NewExecutable>,
|
||||
IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
{
|
||||
// Check for "Inno" in the reserved words
|
||||
if (nex.Model.Stub?.Header?.Reserved2?[4] == 0x6E49 && nex.Model.Stub?.Header?.Reserved2?[5] == 0x6F6E)
|
||||
@@ -27,7 +28,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -38,7 +39,7 @@ namespace BinaryObjectScanner.Packer
|
||||
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
{
|
||||
var str = strs.FirstOrDefault(s => s.StartsWith("Inno Setup Setup Data"));
|
||||
var str = strs.Find(s => s.StartsWith("Inno Setup Setup Data"));
|
||||
if (str != null)
|
||||
{
|
||||
return str.Replace("Inno Setup Setup Data", "Inno Setup")
|
||||
@@ -53,9 +54,9 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string GetOldVersion(string file, NewExecutable nex)
|
||||
|
||||
@@ -6,10 +6,10 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction, which may be possible with the current libraries but needs to be investigated further.
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class InstallAnywhere : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class InstallAnywhere : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -28,9 +28,9 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private string GetVersion(PortableExecutable pex)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
@@ -6,11 +5,11 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction - https://github.com/Bioruebe/UniExtract2
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class InstallerVISE : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class InstallerVISE : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
//TODO: Add exact version detection for Windows builds, make sure versions before 3.X are detected as well, and detect the Mac builds.
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -21,7 +20,7 @@ namespace BinaryObjectScanner.Packer
|
||||
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
{
|
||||
if (strs.Any(s => s.Contains("ViseMain")))
|
||||
if (strs.Exists(s => s.Contains("ViseMain")))
|
||||
return "Installer VISE";
|
||||
}
|
||||
|
||||
@@ -29,9 +28,9 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@ using SabreTools.Serialization.Wrappers;
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction, seems to primarily use MSZip compression.
|
||||
public class IntelInstallationFramework : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class IntelInstallationFramework : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -33,9 +33,9 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
@@ -7,10 +6,10 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction, which should be possible with LibMSPackN, but it refuses to extract due to SFX files lacking the typical CAB identifiers.
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class MicrosoftCABSFX : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class MicrosoftCABSFX : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -29,7 +28,7 @@ namespace BinaryObjectScanner.Packer
|
||||
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
{
|
||||
if (strs.Any(s => s.Contains("wextract_cleanup")))
|
||||
if (strs.Exists(s => s.Contains("wextract_cleanup")))
|
||||
return $"Microsoft CAB SFX {GetVersion(pex)}";
|
||||
}
|
||||
|
||||
@@ -39,7 +38,7 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// 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.
|
||||
if (strs.Any(s => s.Contains("MSCFu")))
|
||||
if (strs.Exists(s => s.Contains("MSCFu")))
|
||||
return $"Microsoft CAB SFX {GetVersion(pex)}";
|
||||
}
|
||||
|
||||
@@ -47,9 +46,9 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private string GetVersion(PortableExecutable pex)
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
public class NSIS : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class NSIS : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -23,7 +22,7 @@ namespace BinaryObjectScanner.Packer
|
||||
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
{
|
||||
if (strs.Any(s => s.Contains("NullsoftInst")))
|
||||
if (strs.Exists(s => s.Contains("NullsoftInst")))
|
||||
return "NSIS";
|
||||
}
|
||||
|
||||
@@ -31,9 +30,9 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
@@ -14,11 +13,11 @@ namespace BinaryObjectScanner.Packer
|
||||
/// PEiD scanning definitions that include NeoLite: https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
/// Website listing various packers, including NeoLite: http://protools.narod.ru/packers.htm
|
||||
/// </summary>
|
||||
public class NeoLite : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class NeoLite : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
// TODO: Find samples of NeoLite 1.X.
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -37,9 +36,9 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Better version detection - https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
// TODO: Add extraction
|
||||
public class PECompact : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class PECompact : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -41,9 +41,9 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class PEtite : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class PEtite : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -24,9 +24,9 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@ namespace BinaryObjectScanner.Packer
|
||||
// TODO: Add extraction, which is possible but the only tools available that can
|
||||
// do this seem to be Universal Extractor 2 and InstallExplorer (https://totalcmd.net/plugring/InstallExplorer.html)
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class SetupFactory : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class SetupFactory : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -38,9 +38,9 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private string GetVersion(PortableExecutable pex)
|
||||
|
||||
@@ -4,11 +4,10 @@ using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
public class SevenZipSFX : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class SevenZipSFX : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -18,7 +17,7 @@ namespace BinaryObjectScanner.Packer
|
||||
// Get the assembly description, if possible
|
||||
if (pex.AssemblyDescription?.StartsWith("7-Zip Self-extracting Archive") == true)
|
||||
return $"7-Zip SFX {pex.AssemblyDescription.Substring("7-Zip Self-extracting Archive ".Length)}";
|
||||
|
||||
|
||||
// Get the file description, if it exists
|
||||
if (pex.FileDescription?.Equals("7z SFX") == true)
|
||||
return "7-Zip SFX";
|
||||
@@ -45,9 +44,10 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
var sevenZip = new FileType.SevenZip();
|
||||
return sevenZip.Extract(file, outDir, lookForHeader: true, includeDebug);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class Shrinker : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class Shrinker : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -25,9 +25,9 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
@@ -9,14 +8,14 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class UPX : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class UPX : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
private static readonly Regex _oldUpxVersionMatch = new Regex(@"\$Id: UPX (.*?) Copyright \(C\)", RegexOptions.Compiled);
|
||||
|
||||
private static readonly Regex _upxVersionMatch = new Regex(@"^([0-9]\.[0-9]{2})$", RegexOptions.Compiled);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -24,13 +23,13 @@ namespace BinaryObjectScanner.Packer
|
||||
return null;
|
||||
|
||||
// Check header padding strings
|
||||
if (pex.HeaderPaddingStrings?.Any() == true)
|
||||
if (pex.HeaderPaddingStrings != null && pex.HeaderPaddingStrings.Count > 0)
|
||||
{
|
||||
var match = pex.HeaderPaddingStrings.FirstOrDefault(s => s.Contains("UPX!"));
|
||||
var match = pex.HeaderPaddingStrings.Find(s => s.Contains("UPX!"));
|
||||
//if (match != null)
|
||||
// return "UPX";
|
||||
|
||||
match = pex.HeaderPaddingStrings.FirstOrDefault(s => s.StartsWith("$Id: UPX"));
|
||||
match = pex.HeaderPaddingStrings.Find(s => s.StartsWith("$Id: UPX"));
|
||||
if (match != null)
|
||||
{
|
||||
var regexMatch = _oldUpxVersionMatch.Match(match);
|
||||
@@ -40,8 +39,8 @@ namespace BinaryObjectScanner.Packer
|
||||
return "UPX (Unknown Version)";
|
||||
}
|
||||
|
||||
match = pex.HeaderPaddingStrings.FirstOrDefault(s => _upxVersionMatch.IsMatch(s));
|
||||
if (match != null && pex.HeaderPaddingStrings.Any(s => s == "UPX!"))
|
||||
match = pex.HeaderPaddingStrings.Find(s => _upxVersionMatch.IsMatch(s));
|
||||
if (match != null && pex.HeaderPaddingStrings.Exists(s => s == "UPX!"))
|
||||
{
|
||||
var regexMatch = _upxVersionMatch.Match(match);
|
||||
if (regexMatch.Success)
|
||||
@@ -49,7 +48,7 @@ namespace BinaryObjectScanner.Packer
|
||||
else
|
||||
return "UPX (Unknown Version)";
|
||||
}
|
||||
else if (match != null && pex.HeaderPaddingStrings.Any(s => s == "NOS "))
|
||||
else if (match != null && pex.HeaderPaddingStrings.Exists(s => s == "NOS "))
|
||||
{
|
||||
var regexMatch = _upxVersionMatch.Match(match);
|
||||
if (regexMatch.Success)
|
||||
@@ -63,9 +62,9 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static string GetVersion(string file, byte[] fileContent, List<int> positions)
|
||||
|
||||
@@ -1,20 +1,13 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Rar;
|
||||
using SharpCompress.Readers;
|
||||
#endif
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
public class WinRARSFX : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
public class WinRARSFX : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -33,52 +26,10 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
// Should be using stream instead of file, but stream fails to extract anything. My guess is that the executable portion of the archive is causing stream to fail, but not file.
|
||||
using (RarArchive zipFile = RarArchive.Open(file, new ReaderOptions() { LookForHeader = true }))
|
||||
{
|
||||
if (!zipFile.IsComplete)
|
||||
return null;
|
||||
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
foreach (var entry in zipFile.Entries)
|
||||
{
|
||||
try
|
||||
{
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
var rar = new FileType.RAR();
|
||||
return rar.Extract(file, outDir, lookForHeader: true, includeDebug);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,26 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Zip;
|
||||
#endif
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
public class WinZipSFX : IExtractableNewExecutable, IExtractablePortableExecutable, INewExecutableCheck, IPortableExecutableCheck
|
||||
public class WinZipSFX : IExtractableExecutable<NewExecutable>, IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
{
|
||||
// If the resident-name table doesnt exist
|
||||
if (nex.Model.ResidentNameTable == null)
|
||||
return null;
|
||||
|
||||
// Check for the WinZip name string
|
||||
// Check for the WinZip name strings
|
||||
bool winZipNameFound = nex.Model.ResidentNameTable
|
||||
.Select(rnte => rnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(rnte.NameString))
|
||||
.Any(s => s.Contains("WZ-SE-01"));
|
||||
winZipNameFound |= nex.Model.NonResidentNameTable?
|
||||
.Select(nrnte => nrnte?.NameString == null ? string.Empty : Encoding.ASCII.GetString(nrnte.NameString))
|
||||
.Any(s => s.Contains("WinZip(R) Self-Extractor")) ?? false;
|
||||
|
||||
// If we didn't find it
|
||||
if (!winZipNameFound)
|
||||
@@ -38,7 +35,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -63,67 +60,20 @@ namespace BinaryObjectScanner.Packer
|
||||
// TODO: Find a way to generically detect 2.X versions and improve exact version detection for SFX PE versions bundled with WinZip 11+
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, NewExecutable nex, bool includeDebug)
|
||||
=> Extract(file, includeDebug);
|
||||
public bool Extract(string file, NewExecutable nex, string outDir, bool includeDebug)
|
||||
=> Extract(file, outDir, includeDebug);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
=> Extract(file, includeDebug);
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
=> Extract(file, outDir, includeDebug);
|
||||
|
||||
/// <summary>
|
||||
/// Handle common extraction between executable types
|
||||
/// </summary>
|
||||
/// <inheritdoc/>
|
||||
public static string? Extract(string file, bool includeDebug)
|
||||
public static bool Extract(string file, string outDir, bool includeDebug)
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (ZipArchive zipFile = ZipArchive.Open(file))
|
||||
{
|
||||
foreach (var entry in zipFile.Entries)
|
||||
{
|
||||
try
|
||||
{
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
|
||||
// If we have a partial entry due to an incomplete multi-part archive, skip it
|
||||
if (!entry.IsComplete)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
var pkzip = new FileType.PKZIP();
|
||||
return pkzip.Extract(file, outDir, lookForHeader: true, includeDebug);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -794,14 +744,14 @@ namespace BinaryObjectScanner.Packer
|
||||
"WZIPSE32.exe" => "Unknown Version (32-bit)",// TODO: Find starting version
|
||||
"SI32LPG.SFX" => "Unknown Version (32-bit)",// TODO: Find starting version
|
||||
"ST32E.WZE" => "Unknown Version (32-bit)",// TODO: Find starting version
|
||||
|
||||
|
||||
// Personal Edition
|
||||
"VW95LE.SFX" => "Unknown Version before Personal Edition Build 1285 (32-bit)",
|
||||
"PE32E.SFX" => "Unknown Version after Personal Edition Build 1285 (32-bit)",
|
||||
"wzsepe32.exe" => "Unknown Version Personal Edition (32-bit)",// TODO: Find starting version
|
||||
"SI32PE.SFX" => "Unknown Version Personal Edition (32-bit)",// TODO: Find starting version
|
||||
"SI32LPE.SFX" => "Unknown Version Personal Edition (32-bit)",// TODO: Find starting version
|
||||
|
||||
|
||||
// Software Installation
|
||||
"VW95SRE.SFX" => "Unknown Version before Software Installation 2.1 (32-bit)",
|
||||
"SI32E.SFX" => "Unknown Version after Software Installation 2.1 (32-bit)",
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
using WiseUnpacker;
|
||||
using WiseUnpacker.EWISE;
|
||||
@@ -12,10 +12,10 @@ using WiseUnpacker.EWISE;
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class WiseInstaller : IExtractableNewExecutable, IExtractablePortableExecutable, INewExecutableCheck, IPortableExecutableCheck
|
||||
public class WiseInstaller : IExtractableExecutable<NewExecutable>, IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
{
|
||||
// If we match a known header
|
||||
if (MatchesNEVersion(nex) != null)
|
||||
@@ -41,7 +41,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -58,7 +58,7 @@ namespace BinaryObjectScanner.Packer
|
||||
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
{
|
||||
if (strs.Any(s => s.Contains("WiseMain")))
|
||||
if (strs.Exists(s => s.Contains("WiseMain")))
|
||||
return "Wise Installation Wizard Module";
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace BinaryObjectScanner.Packer
|
||||
strs = pex.GetFirstSectionStrings(".rdata");
|
||||
if (strs != null)
|
||||
{
|
||||
if (strs.Any(s => s.Contains("WiseMain")))
|
||||
if (strs.Exists(s => s.Contains("WiseMain")))
|
||||
return "Wise Installation Wizard Module";
|
||||
}
|
||||
|
||||
@@ -74,52 +74,36 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, NewExecutable nex, bool includeDebug)
|
||||
public bool Extract(string file, NewExecutable nex, string outDir, bool includeDebug)
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
Directory.CreateDirectory(outDir);
|
||||
|
||||
try
|
||||
{
|
||||
// TODO: Try to find where the file data lives and how to get it
|
||||
if (!Extractor.ExtractTo(file, tempPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
return Extractor.ExtractTo(file, outDir);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get the matching PE format
|
||||
var format = GetPEFormat(pex);
|
||||
if (format == null)
|
||||
return null;
|
||||
return false;
|
||||
|
||||
// Get the overlay data for easier reading
|
||||
int overlayOffset = 0, dataStart = 0;
|
||||
var overlayData = pex.OverlayData;
|
||||
if (overlayData == null)
|
||||
return null;
|
||||
return false;
|
||||
|
||||
// Skip over the additional DLL name, if we expect it
|
||||
if (format.Dll)
|
||||
@@ -172,45 +156,34 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
// If the first entry is PKZIP, we assume it's an embedded zipfile
|
||||
var magic = overlayData.ReadBytes(ref overlayOffset, 4); overlayOffset -= 4;
|
||||
#if NET20
|
||||
bool pkzip = Extensions.StartsWith(magic, new byte?[] { (byte)'P', (byte)'K' });
|
||||
#else
|
||||
bool pkzip = magic?.StartsWith(new byte?[] { (byte)'P', (byte)'K' }) ?? false;
|
||||
#endif
|
||||
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
// Create the output directory
|
||||
Directory.CreateDirectory(outDir);
|
||||
|
||||
// If we have PKZIP
|
||||
if (pkzip)
|
||||
{
|
||||
string tempFile = Path.Combine(tempPath, "WISEDATA.zip");
|
||||
using (Stream tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
|
||||
{
|
||||
tempStream.Write(overlayData, overlayOffset, overlayData.Length - overlayOffset);
|
||||
}
|
||||
string tempFile = Path.Combine(outDir, "WISEDATA.zip");
|
||||
using Stream tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
|
||||
tempStream.Write(overlayData, overlayOffset, overlayData.Length - overlayOffset);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we have DEFLATE -- TODO: Port implementation here or use DeflateStream
|
||||
else
|
||||
{
|
||||
if (!Extractor.ExtractTo(file, tempPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
return Extractor.ExtractTo(file, outDir);
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,16 @@ using System.Diagnostics;
|
||||
|
||||
namespace System
|
||||
{
|
||||
/// <summary>Defines a provider for progress updates.</summary>
|
||||
/// <typeparam name="T">The type of progress update value.</typeparam>
|
||||
/// <see href="https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/IProgress.cs"/>
|
||||
public interface IProgress<in T>
|
||||
{
|
||||
/// <summary>Reports a progress update.</summary>
|
||||
/// <param name="value">The value of the updated progress.</param>
|
||||
void Report(T value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides an IProgress{T} that invokes callbacks for each reported progress value.
|
||||
/// </summary>
|
||||
|
||||
@@ -3,12 +3,13 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// TODO: Figure out how to get version numbers
|
||||
public class ActiveMARK : IContentCheck, IPortableExecutableCheck
|
||||
public class ActiveMARK : IContentCheck, IExecutableCheck<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckContents(string file, byte[] fileContent, bool includeDebug)
|
||||
@@ -34,7 +35,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -44,45 +45,55 @@ namespace BinaryObjectScanner.Protection
|
||||
// Get the entry point data, if it exists
|
||||
if (pex.EntryPointData != null)
|
||||
{
|
||||
#if NET20
|
||||
// Found in "Zuma.exe"
|
||||
if (pex.EntryPointData.StartsWith(new byte?[] { 0x89, 0x25, 0x04, 0xF0, 0x86, 0x00, 0x68, 0x30 }))
|
||||
if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x89, 0x25, 0x04, 0xF0, 0x86, 0x00, 0x68, 0x30 }))
|
||||
return "ActiveMark v5.3.1078 (Packer Version)";
|
||||
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
else if (pex.EntryPointData.StartsWith(new byte?[] { 0x89, 0x25, null, null, null, null, 0xEB }))
|
||||
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x89, 0x25, null, null, null, null, 0xEB }))
|
||||
return "ActiveMark -> Trymedia Systems Inc. (Unconfirmed - Please report to us on Github)";
|
||||
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
else if (pex.EntryPointData.StartsWith(new byte?[] { 0x89, 0x25, null, null, null, null, 0x33, 0xED, 0x55, 0x8B, 0xEC, 0xE8, null, null, null, null, 0x8B, 0xD0, 0x81, 0xE2, 0xFF, 0x00, 0x00, 0x00, 0x89, 0x15, null, null, null, null, 0x8B, 0xD0, 0xC1, 0xEA, 0x08, 0x81, 0xE2, 0xFF, 0x00, 0x00, 0x00, 0xA3, null, null, null, null, 0xD1, 0xE0, 0x0F, 0x93, 0xC3, 0x33, 0xC0, 0x8A, 0xC3, 0xA3, null, null, null, null, 0x68, 0xFF, 0x00, 0x00, 0x00, 0xE8, null, null, null, null, 0x6A, 0x00, 0xE8, null, null, null, null, 0xA3, null, null, null, null, 0xBB, null, null, null, null, 0xC7, 0x03, 0x44, 0x00, 0x00, 0x00 }))
|
||||
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x89, 0x25, null, null, null, null, 0x33, 0xED, 0x55, 0x8B, 0xEC, 0xE8, null, null, null, null, 0x8B, 0xD0, 0x81, 0xE2, 0xFF, 0x00, 0x00, 0x00, 0x89, 0x15, null, null, null, null, 0x8B, 0xD0, 0xC1, 0xEA, 0x08, 0x81, 0xE2, 0xFF, 0x00, 0x00, 0x00, 0xA3, null, null, null, null, 0xD1, 0xE0, 0x0F, 0x93, 0xC3, 0x33, 0xC0, 0x8A, 0xC3, 0xA3, null, null, null, null, 0x68, 0xFF, 0x00, 0x00, 0x00, 0xE8, null, null, null, null, 0x6A, 0x00, 0xE8, null, null, null, null, 0xA3, null, null, null, null, 0xBB, null, null, null, null, 0xC7, 0x03, 0x44, 0x00, 0x00, 0x00 }))
|
||||
return "ActiveMark -> Trymedia Systems Inc. (Unconfirmed - Please report to us on Github)";
|
||||
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
else if (pex.EntryPointData.StartsWith(new byte?[] { 0x20, 0x2D, 0x2D, 0x4D, 0x50, 0x52, 0x4D, 0x4D, 0x47, 0x56, 0x41, 0x2D, 0x2D, 0x00, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6F, 0x78, 0x41, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67 }))
|
||||
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x20, 0x2D, 0x2D, 0x4D, 0x50, 0x52, 0x4D, 0x4D, 0x47, 0x56, 0x41, 0x2D, 0x2D, 0x00, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6F, 0x78, 0x41, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67 }))
|
||||
return "ActiveMARK 5.x -> Trymedia Systems Inc. (h) (Unconfirmed - Please report to us on Github)";
|
||||
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
else if (pex.EntryPointData.StartsWith(new byte?[] { 0x20, 0x2D, 0x2D, 0x4D, 0x50, 0x52, 0x4D, 0x4D, 0x47, 0x56, 0x41, 0x2D, 0x2D, 0x00, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6F, 0x78, 0x41, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x2E, 0x0D, 0x0A, 0x50, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x20, 0x75, 0x6E, 0x6C, 0x6F, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x65, 0x72, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x00, 0x57, 0x61, 0x72, 0x6E, 0x69, 0x6E, 0x67 }))
|
||||
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x20, 0x2D, 0x2D, 0x4D, 0x50, 0x52, 0x4D, 0x4D, 0x47, 0x56, 0x41, 0x2D, 0x2D, 0x00, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6F, 0x78, 0x41, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x2E, 0x0D, 0x0A, 0x50, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x20, 0x75, 0x6E, 0x6C, 0x6F, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x65, 0x72, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x00, 0x57, 0x61, 0x72, 0x6E, 0x69, 0x6E, 0x67 }))
|
||||
return "ActiveMARK 5.x -> Trymedia Systems,Inc. (Unconfirmed - Please report to us on Github)";
|
||||
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
else if (pex.EntryPointData.StartsWith(new byte?[] { 0x79, 0x11, 0x7F, 0xAB, 0x9A, 0x4A, 0x83, 0xB5, 0xC9, 0x6B, 0x1A, 0x48, 0xF9, 0x27, 0xB4, 0x25 }))
|
||||
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x79, 0x11, 0x7F, 0xAB, 0x9A, 0x4A, 0x83, 0xB5, 0xC9, 0x6B, 0x1A, 0x48, 0xF9, 0x27, 0xB4, 0x25 }))
|
||||
return "ActiveMARK[TM] (Unconfirmed - Please report to us on Github)";
|
||||
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
else if (pex.EntryPointData.StartsWith(new byte?[] { 0x79, 0x07, 0x0F, 0xB7, 0x07, 0x47, 0x50, 0x47, 0xB9, 0x57, 0x48, 0xF2, 0xAE, 0x55, 0xFF, 0x96, 0x84, null, 0x00, 0x00, 0x09, 0xC0, 0x74, 0x07, 0x89, 0x03, 0x83, 0xC3, 0x04, 0xEB, 0xD8, 0xFF, 0x96, 0x88, null, 0x00, 0x00, 0x61, 0xE9, null, null, null, 0xFF }))
|
||||
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x79, 0x07, 0x0F, 0xB7, 0x07, 0x47, 0x50, 0x47, 0xB9, 0x57, 0x48, 0xF2, 0xAE, 0x55, 0xFF, 0x96, 0x84, null, 0x00, 0x00, 0x09, 0xC0, 0x74, 0x07, 0x89, 0x03, 0x83, 0xC3, 0x04, 0xEB, 0xD8, 0xFF, 0x96, 0x88, null, 0x00, 0x00, 0x61, 0xE9, null, null, null, 0xFF }))
|
||||
return "ActiveMARK[TM] R5.31.1140 -> Trymedia (Unconfirmed - Please report to us on Github)";
|
||||
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0xBE, 0x48, 0x01, 0x40, 0x00, 0xAD, 0x8B, 0xF8, 0x95, 0xA5, 0x33, 0xC0, 0x33, 0xC9, 0xAB, 0x48, 0xAB, 0xF7, 0xD8, 0xB1, 0x04, 0xF3, 0xAB, 0xC1, 0xE0, 0x0A, 0xB5, 0x1C, 0xF3, 0xAB, 0xAD, 0x50, 0x97, 0x51, 0xAD, 0x87, 0xF5, 0x58, 0x8D, 0x54, 0x86, 0x5C, 0xFF, 0xD5, 0x72, 0x5A, 0x2C, 0x03, 0x73, 0x02, 0xB0, 0x00, 0x3C, 0x07, 0x72, 0x02, 0x2C, 0x03, 0x50, 0x0F, 0xB6, 0x5F, 0xFF, 0xC1, 0xE3, 0x03, 0xB3, 0x00, 0x8D, 0x1C, 0x5B, 0x8D, 0x9C, 0x9E, 0x0C, 0x10, 0x00, 0x00, 0xB0, 0x01, 0x67, 0xE3, 0x29, 0x8B, 0xD7, 0x2B, 0x56, 0x0C, 0x8A, 0x2A, 0x33, 0xD2, 0x84, 0xE9, 0x0F, 0x95, 0xC6, 0x52, 0xFE, 0xC6, 0x8A, 0xD0, 0x8D, 0x14, 0x93, 0xFF, 0xD5, 0x5A, 0x9F, 0x12, 0xC0, 0xD0, 0xE9, 0x74, 0x0E, 0x9E, 0x1A, 0xF2, 0x74, 0xE4, 0xB4, 0x00, 0x33, 0xC9, 0xB5, 0x01, 0xFF, 0x55, 0xCC, 0x33, 0xC9, 0xE9, 0xDF, 0x00, 0x00, 0x00, 0x8B, 0x5E, 0x0C, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x73, 0x50, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x72, 0x1B, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x72, 0x2B, 0x3C, 0x07, 0xB0, 0x09, 0x72, 0x02, 0xB0, 0x0B, 0x50, 0x8B, 0xC7, 0x2B, 0x46, 0x0C, 0xB1, 0x80, 0x8A, 0x00, 0xEB, 0xCF, 0x83, 0xC2, 0x60, 0xFF, 0xD5, 0x87, 0x5E, 0x10, 0x73, 0x0D, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x87, 0x5E, 0x14, 0x73, 0x03, 0x87, 0x5E, 0x18, 0x3C, 0x07, 0xB0, 0x08, 0x72, 0x02, 0xB0, 0x0B, 0x50, 0x53, 0x8D, 0x96, 0x7C, 0x07, 0x00, 0x00, 0xFF, 0x55, 0xD0, 0x5B, 0x91, 0xEB, 0x77, 0x3C, 0x07, 0xB0, 0x07, 0x72, 0x02, 0xB0, 0x0A, 0x50, 0x87, 0x5E, 0x10, 0x87, 0x5E, 0x14, 0x89, 0x5E, 0x18, 0x8D, 0x96, 0xC4, 0x0B, 0x00, 0x00, 0xFF, 0x55, 0xD0, 0x50, 0x48 }))
|
||||
return "ActiveMARK 5.x -> Trymedia Systems,Inc. (h) (Unconfirmed - Please report to us on Github)";
|
||||
#else
|
||||
// Found in "Zuma.exe"
|
||||
if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x89, 0x25, 0x04, 0xF0, 0x86, 0x00, 0x68, 0x30 }))
|
||||
return "ActiveMark v5.3.1078 (Packer Version)";
|
||||
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
else if (pex.EntryPointData.StartsWith(new byte?[] { 0xBE, 0x48, 0x01, 0x40, 0x00, 0xAD, 0x8B, 0xF8, 0x95, 0xA5, 0x33, 0xC0, 0x33, 0xC9, 0xAB, 0x48, 0xAB, 0xF7, 0xD8, 0xB1, 0x04, 0xF3, 0xAB, 0xC1, 0xE0, 0x0A, 0xB5, 0x1C, 0xF3, 0xAB, 0xAD, 0x50, 0x97, 0x51, 0xAD, 0x87, 0xF5, 0x58, 0x8D, 0x54, 0x86, 0x5C, 0xFF, 0xD5, 0x72, 0x5A, 0x2C, 0x03, 0x73, 0x02, 0xB0, 0x00, 0x3C, 0x07, 0x72, 0x02, 0x2C, 0x03, 0x50, 0x0F, 0xB6, 0x5F, 0xFF, 0xC1, 0xE3, 0x03, 0xB3, 0x00, 0x8D, 0x1C, 0x5B, 0x8D, 0x9C, 0x9E, 0x0C, 0x10, 0x00, 0x00, 0xB0, 0x01, 0x67, 0xE3, 0x29, 0x8B, 0xD7, 0x2B, 0x56, 0x0C, 0x8A, 0x2A, 0x33, 0xD2, 0x84, 0xE9, 0x0F, 0x95, 0xC6, 0x52, 0xFE, 0xC6, 0x8A, 0xD0, 0x8D, 0x14, 0x93, 0xFF, 0xD5, 0x5A, 0x9F, 0x12, 0xC0, 0xD0, 0xE9, 0x74, 0x0E, 0x9E, 0x1A, 0xF2, 0x74, 0xE4, 0xB4, 0x00, 0x33, 0xC9, 0xB5, 0x01, 0xFF, 0x55, 0xCC, 0x33, 0xC9, 0xE9, 0xDF, 0x00, 0x00, 0x00, 0x8B, 0x5E, 0x0C, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x73, 0x50, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x72, 0x1B, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x72, 0x2B, 0x3C, 0x07, 0xB0, 0x09, 0x72, 0x02, 0xB0, 0x0B, 0x50, 0x8B, 0xC7, 0x2B, 0x46, 0x0C, 0xB1, 0x80, 0x8A, 0x00, 0xEB, 0xCF, 0x83, 0xC2, 0x60, 0xFF, 0xD5, 0x87, 0x5E, 0x10, 0x73, 0x0D, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x87, 0x5E, 0x14, 0x73, 0x03, 0x87, 0x5E, 0x18, 0x3C, 0x07, 0xB0, 0x08, 0x72, 0x02, 0xB0, 0x0B, 0x50, 0x53, 0x8D, 0x96, 0x7C, 0x07, 0x00, 0x00, 0xFF, 0x55, 0xD0, 0x5B, 0x91, 0xEB, 0x77, 0x3C, 0x07, 0xB0, 0x07, 0x72, 0x02, 0xB0, 0x0A, 0x50, 0x87, 0x5E, 0x10, 0x87, 0x5E, 0x14, 0x89, 0x5E, 0x18, 0x8D, 0x96, 0xC4, 0x0B, 0x00, 0x00, 0xFF, 0x55, 0xD0, 0x50, 0x48 }))
|
||||
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x89, 0x25, null, null, null, null, 0xEB }))
|
||||
return "ActiveMark -> Trymedia Systems Inc. (Unconfirmed - Please report to us on Github)";
|
||||
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x89, 0x25, null, null, null, null, 0x33, 0xED, 0x55, 0x8B, 0xEC, 0xE8, null, null, null, null, 0x8B, 0xD0, 0x81, 0xE2, 0xFF, 0x00, 0x00, 0x00, 0x89, 0x15, null, null, null, null, 0x8B, 0xD0, 0xC1, 0xEA, 0x08, 0x81, 0xE2, 0xFF, 0x00, 0x00, 0x00, 0xA3, null, null, null, null, 0xD1, 0xE0, 0x0F, 0x93, 0xC3, 0x33, 0xC0, 0x8A, 0xC3, 0xA3, null, null, null, null, 0x68, 0xFF, 0x00, 0x00, 0x00, 0xE8, null, null, null, null, 0x6A, 0x00, 0xE8, null, null, null, null, 0xA3, null, null, null, null, 0xBB, null, null, null, null, 0xC7, 0x03, 0x44, 0x00, 0x00, 0x00 }))
|
||||
return "ActiveMark -> Trymedia Systems Inc. (Unconfirmed - Please report to us on Github)";
|
||||
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x20, 0x2D, 0x2D, 0x4D, 0x50, 0x52, 0x4D, 0x4D, 0x47, 0x56, 0x41, 0x2D, 0x2D, 0x00, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6F, 0x78, 0x41, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67 }))
|
||||
return "ActiveMARK 5.x -> Trymedia Systems Inc. (h) (Unconfirmed - Please report to us on Github)";
|
||||
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x20, 0x2D, 0x2D, 0x4D, 0x50, 0x52, 0x4D, 0x4D, 0x47, 0x56, 0x41, 0x2D, 0x2D, 0x00, 0x75, 0x73, 0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x4D, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x6F, 0x78, 0x41, 0x00, 0x54, 0x68, 0x69, 0x73, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x6E, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x65, 0x72, 0x20, 0x69, 0x6E, 0x20, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x2E, 0x0D, 0x0A, 0x50, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x20, 0x75, 0x6E, 0x6C, 0x6F, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x65, 0x72, 0x20, 0x61, 0x6E, 0x64, 0x20, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x00, 0x57, 0x61, 0x72, 0x6E, 0x69, 0x6E, 0x67 }))
|
||||
return "ActiveMARK 5.x -> Trymedia Systems,Inc. (Unconfirmed - Please report to us on Github)";
|
||||
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x79, 0x11, 0x7F, 0xAB, 0x9A, 0x4A, 0x83, 0xB5, 0xC9, 0x6B, 0x1A, 0x48, 0xF9, 0x27, 0xB4, 0x25 }))
|
||||
return "ActiveMARK[TM] (Unconfirmed - Please report to us on Github)";
|
||||
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0x79, 0x07, 0x0F, 0xB7, 0x07, 0x47, 0x50, 0x47, 0xB9, 0x57, 0x48, 0xF2, 0xAE, 0x55, 0xFF, 0x96, 0x84, null, 0x00, 0x00, 0x09, 0xC0, 0x74, 0x07, 0x89, 0x03, 0x83, 0xC3, 0x04, 0xEB, 0xD8, 0xFF, 0x96, 0x88, null, 0x00, 0x00, 0x61, 0xE9, null, null, null, 0xFF }))
|
||||
return "ActiveMARK[TM] R5.31.1140 -> Trymedia (Unconfirmed - Please report to us on Github)";
|
||||
else if (Extensions.StartsWith(pex.EntryPointData, new byte?[] { 0xBE, 0x48, 0x01, 0x40, 0x00, 0xAD, 0x8B, 0xF8, 0x95, 0xA5, 0x33, 0xC0, 0x33, 0xC9, 0xAB, 0x48, 0xAB, 0xF7, 0xD8, 0xB1, 0x04, 0xF3, 0xAB, 0xC1, 0xE0, 0x0A, 0xB5, 0x1C, 0xF3, 0xAB, 0xAD, 0x50, 0x97, 0x51, 0xAD, 0x87, 0xF5, 0x58, 0x8D, 0x54, 0x86, 0x5C, 0xFF, 0xD5, 0x72, 0x5A, 0x2C, 0x03, 0x73, 0x02, 0xB0, 0x00, 0x3C, 0x07, 0x72, 0x02, 0x2C, 0x03, 0x50, 0x0F, 0xB6, 0x5F, 0xFF, 0xC1, 0xE3, 0x03, 0xB3, 0x00, 0x8D, 0x1C, 0x5B, 0x8D, 0x9C, 0x9E, 0x0C, 0x10, 0x00, 0x00, 0xB0, 0x01, 0x67, 0xE3, 0x29, 0x8B, 0xD7, 0x2B, 0x56, 0x0C, 0x8A, 0x2A, 0x33, 0xD2, 0x84, 0xE9, 0x0F, 0x95, 0xC6, 0x52, 0xFE, 0xC6, 0x8A, 0xD0, 0x8D, 0x14, 0x93, 0xFF, 0xD5, 0x5A, 0x9F, 0x12, 0xC0, 0xD0, 0xE9, 0x74, 0x0E, 0x9E, 0x1A, 0xF2, 0x74, 0xE4, 0xB4, 0x00, 0x33, 0xC9, 0xB5, 0x01, 0xFF, 0x55, 0xCC, 0x33, 0xC9, 0xE9, 0xDF, 0x00, 0x00, 0x00, 0x8B, 0x5E, 0x0C, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x73, 0x50, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x72, 0x1B, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x72, 0x2B, 0x3C, 0x07, 0xB0, 0x09, 0x72, 0x02, 0xB0, 0x0B, 0x50, 0x8B, 0xC7, 0x2B, 0x46, 0x0C, 0xB1, 0x80, 0x8A, 0x00, 0xEB, 0xCF, 0x83, 0xC2, 0x60, 0xFF, 0xD5, 0x87, 0x5E, 0x10, 0x73, 0x0D, 0x83, 0xC2, 0x30, 0xFF, 0xD5, 0x87, 0x5E, 0x14, 0x73, 0x03, 0x87, 0x5E, 0x18, 0x3C, 0x07, 0xB0, 0x08, 0x72, 0x02, 0xB0, 0x0B, 0x50, 0x53, 0x8D, 0x96, 0x7C, 0x07, 0x00, 0x00, 0xFF, 0x55, 0xD0, 0x5B, 0x91, 0xEB, 0x77, 0x3C, 0x07, 0xB0, 0x07, 0x72, 0x02, 0xB0, 0x0A, 0x50, 0x87, 0x5E, 0x10, 0x87, 0x5E, 0x14, 0x89, 0x5E, 0x18, 0x8D, 0x96, 0xC4, 0x0B, 0x00, 0x00, 0xFF, 0x55, 0xD0, 0x50, 0x48 }))
|
||||
return "ActiveMARK 5.x -> Trymedia Systems,Inc. (h) (Unconfirmed - Please report to us on Github)";
|
||||
#endif
|
||||
}
|
||||
|
||||
// Get the .data section strings, if they exist
|
||||
var strs = pex.GetLastSectionStrings(".data");
|
||||
if (strs != null)
|
||||
{
|
||||
if (strs.Any(s => s.Contains("MPRMMGVA"))
|
||||
&& strs.Any(s => s.Contains("This application cannot run with an active debugger in memory.")))
|
||||
if (strs.Exists(s => s.Contains("MPRMMGVA"))
|
||||
&& strs.Exists(s => s.Contains("This application cannot run with an active debugger in memory.")))
|
||||
{
|
||||
return "ActiveMARK 6.x";
|
||||
}
|
||||
@@ -102,7 +113,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// Get the overlay data, if it exists
|
||||
if (pex.OverlayStrings != null)
|
||||
{
|
||||
if (pex.OverlayStrings.Any(s => s.Contains("TMSAMVOH")))
|
||||
if (pex.OverlayStrings.Exists(s => s.Contains("TMSAMVOH")))
|
||||
return "ActiveMARK";
|
||||
}
|
||||
|
||||
@@ -110,7 +121,7 @@ namespace BinaryObjectScanner.Protection
|
||||
strs = pex.GetLastSectionStrings(".bss");
|
||||
if (strs != null)
|
||||
{
|
||||
if (strs.Any(s => s.Contains("TMSAMVOF")))
|
||||
if (strs.Exists(s => s.Contains("TMSAMVOF")))
|
||||
return "ActiveMARK";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Collections.Concurrent;
|
||||
#endif
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
using SabreTools.Matching.Paths;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
@@ -19,10 +18,10 @@ namespace BinaryObjectScanner.Protection
|
||||
/// https://pitchbook.com/profiles/company/118805-59
|
||||
/// https://web.archive.org/web/19990417191351/http://www.aegisoft.com:80/
|
||||
/// </summary>
|
||||
public class AegiSoft : IPathCheck, IPortableExecutableCheck
|
||||
public class AegiSoft : IExecutableCheck<PortableExecutable>, IPathCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -69,11 +68,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET20 || NET35
|
||||
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#else
|
||||
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#endif
|
||||
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Collections.Concurrent;
|
||||
#endif
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Paths;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
@@ -18,11 +16,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public class AlphaDVD : IPathCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET20 || NET35
|
||||
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#else
|
||||
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#endif
|
||||
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
@@ -41,10 +39,10 @@ namespace BinaryObjectScanner.Protection
|
||||
// - SETTEC0000SETTEC1111
|
||||
// - SOFTWARE\SETTEC
|
||||
// TODO: Are there version numbers?
|
||||
public class AlphaROM : IPortableExecutableCheck
|
||||
public class AlphaROM : IExecutableCheck<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// TODO: Add support for detecting Alpha-ROM found in older games made with the RealLive engine.
|
||||
// TODO: Add version detection for Alpha-ROM.
|
||||
@@ -58,10 +56,10 @@ namespace BinaryObjectScanner.Protection
|
||||
var strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
|
||||
if (strs != null)
|
||||
{
|
||||
if (strs.Any(s => s.Contains("\\SETTEC")))
|
||||
if (strs.Exists(s => s.Contains("\\SETTEC")))
|
||||
return "Alpha-ROM";
|
||||
|
||||
if (strs.Any(s => s.Contains("SETTEC0000")))
|
||||
if (strs.Exists(s => s.Contains("SETTEC0000")))
|
||||
return "Alpha-ROM";
|
||||
}
|
||||
|
||||
@@ -69,7 +67,13 @@ namespace BinaryObjectScanner.Protection
|
||||
strs = pex.GetFirstSectionStrings(".rdata");
|
||||
if (strs != null)
|
||||
{
|
||||
if (strs.Any(s => s.Contains("This Game is Japan Only")))
|
||||
if (strs.Exists(s => s.Contains("This Game is Japan Only")))
|
||||
return "Alpha-ROM";
|
||||
// Found in "Filechk.exe" in Redump entry 115358.
|
||||
if (strs.Exists(s => s.Contains("AlphaCheck.exe")))
|
||||
return "Alpha-ROM";
|
||||
// Found in "Uninstall.exe" in Redump entry 115358.
|
||||
if (strs.Exists(s => s.Contains("AlphaCheck.dat")))
|
||||
return "Alpha-ROM";
|
||||
}
|
||||
|
||||
@@ -77,7 +81,7 @@ namespace BinaryObjectScanner.Protection
|
||||
if (pex.OverlayStrings != null)
|
||||
{
|
||||
// Found in Redump entry 84122.
|
||||
if (pex.OverlayStrings.Any(s => s.Contains("SETTEC0000")))
|
||||
if (pex.OverlayStrings.Exists(s => s.Contains("SETTEC0000")))
|
||||
return "Alpha-ROM";
|
||||
}
|
||||
|
||||
|
||||
60
BinaryObjectScanner/Protection/Armadillo.cs
Normal file
60
BinaryObjectScanner/Protection/Armadillo.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
/// <summary>
|
||||
/// Armadillo was a license manager, packer, and DRM by "The Silicon Realm Toolworks": https://web.archive.org/web/20030203101931/http://www.siliconrealms.com/armadillo.shtml
|
||||
/// They were later bought by Digital River, and updated their website: https://web.archive.org/web/20031203021152/http://www.siliconrealms.com/armadillo.shtml
|
||||
/// A new updated version named "SoftwarePassport" was released: https://web.archive.org/web/20040423044529/http://siliconrealms.com/softwarepassport/popup.shtml
|
||||
/// Later copy of the website, with SoftwarePassport being named instead of Armadillo: https://web.archive.org/web/20040804032608/http://www.siliconrealms.com/armadillo.shtml
|
||||
/// It appears as though both Armadillo and SoftwarePassport were being released at the same time, possibly with Armadillo acting as the core component and SoftwarePassport being supplementary: https://web.archive.org/web/20050619013312/http://siliconrealms.com/srt-news.shtml
|
||||
/// Digital River itself also advertised Armadillo at first: https://web.archive.org/web/20040116043029/http://www.digitalriver.com:80/corporate/solutions06.shtml
|
||||
/// But then only advertised SoftwarePassport once it was released: https://web.archive.org/web/20040604065907/http://www.digitalriver.com/corporate/solutions06.shtml
|
||||
/// </summary>
|
||||
|
||||
// TODO: Add extraction
|
||||
// TODO: Add version checking, if possible
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
|
||||
public class Armadillo : IExtractableExecutable<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
// Get the .nicode section, if it exists
|
||||
bool nicodeSection = pex.ContainsSection(".nicode", exact: true);
|
||||
if (nicodeSection)
|
||||
return "Armadillo";
|
||||
|
||||
// Loop through all "extension" sections -- usually .data1 or .text1
|
||||
if (pex.SectionNames != null)
|
||||
{
|
||||
foreach (var sectionName in Array.FindAll(pex.SectionNames, s => s != null && s.EndsWith("1")))
|
||||
{
|
||||
// Get the section strings, if they exist
|
||||
var strs = pex.GetFirstSectionStrings(sectionName);
|
||||
if (strs != null)
|
||||
{
|
||||
if (strs.Exists(s => s.Contains("ARMDEBUG")))
|
||||
return "Armadillo";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool Extract(string file, PortableExecutable pex, string outDir, bool includeDebug)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Collections.Concurrent;
|
||||
#endif
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Paths;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
@@ -15,11 +13,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public class Bitpool : IPathCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET20 || NET35
|
||||
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#else
|
||||
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#endif
|
||||
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
@@ -31,13 +25,13 @@ namespace BinaryObjectScanner.Protection
|
||||
|
||||
// A set of 4 identically sized (within the same game, not between games), corrupted/padded files present in several games (Redump entries 31782 and 35476).
|
||||
// Both examples with only having the first letter uppercase and as the whole file name being uppercase have been seen.
|
||||
new(new List<PathMatch>
|
||||
{
|
||||
new(
|
||||
[
|
||||
new FilePathMatch("Crc_a"),
|
||||
new FilePathMatch("Crc_b"),
|
||||
new FilePathMatch("Crc_c"),
|
||||
new FilePathMatch("Crc_d"),
|
||||
}, "Bitpool"),
|
||||
], "Bitpool"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: true);
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Collections.Concurrent;
|
||||
#endif
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Paths;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
@@ -40,10 +38,10 @@ namespace BinaryObjectScanner.Protection
|
||||
/// https://www.ftc.gov/sites/default/files/documents/public_comments/ftc-town-hall-address-digital-rights-management-technologies-event-takes-place-wednesday-march-25/539814-00707.pdf
|
||||
/// https://www.gamesindustry.biz/byteshield-drm-system-now-protecting-over-200-games
|
||||
/// </summary>
|
||||
public class ByteShield : IPortableExecutableCheck, IPathCheck
|
||||
public class ByteShield : IExecutableCheck<PortableExecutable>, IPathCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -97,7 +95,7 @@ namespace BinaryObjectScanner.Protection
|
||||
if (strs != null)
|
||||
{
|
||||
// Found in "LineRider2.exe" in Redump entry 6236
|
||||
if (strs.Any(s => s?.Contains("ByteShield") == true))
|
||||
if (strs.Exists(s => s?.Contains("ByteShield") == true))
|
||||
return "ByteShield";
|
||||
}
|
||||
|
||||
@@ -106,15 +104,15 @@ namespace BinaryObjectScanner.Protection
|
||||
if (strs != null)
|
||||
{
|
||||
// Found in "ByteShield.dll" in Redump entry 6236
|
||||
if (strs.Any(s => s?.Contains("Byte|Shield") == true))
|
||||
if (strs.Exists(s => s?.Contains("Byte|Shield") == true))
|
||||
return "ByteShield Component Module";
|
||||
|
||||
// Found in "ByteShield.dll" in Redump entry 6236
|
||||
else if (strs.Any(s => s?.Contains("Byteshield0") == true))
|
||||
else if (strs.Exists(s => s?.Contains("Byteshield0") == true))
|
||||
return "ByteShield Component Module";
|
||||
|
||||
// Found in "ByteShield.dll" in Redump entry 6236
|
||||
else if (strs.Any(s => s?.Contains("ByteShieldLoader") == true))
|
||||
else if (strs.Exists(s => s?.Contains("ByteShieldLoader") == true))
|
||||
return "ByteShield Component Module";
|
||||
}
|
||||
|
||||
@@ -124,7 +122,7 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// TODO: Figure out if this specifically indicates if the file is encrypted
|
||||
// Found in "LineRider2.bbz" in Redump entry 6236
|
||||
if (strs.Any(s => s?.Contains("ByteShield") == true))
|
||||
if (strs.Exists(s => s?.Contains("ByteShield") == true))
|
||||
return "ByteShield";
|
||||
}
|
||||
|
||||
@@ -132,11 +130,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET20 || NET35
|
||||
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#else
|
||||
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#endif
|
||||
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
{
|
||||
// TODO: Investigate reference to "bbz650.tmp" in "Byteshield.dll" (Redump entry 6236)
|
||||
// Files with the ".bbz" extension are associated with ByteShield, but the extenstion is known to be used in other places as well.
|
||||
|
||||
@@ -3,10 +3,10 @@ using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
public class CDCheck : IPortableExecutableCheck
|
||||
public class CDCheck : IExecutableCheck<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
using System;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Collections.Concurrent;
|
||||
#endif
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Models.PortableExecutable;
|
||||
using SabreTools.Matching.Content;
|
||||
using SabreTools.Matching.Paths;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
@@ -65,7 +63,7 @@ namespace BinaryObjectScanner.Protection
|
||||
/// List of applications that have CD/DVD/WEB-Cops relating to a Windows update: https://www.betaarchive.com/wiki/index.php/Microsoft_KB_Archive/924867
|
||||
/// </summary>
|
||||
|
||||
public class CDDVDCops : IContentCheck, INewExecutableCheck, IPathCheck, IPortableExecutableCheck
|
||||
public class CDDVDCops : IContentCheck, IExecutableCheck<NewExecutable>, IExecutableCheck<PortableExecutable>, IPathCheck
|
||||
{
|
||||
// TODO: Investigate reference to "CD32COPS.DLL" in "WETFLIPP.QZ_" in IA item "Triada_Russian_DVD_Complete_Collection_of_Erotic_Games".
|
||||
/// <inheritdoc/>
|
||||
@@ -99,7 +97,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
{
|
||||
// TODO: Don't read entire file
|
||||
var data = nex.ReadArbitraryRange();
|
||||
@@ -143,7 +141,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -184,11 +182,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET20 || NET35
|
||||
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#else
|
||||
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#endif
|
||||
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
{
|
||||
// TODO: Original had "CDCOPS.DLL" required and all the rest in a combined OR
|
||||
var matchers = new List<PathMatchSet>
|
||||
@@ -197,7 +191,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// Presumably used to increase the amount of data written to the disc to allow DPM checking to be used for the protection. It's unknown if this file is used on any other protected discs.
|
||||
|
||||
// Found in Redump entry 84517.
|
||||
new(new PathMatch("CDCOPS.DLL", useEndsWith: true), "CD-Cops"),
|
||||
new(new FilePathMatch("CDCOPS.DLL"), "CD-Cops"),
|
||||
new(new PathMatch(".W_X", matchExact: true, useEndsWith: true), "CD/DVD-Cops"),
|
||||
new(new PathMatch(".QZ_", matchExact: true, useEndsWith: true), "CD/DVD-Cops"),
|
||||
|
||||
@@ -217,7 +211,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// Presumably used to increase the amount of data written to the disc to allow DPM checking to be used for the protection. It's unknown if this file is used on any other protected discs.
|
||||
|
||||
// Found in Redump entry 84517.
|
||||
new(new PathMatch("CDCOPS.DLL", useEndsWith: true), "CD-Cops"),
|
||||
new(new FilePathMatch("CDCOPS.DLL"), "CD-Cops"),
|
||||
new(new PathMatch(".W_X", matchExact: true, useEndsWith: true), "CD/DVD-Cops"),
|
||||
new(new PathMatch(".QZ_", matchExact: true, useEndsWith: true), "CD/DVD-Cops"),
|
||||
|
||||
@@ -234,13 +228,10 @@ namespace BinaryObjectScanner.Protection
|
||||
if (fileContent == null)
|
||||
return null;
|
||||
|
||||
#if NET20 || NET35 || NET40
|
||||
byte[] versionBytes = new byte[4];
|
||||
Array.Copy(fileContent, positions[0] + 15, versionBytes, 0, 4);
|
||||
char[] version = versionBytes.Select(b => (char)b).ToArray();
|
||||
#else
|
||||
char[] version = new ArraySegment<byte>(fileContent, positions[0] + 15, 4).Select(b => (char)b).ToArray();
|
||||
#endif
|
||||
char[] version = Array.ConvertAll(versionBytes, b => (char)b);
|
||||
|
||||
if (version[0] == 0x00)
|
||||
return string.Empty;
|
||||
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
using System;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Collections.Concurrent;
|
||||
#endif
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Paths;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
@@ -23,10 +20,10 @@ namespace BinaryObjectScanner.Protection
|
||||
/// https://gamecopyworld.com/games/pc_omikron.shtml
|
||||
/// https://forum.ixbt.com/topic.cgi?id=31:3985
|
||||
/// </summary>
|
||||
public class CDGuard : IPathCheck, IPortableExecutableCheck
|
||||
public class CDGuard : IExecutableCheck<PortableExecutable>, IPathCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -48,7 +45,7 @@ namespace BinaryObjectScanner.Protection
|
||||
if (pex.Model.ImportTable?.ImportDirectoryTable != null)
|
||||
{
|
||||
// Found in "Randevu.exe" in Redump entry 97142.
|
||||
bool match = pex.Model.ImportTable.ImportDirectoryTable.Any(idte => idte?.Name != null && idte.Name.Equals("cdguard.dll", StringComparison.OrdinalIgnoreCase));
|
||||
bool match = Array.Exists(pex.Model.ImportTable.ImportDirectoryTable, idte => idte?.Name != null && idte.Name.Equals("cdguard.dll", StringComparison.OrdinalIgnoreCase));
|
||||
if (match)
|
||||
return "CD-Guard Copy Protection System";
|
||||
}
|
||||
@@ -57,11 +54,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET20 || NET35
|
||||
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#else
|
||||
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#endif
|
||||
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
|
||||
@@ -4,10 +4,10 @@ using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
public class CDKey : IPortableExecutableCheck
|
||||
public class CDKey : IExecutableCheck<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Collections.Concurrent;
|
||||
#endif
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
using SabreTools.Matching.Paths;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
@@ -26,10 +25,10 @@ namespace BinaryObjectScanner.Protection
|
||||
/// Possible false positives include Redump entries 51241, 51373, 54397, 76437.
|
||||
/// Confirmed to be present on Redump entries 24287, 31615, 34448, 35967, 36627, 37700, 37788, 43221, 55788, and 66749.
|
||||
/// </summary>
|
||||
public class CDLock : IPathCheck, IPortableExecutableCheck
|
||||
public class CDLock : IExecutableCheck<PortableExecutable>, IPathCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -63,18 +62,14 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET20 || NET35
|
||||
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#else
|
||||
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#endif
|
||||
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// TODO: Determine if there's any consistency in the naming of the additional AFP files.
|
||||
|
||||
// Found in every confirmed sample of CD-Lock, generally (but not always) appears to include markers relating to the additional AFP files present (Redump entries 24287 and 31615).
|
||||
new(new PathMatch("CONFIG.AFP", useEndsWith: true), "CD-Lock"),
|
||||
new(new FilePathMatch("CONFIG.AFP"), "CD-Lock"),
|
||||
|
||||
// There is also a "$$$$$$$$.$$$" file present on some discs, but it isn't known if this is directly related to CD-Lock (Redump entries 37788 and 43221).
|
||||
};
|
||||
@@ -90,7 +85,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// TODO: Determine if there's any consistency in the naming of the additional AFP files.
|
||||
|
||||
// Found in every confirmed sample of CD-Lock, generally (but not always) appears to include markers relating to the additional AFP files present (Redump entries 24287 and 31615).
|
||||
new(new PathMatch("CONFIG.AFP", useEndsWith: true), "CD-Lock"),
|
||||
new(new FilePathMatch("CONFIG.AFP"), "CD-Lock"),
|
||||
|
||||
// There is also a "$$$$$$$$.$$$" file present on some discs, but it isn't known if this is directly related to CD-Lock (Redump entries 37788 and 43221).
|
||||
};
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Collections.Concurrent;
|
||||
#endif
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Paths;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
@@ -19,11 +17,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public class CDProtector : IPathCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET20 || NET35
|
||||
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#else
|
||||
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#endif
|
||||
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
public class CDSHiELDSE : IPortableExecutableCheck
|
||||
public class CDSHiELDSE : IExecutableCheck<PortableExecutable>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
public string? CheckExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -28,7 +26,7 @@ namespace BinaryObjectScanner.Protection
|
||||
var strs = pex.GetFirstSectionStrings("code") ?? pex.GetFirstSectionStrings("CODE");
|
||||
if (strs != null)
|
||||
{
|
||||
if (strs.Any(s => s.Contains("~0017.tmp")))
|
||||
if (strs.Exists(s => s.Contains("~0017.tmp")))
|
||||
return "CDSHiELD SE";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using System.Collections.Concurrent;
|
||||
#endif
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Paths;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
@@ -14,11 +12,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public class CDX : IPathCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET20 || NET35
|
||||
public Queue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#else
|
||||
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#endif
|
||||
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
{
|
||||
// TODO: Verify if these are OR or AND
|
||||
var matchers = new List<PathMatchSet>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
@@ -17,14 +17,13 @@ namespace BinaryObjectScanner.Protection
|
||||
var contentMatchSets = new List<ContentMatchSet>
|
||||
{
|
||||
// CDSPlayer
|
||||
new(new byte?[] { 0x43, 0x44, 0x53, 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72 }, "Cactus Data Shield 200"),
|
||||
new([0x43, 0x44, 0x53, 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72], "Cactus Data Shield 200"),
|
||||
|
||||
// yucca.cds
|
||||
new(new byte?[] { 0x79, 0x75, 0x63, 0x63, 0x61, 0x2E, 0x63, 0x64, 0x73 }, "Cactus Data Shield 200"),
|
||||
new([0x79, 0x75, 0x63, 0x63, 0x61, 0x2E, 0x63, 0x64, 0x73], "Cactus Data Shield 200"),
|
||||
};
|
||||
|
||||
if (contentMatchSets != null && contentMatchSets.Any())
|
||||
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
|
||||
return MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user