mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-02-04 21:30:10 +00:00
Compare commits
234 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
7432100139 | ||
|
|
29fabb44eb | ||
|
|
ad776d4189 | ||
|
|
4cf12c76a8 | ||
|
|
39185f5ddd | ||
|
|
03477327c4 | ||
|
|
29fa0d1ac7 | ||
|
|
7eca23a7f3 | ||
|
|
f0c90bb332 | ||
|
|
0af67e5802 | ||
|
|
6ab9f730f9 | ||
|
|
258238bcc0 | ||
|
|
3936a15ef7 | ||
|
|
f6dbb349c4 | ||
|
|
3c69e02cfc | ||
|
|
531e634e62 | ||
|
|
f9c0c42b26 | ||
|
|
83aebbbfbd | ||
|
|
3847e5e9dc | ||
|
|
a72bb7e332 | ||
|
|
839791f467 | ||
|
|
469356e8c1 | ||
|
|
66e8eb985c | ||
|
|
90223e6c94 | ||
|
|
2f2cf76d7b | ||
|
|
558fee2200 | ||
|
|
a82abc05ec | ||
|
|
74df37597a | ||
|
|
1581023c01 | ||
|
|
c0d1260656 | ||
|
|
969d103c2c | ||
|
|
e5e3f3e3ef | ||
|
|
c1ee399262 | ||
|
|
74ee9932a7 | ||
|
|
e70f8d7220 | ||
|
|
ceba351372 | ||
|
|
ad4082c531 | ||
|
|
115ea02822 | ||
|
|
f876a4e4a6 | ||
|
|
be114f60d3 | ||
|
|
b2594f8148 | ||
|
|
f58ada3dde | ||
|
|
bc4f07970d | ||
|
|
25d6822283 | ||
|
|
3b22262c21 | ||
|
|
314fc1e3fc | ||
|
|
5742749dec | ||
|
|
c55fffeb7b | ||
|
|
e469dc38bf | ||
|
|
553703c30e | ||
|
|
3fd093f9b4 | ||
|
|
4946d4e7ff | ||
|
|
491fc0f71c | ||
|
|
fe6627f1ba | ||
|
|
edffa3c7cc | ||
|
|
a66d62bfbc | ||
|
|
9321b8f221 | ||
|
|
cd0863ac56 | ||
|
|
24a73e8bfd | ||
|
|
46eaa7db1e | ||
|
|
0eab7fd555 | ||
|
|
dba476d8bb | ||
|
|
b10b4d6658 | ||
|
|
2959fdbe9a | ||
|
|
9c0d100c2a | ||
|
|
03ca0faf2e | ||
|
|
cbaf004e25 | ||
|
|
bbe4fb610c | ||
|
|
650115f722 | ||
|
|
1afcbe3182 | ||
|
|
8aa90dbc49 | ||
|
|
0781524669 | ||
|
|
3b3cb7a862 | ||
|
|
810d20d95c | ||
|
|
de578511bf | ||
|
|
f1ec025950 | ||
|
|
0c58ecc548 | ||
|
|
d2a73a153b | ||
|
|
eae2e3366b | ||
|
|
afb04c99c0 | ||
|
|
1d3bd2f8b1 | ||
|
|
3f52c24713 | ||
|
|
ae1417a343 | ||
|
|
871a3e6366 | ||
|
|
3457b807cb | ||
|
|
027f295d21 | ||
|
|
63e6d1e285 | ||
|
|
2193095f70 | ||
|
|
074694298f | ||
|
|
ce4d32b053 | ||
|
|
a25af3940c | ||
|
|
9d1a2db45a | ||
|
|
5cdf269a3e | ||
|
|
b9d90ec35d | ||
|
|
5fc1d3254d | ||
|
|
d61bae8e61 | ||
|
|
f8f53869ae | ||
|
|
f5146a6e35 | ||
|
|
faf96b9375 | ||
|
|
2228e344f6 | ||
|
|
9955bdcab1 | ||
|
|
4586d49a3f | ||
|
|
1f4e24452a | ||
|
|
090bac4d59 | ||
|
|
59bedf5fce | ||
|
|
1bbc541957 | ||
|
|
1bb0107ceb | ||
|
|
10dad356cd | ||
|
|
22b6971e51 | ||
|
|
3203b56ef6 | ||
|
|
d6db84152f | ||
|
|
b7afad5a4a | ||
|
|
9d6c53f631 | ||
|
|
aa7b02dfc3 | ||
|
|
379ffaf61a | ||
|
|
1bdfccddbc | ||
|
|
c83cdd590c | ||
|
|
f4770374a7 | ||
|
|
72880e93bc | ||
|
|
6c9cd72948 | ||
|
|
2e71ef4635 | ||
|
|
04cd1098ea | ||
|
|
e76ce64568 | ||
|
|
8fe84abef3 | ||
|
|
1b1fa53547 | ||
|
|
5019407f35 | ||
|
|
83ba19eccb | ||
|
|
936bf38521 | ||
|
|
f54b0d2bbb | ||
|
|
0e32abc76c | ||
|
|
94cb06a3bd | ||
|
|
907aea443e | ||
|
|
385922723c | ||
|
|
3061c2f009 | ||
|
|
5c0ccbde35 | ||
|
|
7b998de2ca | ||
|
|
b0d49f52a5 | ||
|
|
6f9bcc2111 | ||
|
|
0fb0ecd28a | ||
|
|
6194d88aec | ||
|
|
b02c3121fe | ||
|
|
580db0cb65 | ||
|
|
6bcdc0e3c6 | ||
|
|
9b4fd91717 | ||
|
|
9421249b8e | ||
|
|
e823cbaee5 | ||
|
|
c34618554b | ||
|
|
6ab7b4a004 | ||
|
|
5b6bf3b73e | ||
|
|
2a30a13f5f | ||
|
|
3c05a112ca |
43
.github/workflows/build_nupkg.yml
vendored
Normal file
43
.github/workflows/build_nupkg.yml
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
name: Nuget Pack
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.x
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
|
||||
- name: Pack
|
||||
run: dotnet pack
|
||||
|
||||
- name: Upload build
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: 'Nuget Package'
|
||||
path: 'BinaryObjectScanner/bin/Release/*.nupkg'
|
||||
|
||||
- name: Upload to rolling
|
||||
uses: ncipollo/release-action@v1.14.0
|
||||
with:
|
||||
allowUpdates: True
|
||||
artifacts: 'BinaryObjectScanner/bin/Release/*.nupkg'
|
||||
body: 'Last built commit: ${{ github.sha }}'
|
||||
name: 'Rolling Release'
|
||||
prerelease: True
|
||||
replacesArtifacts: True
|
||||
tag: "rolling"
|
||||
updateOnlyUnreleased: True
|
||||
53
.github/workflows/build_test.yml
vendored
Normal file
53
.github/workflows/build_test.yml
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
name: Build Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
project: [Test]
|
||||
runtime: [win-x86, win-x64, win-arm64, linux-x64, linux-arm64, osx-x64]
|
||||
framework: [net8.0] #[net20, net35, net40, net452, net472, net48, netcoreapp3.1, net5.0, net6.0, net7.0, net8.0]
|
||||
conf: [Release, Debug]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.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' || ''}}
|
||||
|
||||
- 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/
|
||||
|
||||
- name: Upload build
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_${{ matrix.conf }}
|
||||
path: ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_${{ matrix.conf }}.zip
|
||||
|
||||
- name: Upload to rolling
|
||||
uses: ncipollo/release-action@v1.14.0
|
||||
with:
|
||||
allowUpdates: True
|
||||
artifacts: ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_${{ matrix.conf }}.zip
|
||||
body: 'Last built commit: ${{ github.sha }}'
|
||||
name: 'Rolling Release'
|
||||
prerelease: True
|
||||
replacesArtifacts: True
|
||||
tag: "rolling"
|
||||
updateOnlyUnreleased: True
|
||||
17
.github/workflows/check_pr.yml
vendored
Normal file
17
.github/workflows/check_pr.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
name: Build PR
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.x
|
||||
|
||||
- name: Build
|
||||
run: dotnet build
|
||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -1,3 +1,9 @@
|
||||
[submodule "BinaryObjectScanner/_EXTERNAL/stormlibsharp"]
|
||||
path = BinaryObjectScanner/_EXTERNAL/stormlibsharp
|
||||
url = https://github.com/robpaveza/stormlibsharp.git
|
||||
[submodule "BinaryObjectScanner/_EXTERNAL/libmspack4n"]
|
||||
path = BinaryObjectScanner/_EXTERNAL/libmspack4n
|
||||
url = https://github.com/activescott/libmspack4n.git
|
||||
[submodule "BinaryObjectScanner/_EXTERNAL/LessIO"]
|
||||
path = BinaryObjectScanner/_EXTERNAL/LessIO
|
||||
url = https://github.com/activescott/LessIO.git
|
||||
|
||||
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@@ -10,7 +10,7 @@
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/Test/bin/Debug/net6.0/Test.dll",
|
||||
"program": "${workspaceFolder}/Test/bin/Debug/net8.0/Test.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/Test",
|
||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||
|
||||
@@ -12,7 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||
Developer Guide.md = Developer Guide.md
|
||||
LICENSE = LICENSE
|
||||
publish-nix.sh = publish-nix.sh
|
||||
publish-win.bat = publish-win.bat
|
||||
publish-win.ps1 = publish-win.ps1
|
||||
README.md = README.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
|
||||
@@ -1,40 +1,67 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net48;net6.0;net7.0</TargetFrameworks>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Version>2.9.0</Version>
|
||||
<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.15</Version>
|
||||
<!-- Mostly added due to external libraries -->
|
||||
<WarningsNotAsErrors>CS0162;CS0612;CS8600;CS8601;CS8602;CS8603;CS8604;CS8605;CS8618;CS8625;CS8634;CS8765;IL3000;NU5100</WarningsNotAsErrors>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<PackageId>BurnOutSharp</PackageId> <!-- Temporary until official renaming -->
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
<Description>Protection scanning library</Description>
|
||||
<Copyright>Copyright (c)2018-2023 Matt Nadareski</Copyright>
|
||||
<Copyright>Copyright (c)2018-2024 Matt Nadareski</Copyright>
|
||||
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/mnadareski/BurnOutSharp</RepositoryUrl>
|
||||
<RepositoryUrl>https://github.com/SabreTools/BinaryObjectScanner</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageTags>protection copy-protection scanning packer</PackageTags>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TargetFramework)'!='net48'">
|
||||
<Nullable>enable</Nullable>
|
||||
<!-- Set a build flag for Windows specifically -->
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)'=='win-x86'">
|
||||
<DefineConstants>$(DefineConstants);WIN</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- These are needed for dealing with submodules -->
|
||||
<!-- 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>
|
||||
|
||||
<!-- Exclude all StormLibSharp for .NET Framework 4.0 -->
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net40`))">
|
||||
<DefaultItemExcludes>
|
||||
$(DefaultItemExcludes);
|
||||
_EXTERNAL\stormlibsharp\src\**
|
||||
</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Exclude all external modules for .NET Framework 2.0, .NET Framework 3.5, or non-Windows builds -->
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR !$(RuntimeIdentifier.StartsWith(`win-x86`))">
|
||||
<DefaultItemExcludes>
|
||||
$(DefaultItemExcludes);
|
||||
_EXTERNAL\**
|
||||
</DefaultItemExcludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- These are needed for dealing with native Windows DLLs -->
|
||||
<ItemGroup>
|
||||
<ItemGroup Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND $(RuntimeIdentifier.StartsWith(`win-x86`))">
|
||||
<Content Include="*.dll">
|
||||
<Pack>true</Pack>
|
||||
<PackagePath>contentFiles;content</PackagePath>
|
||||
@@ -47,22 +74,30 @@
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenMcdf" Version="2.3.0" />
|
||||
<PackageReference Include="SabreTools.Compression" Version="0.1.1" />
|
||||
<PackageReference Include="SabreTools.IO" Version="1.1.1" />
|
||||
<PackageReference Include="SabreTools.Matching" Version="1.1.1" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.1.5" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.1.7" />
|
||||
<PackageReference Include="SharpCompress" Version="0.34.1" />
|
||||
<PackageReference Include="SharpZipLib" Version="1.4.2" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="7.0.0" />
|
||||
<PackageReference Include="UnshieldSharp" Version="1.6.9" />
|
||||
<PackageReference Include="WiseUnpacker" Version="1.0.4" />
|
||||
<!-- 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" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)'=='net48'">
|
||||
<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 Condition="$(TargetFramework.StartsWith(`net4`)) AND !$(TargetFramework.StartsWith(`net40`))">
|
||||
<PackageReference Include="System.Memory" Version="4.5.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SabreTools.Compression" Version="0.5.2" />
|
||||
<PackageReference Include="SabreTools.Hashing" Version="1.2.2" />
|
||||
<PackageReference Include="SabreTools.IO" Version="1.4.13" />
|
||||
<PackageReference Include="SabreTools.Matching" Version="1.3.3" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.4.11" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="1.6.9" />
|
||||
<PackageReference Include="UnshieldSharp" Version="1.8.5" />
|
||||
<PackageReference Include="WiseUnpacker" Version="1.4.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Utilities;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner
|
||||
{
|
||||
@@ -8,71 +8,65 @@ namespace BinaryObjectScanner
|
||||
/// <summary>
|
||||
/// Create an instance of a detectable based on file type
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static IDetectable CreateDetectable(SupportedFileType fileType)
|
||||
#else
|
||||
public static IDetectable? CreateDetectable(SupportedFileType fileType)
|
||||
#endif
|
||||
public static IDetectable? CreateDetectable(WrapperType fileType)
|
||||
{
|
||||
switch (fileType)
|
||||
return fileType switch
|
||||
{
|
||||
case SupportedFileType.AACSMediaKeyBlock: return new BinaryObjectScanner.FileType.AACSMediaKeyBlock();
|
||||
case SupportedFileType.BDPlusSVM: return new BinaryObjectScanner.FileType.BDPlusSVM();
|
||||
//case SupportedFileType.CIA: return new BinaryObjectScanner.FileType.CIA();
|
||||
case SupportedFileType.Executable: return new BinaryObjectScanner.FileType.Executable();
|
||||
case SupportedFileType.LDSCRYPT: return new BinaryObjectScanner.FileType.LDSCRYPT();
|
||||
//case SupportedFileType.N3DS: return new BinaryObjectScanner.FileType.N3DS();
|
||||
//case SupportedFileType.Nitro: return new BinaryObjectScanner.FileType.Nitro();
|
||||
case SupportedFileType.PLJ: return new BinaryObjectScanner.FileType.PLJ();
|
||||
case SupportedFileType.SFFS: return new BinaryObjectScanner.FileType.SFFS();
|
||||
case SupportedFileType.Textfile: return new BinaryObjectScanner.FileType.Textfile();
|
||||
default: return null;
|
||||
}
|
||||
WrapperType.AACSMediaKeyBlock => new FileType.AACSMediaKeyBlock(),
|
||||
WrapperType.BDPlusSVM => new FileType.BDPlusSVM(),
|
||||
//WrapperType.CIA => new FileType.CIA(),
|
||||
WrapperType.Executable => new FileType.Executable(),
|
||||
WrapperType.LDSCRYPT => new FileType.LDSCRYPT(),
|
||||
//WrapperType.N3DS => new FileType.N3DS(),
|
||||
//WrapperType.Nitro => new FileType.Nitro(),
|
||||
WrapperType.PlayJAudioFile => new FileType.PLJ(),
|
||||
WrapperType.RealArcadeInstaller => new FileType.RealArcadeInstaller(),
|
||||
WrapperType.RealArcadeMezzanine => new FileType.RealArcadeMezzanine(),
|
||||
WrapperType.SFFS => new FileType.SFFS(),
|
||||
WrapperType.Textfile => new FileType.Textfile(),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an instance of an extractable based on file type
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static IExtractable CreateExtractable(SupportedFileType fileType)
|
||||
#else
|
||||
public static IExtractable? CreateExtractable(SupportedFileType fileType)
|
||||
#endif
|
||||
public static IExtractable? CreateExtractable(WrapperType fileType)
|
||||
{
|
||||
switch (fileType)
|
||||
return fileType switch
|
||||
{
|
||||
case SupportedFileType.BFPK: return new BinaryObjectScanner.FileType.BFPK();
|
||||
case SupportedFileType.BSP: return new BinaryObjectScanner.FileType.BSP();
|
||||
case SupportedFileType.BZip2: return new BinaryObjectScanner.FileType.BZip2();
|
||||
case SupportedFileType.CFB: return new BinaryObjectScanner.FileType.CFB();
|
||||
//case SupportedFileType.CIA: return new BinaryObjectScanner.FileType.CIA();
|
||||
case SupportedFileType.GCF: return new BinaryObjectScanner.FileType.GCF();
|
||||
case SupportedFileType.GZIP: return new BinaryObjectScanner.FileType.GZIP();
|
||||
case SupportedFileType.InstallShieldArchiveV3: return new BinaryObjectScanner.FileType.InstallShieldArchiveV3();
|
||||
case SupportedFileType.InstallShieldCAB: return new BinaryObjectScanner.FileType.InstallShieldCAB();
|
||||
case SupportedFileType.MicrosoftCAB: return new BinaryObjectScanner.FileType.MicrosoftCAB();
|
||||
case SupportedFileType.MicrosoftLZ: return new BinaryObjectScanner.FileType.MicrosoftLZ();
|
||||
case SupportedFileType.MPQ: return new BinaryObjectScanner.FileType.MPQ();
|
||||
//case SupportedFileType.N3DS: return new BinaryObjectScanner.FileType.N3DS();
|
||||
//case SupportedFileType.NCF: return new BinaryObjectScanner.FileType.NCF();
|
||||
//case SupportedFileType.Nitro: return new BinaryObjectScanner.FileType.Nitro();
|
||||
case SupportedFileType.PAK: return new BinaryObjectScanner.FileType.PAK();
|
||||
case SupportedFileType.PFF: return new BinaryObjectScanner.FileType.PFF();
|
||||
case SupportedFileType.PKZIP: return new BinaryObjectScanner.FileType.PKZIP();
|
||||
//case SupportedFileType.PLJ: return new BinaryObjectScanner.FileType.PLJ();
|
||||
//case SupportedFileType.Quantum: return new BinaryObjectScanner.FileType.Quantum();
|
||||
case SupportedFileType.RAR: return new BinaryObjectScanner.FileType.RAR();
|
||||
case SupportedFileType.SevenZip: return new BinaryObjectScanner.FileType.SevenZip();
|
||||
case SupportedFileType.SFFS: return new BinaryObjectScanner.FileType.SFFS();
|
||||
case SupportedFileType.SGA: return new BinaryObjectScanner.FileType.SGA();
|
||||
case SupportedFileType.TapeArchive: return new BinaryObjectScanner.FileType.TapeArchive();
|
||||
case SupportedFileType.VBSP: return new BinaryObjectScanner.FileType.VBSP();
|
||||
case SupportedFileType.VPK: return new BinaryObjectScanner.FileType.VPK();
|
||||
case SupportedFileType.WAD: return new BinaryObjectScanner.FileType.WAD();
|
||||
case SupportedFileType.XZ: return new BinaryObjectScanner.FileType.XZ();
|
||||
case SupportedFileType.XZP: return new BinaryObjectScanner.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,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,27 +11,19 @@ namespace BinaryObjectScanner.FileType
|
||||
public class AACSMediaKeyBlock : IDetectable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Detect(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Detect(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Detect(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Detect(Stream stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// If the MKB file itself fails
|
||||
try
|
||||
|
||||
@@ -10,27 +10,19 @@ namespace BinaryObjectScanner.FileType
|
||||
public class BDPlusSVM : IDetectable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Detect(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Detect(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Detect(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Detect(Stream stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// If the BD+ file itself fails
|
||||
try
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.Deflate;
|
||||
#endif
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
@@ -12,27 +14,17 @@ namespace BinaryObjectScanner.FileType
|
||||
public class BFPK : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -56,7 +48,7 @@ namespace BinaryObjectScanner.FileType
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Extract all files from the BFPK to an output directory
|
||||
/// </summary>
|
||||
@@ -117,25 +109,26 @@ namespace BinaryObjectScanner.FileType
|
||||
|
||||
// Create the output path
|
||||
string filePath = Path.Combine(outputDirectory, file.Name ?? $"file{index}");
|
||||
using (FileStream fs = File.OpenWrite(filePath))
|
||||
{
|
||||
// Read the data block
|
||||
var data = item.ReadFromDataSource(offset, compressedSize);
|
||||
if (data == null)
|
||||
return false;
|
||||
using FileStream fs = File.OpenWrite(filePath);
|
||||
|
||||
// If we have uncompressed data
|
||||
if (compressedSize == file.UncompressedSize)
|
||||
{
|
||||
fs.Write(data, 0, compressedSize);
|
||||
}
|
||||
// Read the data block
|
||||
var data = item.ReadFromDataSource(offset, compressedSize);
|
||||
if (data == null)
|
||||
return false;
|
||||
|
||||
// If we have uncompressed data
|
||||
if (compressedSize == file.UncompressedSize)
|
||||
{
|
||||
fs.Write(data, 0, compressedSize);
|
||||
}
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
else
|
||||
{
|
||||
MemoryStream ms = new MemoryStream(data);
|
||||
ZlibStream zs = new ZlibStream(ms, CompressionMode.Decompress);
|
||||
zs.CopyTo(fs);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -11,27 +11,19 @@ namespace BinaryObjectScanner.FileType
|
||||
public class BSP : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -117,7 +109,7 @@ namespace BinaryObjectScanner.FileType
|
||||
}
|
||||
|
||||
// If we have an invalid output directory
|
||||
if (string.IsNullOrWhiteSpace(outputDirectory))
|
||||
if (string.IsNullOrEmpty(outputDirectory))
|
||||
return false;
|
||||
|
||||
// Create the full output path
|
||||
@@ -196,7 +188,7 @@ namespace BinaryObjectScanner.FileType
|
||||
string filename = $"{texture.Name}.bmp";
|
||||
|
||||
// If we have an invalid output directory
|
||||
if (string.IsNullOrWhiteSpace(outputDirectory))
|
||||
if (string.IsNullOrEmpty(outputDirectory))
|
||||
return false;
|
||||
|
||||
// Create the full output path
|
||||
@@ -229,11 +221,7 @@ namespace BinaryObjectScanner.FileType
|
||||
/// </summary>
|
||||
/// <param name="texture">Texture object to format</param>
|
||||
/// <returns>Byte array representing the texture as a bitmap</returns>
|
||||
#if NET48
|
||||
private static byte[] CreateTextureData(SabreTools.Models.BSP.Texture texture)
|
||||
#else
|
||||
private static byte[]? CreateTextureData(SabreTools.Models.BSP.Texture texture)
|
||||
#endif
|
||||
{
|
||||
// If there's no palette data
|
||||
if (texture.PaletteData == null || texture.PaletteData.Length == 0)
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.BZip2;
|
||||
#endif
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
@@ -12,31 +14,22 @@ namespace BinaryObjectScanner.FileType
|
||||
public class BZip2 : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (stream == null)
|
||||
return null;
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
@@ -59,6 +52,9 @@ namespace BinaryObjectScanner.FileType
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
#if NET40_OR_GREATER || NETCOREAPP
|
||||
using OpenMcdf;
|
||||
#endif
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
@@ -12,28 +14,22 @@ namespace BinaryObjectScanner.FileType
|
||||
public class CFB : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
#if NET20 || NET35
|
||||
// Not supported for .NET Framework 2.0 or .NET Framework 3.5 due to library support
|
||||
return null;
|
||||
#else
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
@@ -92,14 +88,11 @@ namespace BinaryObjectScanner.FileType
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <remarks>Adapted from LibMSI</remarks>
|
||||
#if NET48
|
||||
public static string DecodeStreamName(string input)
|
||||
#else
|
||||
public static string? DecodeStreamName(string input)
|
||||
#endif
|
||||
{
|
||||
if (input == null)
|
||||
return null;
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Utilities;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
@@ -40,10 +37,8 @@ namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (contentCheckClasses == null)
|
||||
contentCheckClasses = InitCheckClasses<IContentCheck>();
|
||||
|
||||
return contentCheckClasses ?? Enumerable.Empty<IContentCheck>();
|
||||
contentCheckClasses ??= InitCheckClasses<IContentCheck>();
|
||||
return contentCheckClasses ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,10 +49,8 @@ namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (linearExecutableCheckClasses == null)
|
||||
linearExecutableCheckClasses = InitCheckClasses<ILinearExecutableCheck>();
|
||||
|
||||
return linearExecutableCheckClasses ?? Enumerable.Empty<ILinearExecutableCheck>();
|
||||
linearExecutableCheckClasses ??= InitCheckClasses<ILinearExecutableCheck>();
|
||||
return linearExecutableCheckClasses ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,10 +61,8 @@ namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (msdosExecutableCheckClasses == null)
|
||||
msdosExecutableCheckClasses = InitCheckClasses<IMSDOSExecutableCheck>();
|
||||
|
||||
return msdosExecutableCheckClasses ?? Enumerable.Empty<IMSDOSExecutableCheck>();
|
||||
msdosExecutableCheckClasses ??= InitCheckClasses<IMSDOSExecutableCheck>();
|
||||
return msdosExecutableCheckClasses ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,10 +73,8 @@ namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (newExecutableCheckClasses == null)
|
||||
newExecutableCheckClasses = InitCheckClasses<INewExecutableCheck>();
|
||||
|
||||
return newExecutableCheckClasses ?? Enumerable.Empty<INewExecutableCheck>();
|
||||
newExecutableCheckClasses ??= InitCheckClasses<INewExecutableCheck>();
|
||||
return newExecutableCheckClasses ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,10 +85,8 @@ namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (portableExecutableCheckClasses == null)
|
||||
portableExecutableCheckClasses = InitCheckClasses<IPortableExecutableCheck>();
|
||||
|
||||
return portableExecutableCheckClasses ?? Enumerable.Empty<IPortableExecutableCheck>();
|
||||
portableExecutableCheckClasses ??= InitCheckClasses<IPortableExecutableCheck>();
|
||||
return portableExecutableCheckClasses ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,115 +97,85 @@ namespace BinaryObjectScanner.FileType
|
||||
/// <summary>
|
||||
/// Cache for all IContentCheck types
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private static IEnumerable<IContentCheck> contentCheckClasses;
|
||||
#else
|
||||
private static IEnumerable<IContentCheck>? contentCheckClasses;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all ILinearExecutableCheck types
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private static IEnumerable<ILinearExecutableCheck> linearExecutableCheckClasses;
|
||||
#else
|
||||
private static IEnumerable<ILinearExecutableCheck>? linearExecutableCheckClasses;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IMSDOSExecutableCheck types
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private static IEnumerable<IMSDOSExecutableCheck> msdosExecutableCheckClasses;
|
||||
#else
|
||||
private static IEnumerable<IMSDOSExecutableCheck>? msdosExecutableCheckClasses;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all INewExecutableCheck types
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private static IEnumerable<INewExecutableCheck> newExecutableCheckClasses;
|
||||
#else
|
||||
private static IEnumerable<INewExecutableCheck>? newExecutableCheckClasses;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Cache for all IPortableExecutableCheck types
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private static IEnumerable<IPortableExecutableCheck> portableExecutableCheckClasses;
|
||||
#else
|
||||
private static IEnumerable<IPortableExecutableCheck>? portableExecutableCheckClasses;
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Detect(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Detect(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Detect(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Detect(Stream stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Try to create a wrapper for the proper executable type
|
||||
var wrapper = WrapperFactory.CreateExecutableWrapper(stream);
|
||||
if (wrapper == null)
|
||||
return null;
|
||||
|
||||
// Create the internal queue
|
||||
var protections = new ConcurrentQueue<string>();
|
||||
// Create the internal list
|
||||
var protections = new List<string>();
|
||||
|
||||
// Only use generic content checks if we're in debug mode
|
||||
if (includeDebug)
|
||||
{
|
||||
var subProtections = RunContentChecks(file, stream, includeDebug);
|
||||
if (subProtections != null)
|
||||
protections.AddRange(subProtections.Values.ToArray());
|
||||
protections.AddRange(subProtections.Values);
|
||||
}
|
||||
|
||||
if (wrapper is MSDOS mz)
|
||||
{
|
||||
var subProtections = RunMSDOSExecutableChecks(file, stream, mz, includeDebug);
|
||||
if (subProtections != null)
|
||||
protections.AddRange(subProtections.Values.ToArray());
|
||||
protections.AddRange(subProtections.Values);
|
||||
}
|
||||
else if (wrapper is LinearExecutable lex)
|
||||
{
|
||||
var subProtections = RunLinearExecutableChecks(file, stream, lex, includeDebug);
|
||||
if (subProtections != null)
|
||||
protections.AddRange(subProtections.Values.ToArray());
|
||||
protections.AddRange(subProtections.Values);
|
||||
}
|
||||
else if (wrapper is NewExecutable nex)
|
||||
{
|
||||
var subProtections = RunNewExecutableChecks(file, stream, nex, includeDebug);
|
||||
if (subProtections != null)
|
||||
protections.AddRange(subProtections.Values.ToArray());
|
||||
protections.AddRange(subProtections.Values);
|
||||
}
|
||||
else if (wrapper is PortableExecutable pex)
|
||||
{
|
||||
var subProtections = RunPortableExecutableChecks(file, stream, pex, includeDebug);
|
||||
if (subProtections != null)
|
||||
protections.AddRange(subProtections.Values.ToArray());
|
||||
protections.AddRange(subProtections.Values);
|
||||
}
|
||||
|
||||
return string.Join(";", protections);
|
||||
return string.Join(";", [.. protections]);
|
||||
}
|
||||
|
||||
#region Check Runners
|
||||
@@ -230,28 +187,21 @@ namespace BinaryObjectScanner.FileType
|
||||
/// <param name="stream">Stream to scan the contents of</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
#if NET48
|
||||
public ConcurrentDictionary<IContentCheck, string> RunContentChecks(string file, Stream stream, bool includeDebug)
|
||||
#else
|
||||
public ConcurrentDictionary<IContentCheck, string>? RunContentChecks(string? file, Stream stream, bool includeDebug)
|
||||
#endif
|
||||
public IDictionary<IContentCheck, string>? RunContentChecks(string? file, Stream stream, bool includeDebug)
|
||||
{
|
||||
// If we have an invalid file
|
||||
if (string.IsNullOrWhiteSpace(file))
|
||||
if (string.IsNullOrEmpty(file))
|
||||
return null;
|
||||
else if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
// Read the file contents
|
||||
byte[] fileContent = new byte[0];
|
||||
byte[] fileContent = [];
|
||||
try
|
||||
{
|
||||
using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
|
||||
{
|
||||
fileContent = br.ReadBytes((int)stream.Length);
|
||||
if (fileContent == null)
|
||||
return null;
|
||||
}
|
||||
fileContent = stream.ReadBytes((int)stream.Length);
|
||||
if (fileContent == null)
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -260,14 +210,14 @@ namespace BinaryObjectScanner.FileType
|
||||
}
|
||||
|
||||
// Create the output dictionary
|
||||
var protections = new ConcurrentDictionary<IContentCheck, string>();
|
||||
var protections = new CheckDictionary<IContentCheck>();
|
||||
|
||||
// Iterate through all checks
|
||||
Parallel.ForEach(ContentCheckClasses, checkClass =>
|
||||
ContentCheckClasses.IterateWithAction(checkClass =>
|
||||
{
|
||||
// Get the protection for the class, if possible
|
||||
var protection = checkClass.CheckContents(file, fileContent, includeDebug);
|
||||
if (string.IsNullOrWhiteSpace(protection))
|
||||
var protection = checkClass.CheckContents(file!, fileContent, includeDebug);
|
||||
if (string.IsNullOrEmpty(protection))
|
||||
return;
|
||||
|
||||
// If we are filtering on game engines
|
||||
@@ -278,7 +228,7 @@ namespace BinaryObjectScanner.FileType
|
||||
if (CheckIfPacker(checkClass) && !IncludePackers)
|
||||
return;
|
||||
|
||||
protections.TryAdd(checkClass, protection);
|
||||
protections.Append(checkClass, protection);
|
||||
});
|
||||
|
||||
return protections;
|
||||
@@ -291,17 +241,17 @@ namespace BinaryObjectScanner.FileType
|
||||
/// <param name="lex">Executable to scan</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
public ConcurrentDictionary<ILinearExecutableCheck, string> RunLinearExecutableChecks(string file, Stream stream, LinearExecutable lex, bool includeDebug)
|
||||
public IDictionary<ILinearExecutableCheck, string> RunLinearExecutableChecks(string file, Stream stream, LinearExecutable lex, bool includeDebug)
|
||||
{
|
||||
// Create the output dictionary
|
||||
var protections = new ConcurrentDictionary<ILinearExecutableCheck, string>();
|
||||
var protections = new CheckDictionary<ILinearExecutableCheck>();
|
||||
|
||||
// Iterate through all checks
|
||||
Parallel.ForEach(LinearExecutableCheckClasses, checkClass =>
|
||||
LinearExecutableCheckClasses.IterateWithAction(checkClass =>
|
||||
{
|
||||
// Get the protection for the class, if possible
|
||||
var protection = checkClass.CheckLinearExecutable(file, lex, includeDebug);
|
||||
if (string.IsNullOrWhiteSpace(protection))
|
||||
if (string.IsNullOrEmpty(protection))
|
||||
return;
|
||||
|
||||
// If we are filtering on game engines
|
||||
@@ -312,7 +262,7 @@ namespace BinaryObjectScanner.FileType
|
||||
if (CheckIfPacker(checkClass) && !IncludePackers)
|
||||
return;
|
||||
|
||||
protections.TryAdd(checkClass, protection);
|
||||
protections.Append(checkClass, protection);
|
||||
});
|
||||
|
||||
return protections;
|
||||
@@ -325,17 +275,17 @@ namespace BinaryObjectScanner.FileType
|
||||
/// <param name="mz">Executable to scan</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
public ConcurrentDictionary<IMSDOSExecutableCheck, string> RunMSDOSExecutableChecks(string file, Stream stream, MSDOS mz, bool includeDebug)
|
||||
public IDictionary<IMSDOSExecutableCheck, string> RunMSDOSExecutableChecks(string file, Stream stream, MSDOS mz, bool includeDebug)
|
||||
{
|
||||
// Create the output dictionary
|
||||
var protections = new ConcurrentDictionary<IMSDOSExecutableCheck, string>();
|
||||
var protections = new CheckDictionary<IMSDOSExecutableCheck>();
|
||||
|
||||
// Iterate through all checks
|
||||
Parallel.ForEach(MSDOSExecutableCheckClasses, checkClass =>
|
||||
MSDOSExecutableCheckClasses.IterateWithAction(checkClass =>
|
||||
{
|
||||
// Get the protection for the class, if possible
|
||||
var protection = checkClass.CheckMSDOSExecutable(file, mz, includeDebug);
|
||||
if (string.IsNullOrWhiteSpace(protection))
|
||||
if (string.IsNullOrEmpty(protection))
|
||||
return;
|
||||
|
||||
// If we are filtering on game engines
|
||||
@@ -346,7 +296,7 @@ namespace BinaryObjectScanner.FileType
|
||||
if (CheckIfPacker(checkClass) && !IncludePackers)
|
||||
return;
|
||||
|
||||
protections.TryAdd(checkClass, protection);
|
||||
protections.Append(checkClass, protection);
|
||||
});
|
||||
|
||||
return protections;
|
||||
@@ -359,17 +309,17 @@ namespace BinaryObjectScanner.FileType
|
||||
/// <param name="nex">Executable to scan</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
public ConcurrentDictionary<INewExecutableCheck, string> RunNewExecutableChecks(string file, Stream stream, NewExecutable nex, bool includeDebug)
|
||||
public IDictionary<INewExecutableCheck, string> RunNewExecutableChecks(string file, Stream stream, NewExecutable nex, bool includeDebug)
|
||||
{
|
||||
// Create the output dictionary
|
||||
var protections = new ConcurrentDictionary<INewExecutableCheck, string>();
|
||||
var protections = new CheckDictionary<INewExecutableCheck>();
|
||||
|
||||
// Iterate through all checks
|
||||
Parallel.ForEach(NewExecutableCheckClasses, checkClass =>
|
||||
NewExecutableCheckClasses.IterateWithAction(checkClass =>
|
||||
{
|
||||
// Get the protection for the class, if possible
|
||||
var protection = checkClass.CheckNewExecutable(file, nex, includeDebug);
|
||||
if (string.IsNullOrWhiteSpace(protection))
|
||||
if (string.IsNullOrEmpty(protection))
|
||||
return;
|
||||
|
||||
// If we are filtering on game engines
|
||||
@@ -380,7 +330,7 @@ namespace BinaryObjectScanner.FileType
|
||||
if (CheckIfPacker(checkClass) && !IncludePackers)
|
||||
return;
|
||||
|
||||
protections.TryAdd(checkClass, protection);
|
||||
protections.Append(checkClass, protection);
|
||||
});
|
||||
|
||||
return protections;
|
||||
@@ -393,17 +343,17 @@ namespace BinaryObjectScanner.FileType
|
||||
/// <param name="pex">Executable to scan</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
public ConcurrentDictionary<IPortableExecutableCheck, string> RunPortableExecutableChecks(string file, Stream stream, PortableExecutable pex, bool includeDebug)
|
||||
public IDictionary<IPortableExecutableCheck, string> RunPortableExecutableChecks(string file, Stream stream, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// Create the output dictionary
|
||||
var protections = new ConcurrentDictionary<IPortableExecutableCheck, string>();
|
||||
var protections = new CheckDictionary<IPortableExecutableCheck>();
|
||||
|
||||
// Iterate through all checks
|
||||
Parallel.ForEach(PortableExecutableCheckClasses, checkClass =>
|
||||
PortableExecutableCheckClasses.IterateWithAction(checkClass =>
|
||||
{
|
||||
// Get the protection for the class, if possible
|
||||
var protection = checkClass.CheckPortableExecutable(file, pex, includeDebug);
|
||||
if (string.IsNullOrWhiteSpace(protection))
|
||||
if (string.IsNullOrEmpty(protection))
|
||||
return;
|
||||
|
||||
// If we are filtering on game engines
|
||||
@@ -414,7 +364,7 @@ namespace BinaryObjectScanner.FileType
|
||||
if (CheckIfPacker(checkClass) && !IncludePackers)
|
||||
return;
|
||||
|
||||
protections.TryAdd(checkClass, protection);
|
||||
protections.Append(checkClass, protection);
|
||||
});
|
||||
|
||||
return protections;
|
||||
@@ -427,35 +377,44 @@ namespace BinaryObjectScanner.FileType
|
||||
/// <summary>
|
||||
/// Initialize all implementations of a type
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private static IEnumerable<T> InitCheckClasses<T>()
|
||||
#else
|
||||
private static IEnumerable<T>? InitCheckClasses<T>()
|
||||
#endif
|
||||
=> InitCheckClasses<T>(typeof(GameEngine._DUMMY).Assembly) ?? Enumerable.Empty<T>()
|
||||
.Concat(InitCheckClasses<T>(typeof(Packer._DUMMY).Assembly) ?? Enumerable.Empty<T>())
|
||||
.Concat(InitCheckClasses<T>(typeof(Protection._DUMMY).Assembly) ?? Enumerable.Empty<T>());
|
||||
private static IEnumerable<T>? InitCheckClasses<T>() =>
|
||||
InitCheckClasses<T>(Assembly.GetExecutingAssembly()) ?? [];
|
||||
|
||||
/// <summary>
|
||||
/// Initialize all implementations of a type
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private static IEnumerable<T> InitCheckClasses<T>(Assembly assembly)
|
||||
#else
|
||||
private static IEnumerable<T>? InitCheckClasses<T>(Assembly assembly)
|
||||
#endif
|
||||
{
|
||||
return assembly.GetTypes()?
|
||||
.Where(t => t.IsClass && t.GetInterface(typeof(T).Name) != null)?
|
||||
#if NET48
|
||||
.Select(t => (T)Activator.CreateInstance(t))
|
||||
#else
|
||||
.Select(t => (T?)Activator.CreateInstance(t))
|
||||
#endif
|
||||
.Cast<T>() ?? Array.Empty<T>();
|
||||
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
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
|
||||
@@ -11,27 +11,19 @@ namespace BinaryObjectScanner.FileType
|
||||
public class GCF : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -124,7 +116,7 @@ namespace BinaryObjectScanner.FileType
|
||||
var filename = file.Path;
|
||||
|
||||
// If we have an invalid output directory
|
||||
if (string.IsNullOrWhiteSpace(outputDirectory))
|
||||
if (string.IsNullOrEmpty(outputDirectory))
|
||||
return false;
|
||||
|
||||
// Create the full output path
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.GZip;
|
||||
#endif
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
@@ -12,31 +14,22 @@ namespace BinaryObjectScanner.FileType
|
||||
public class GZIP : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (stream == null)
|
||||
return null;
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
@@ -49,10 +42,14 @@ namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
// 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);
|
||||
}
|
||||
@@ -70,6 +67,9 @@ namespace BinaryObjectScanner.FileType
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using UnshieldSharp.Archive;
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
@@ -12,27 +10,17 @@ namespace BinaryObjectScanner.FileType
|
||||
public class InstallShieldArchiveV3 : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -41,17 +29,17 @@ namespace BinaryObjectScanner.FileType
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
UnshieldSharp.Archive.InstallShieldArchiveV3 archive = new UnshieldSharp.Archive.InstallShieldArchiveV3(file);
|
||||
foreach (CompressedFile cfile in archive.Files.Select(kvp => kvp.Value))
|
||||
foreach (var cfile in archive.Files)
|
||||
{
|
||||
try
|
||||
{
|
||||
string tempFile = Path.Combine(tempPath, cfile.FullPath);
|
||||
string tempFile = Path.Combine(tempPath, cfile.Key);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
|
||||
(byte[] fileContents, string error) = archive.Extract(cfile.FullPath);
|
||||
if (!string.IsNullOrWhiteSpace(error))
|
||||
byte[]? fileContents = archive.Extract(cfile.Key, out string? error);
|
||||
if (fileContents == null || !string.IsNullOrEmpty(error))
|
||||
continue;
|
||||
|
||||
using (FileStream fs = File.OpenWrite(tempFile))
|
||||
|
||||
@@ -12,27 +12,17 @@ namespace BinaryObjectScanner.FileType
|
||||
public class InstallShieldCAB : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the name of the first cabinet file or header
|
||||
var directory = Path.GetDirectoryName(file);
|
||||
@@ -68,20 +58,23 @@ namespace BinaryObjectScanner.FileType
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
InstallShieldCabinet cabfile = InstallShieldCabinet.Open(file);
|
||||
for (int i = 0; i < cabfile.FileCount; i++)
|
||||
var cabfile = InstallShieldCabinet.Open(file);
|
||||
if (cabfile?.HeaderList == null)
|
||||
return null;
|
||||
|
||||
for (int i = 0; i < cabfile.HeaderList.FileCount; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Check if the file is valid first
|
||||
if (!cabfile.FileIsValid(i))
|
||||
if (!cabfile.HeaderList.FileIsValid(i))
|
||||
continue;
|
||||
|
||||
string tempFile;
|
||||
try
|
||||
{
|
||||
string filename = cabfile.FileName(i);
|
||||
tempFile = Path.Combine(tempPath, filename);
|
||||
string? filename = cabfile.HeaderList.GetFileName(i);
|
||||
tempFile = Path.Combine(tempPath, filename ?? string.Empty);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -11,27 +11,19 @@ namespace BinaryObjectScanner.FileType
|
||||
public class LDSCRYPT : IDetectable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Detect(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Detect(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Detect(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Detect(Stream stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
#if NET48
|
||||
#if (NET452_OR_GREATER || NETCOREAPP) && WIN
|
||||
using StormLibSharp;
|
||||
#endif
|
||||
|
||||
@@ -13,43 +12,34 @@ namespace BinaryObjectScanner.FileType
|
||||
public class MPQ : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
// TODO: Add stream opening support
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
#if NET6_0_OR_GREATER
|
||||
// Not supported for .NET 6.0 due to Windows DLL requirements
|
||||
#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;
|
||||
#else
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), System.Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (MpqArchive mpqArchive = new MpqArchive(file, FileAccess.Read))
|
||||
using (var mpqArchive = new MpqArchive(file, FileAccess.Read))
|
||||
{
|
||||
// Try to open the listfile
|
||||
string listfile = null;
|
||||
string? listfile = null;
|
||||
MpqFileStream listStream = mpqArchive.OpenFile("(listfile)");
|
||||
|
||||
// If we can't read the listfile, we just return
|
||||
@@ -57,7 +47,7 @@ namespace BinaryObjectScanner.FileType
|
||||
return null;
|
||||
|
||||
// Read the listfile in for processing
|
||||
using (StreamReader sr = new StreamReader(listStream))
|
||||
using (var sr = new StreamReader(listStream))
|
||||
{
|
||||
listfile = sr.ReadToEnd();
|
||||
}
|
||||
@@ -74,18 +64,18 @@ namespace BinaryObjectScanner.FileType
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(tempFile));
|
||||
mpqArchive.ExtractFile(sub, tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
if (includeDebug) System.Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
if (includeDebug) System.Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
#if (NET40_OR_GREATER || NETCOREAPP) && WIN
|
||||
using LibMSPackN;
|
||||
#endif
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
@@ -13,29 +14,55 @@ namespace BinaryObjectScanner.FileType
|
||||
public class MicrosoftCAB : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
#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;
|
||||
#else
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), System.Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (var cabArchive = new MSCabinet(file))
|
||||
{
|
||||
// Loop over each entry
|
||||
foreach (var compressedFile in cabArchive.GetFiles())
|
||||
{
|
||||
try
|
||||
{
|
||||
string tempFile = Path.Combine(tempPath, compressedFile.Filename);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(tempFile));
|
||||
compressedFile.ExtractTo(tempFile);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
if (includeDebug) System.Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
if (includeDebug) System.Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,27 +12,19 @@ namespace BinaryObjectScanner.FileType
|
||||
public class MicrosoftLZ : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -10,27 +10,19 @@ namespace BinaryObjectScanner.FileType
|
||||
public class PAK : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -106,7 +98,7 @@ namespace BinaryObjectScanner.FileType
|
||||
var filename = directoryItem.ItemName;
|
||||
|
||||
// If we have an invalid output directory
|
||||
if (string.IsNullOrWhiteSpace(outputDirectory))
|
||||
if (string.IsNullOrEmpty(outputDirectory))
|
||||
return false;
|
||||
|
||||
// Create the full output path
|
||||
|
||||
@@ -10,27 +10,19 @@ namespace BinaryObjectScanner.FileType
|
||||
public class PFF : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Zip;
|
||||
#endif
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
@@ -12,31 +14,22 @@ namespace BinaryObjectScanner.FileType
|
||||
public class PKZIP : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (stream == null)
|
||||
return null;
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
@@ -49,10 +42,18 @@ namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
// 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 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))
|
||||
@@ -73,6 +74,9 @@ namespace BinaryObjectScanner.FileType
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,27 +11,19 @@ namespace BinaryObjectScanner.FileType
|
||||
public class PLJ : IDetectable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Detect(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Detect(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Detect(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Detect(Stream stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -10,27 +10,19 @@ namespace BinaryObjectScanner.FileType
|
||||
public class Quantum : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -137,7 +129,7 @@ namespace BinaryObjectScanner.FileType
|
||||
// string filename = fileDescriptor.FileName;
|
||||
|
||||
// // If we have an invalid output directory
|
||||
// if (string.IsNullOrWhiteSpace(outputDirectory))
|
||||
// if (string.IsNullOrEmpty(outputDirectory))
|
||||
// return false;
|
||||
|
||||
// // Create the full output path
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Rar;
|
||||
#endif
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
@@ -12,31 +14,22 @@ namespace BinaryObjectScanner.FileType
|
||||
public class RAR : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (stream == null)
|
||||
return null;
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
@@ -49,11 +42,22 @@ namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
// 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)
|
||||
@@ -70,6 +74,9 @@ namespace BinaryObjectScanner.FileType
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
48
BinaryObjectScanner/FileType/RealArcadeInstaller.cs
Normal file
48
BinaryObjectScanner/FileType/RealArcadeInstaller.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
/// <summary>
|
||||
/// RealArcade Installer. Known to use the ".rgs" file extension.
|
||||
///
|
||||
/// TODO: Add further parsing, game ID and name should be possible to parse.
|
||||
/// </summary>
|
||||
public class RealArcadeInstaller : IDetectable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Detect(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Detect(Stream stream, string file, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] magic = new byte[16];
|
||||
stream.Read(magic, 0, 16);
|
||||
|
||||
// RASGI2.0
|
||||
// Found in the ".rgs" files in IA item "Nova_RealArcadeCD_USA".
|
||||
if (magic.StartsWith(new byte?[] { 0x52, 0x41, 0x53, 0x47, 0x49, 0x32, 0x2E, 0x30 }))
|
||||
return "RealArcade Installer";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
48
BinaryObjectScanner/FileType/RealArcadeMezzanine.cs
Normal file
48
BinaryObjectScanner/FileType/RealArcadeMezzanine.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
/// <summary>
|
||||
/// RealArcade Mezzanine files, which contain metadata. Known to use the ".mez" file extension.
|
||||
///
|
||||
/// TODO: Add further parsing, game ID should be possible to parse.
|
||||
/// </summary>
|
||||
public class RealArcadeMezzanine : IDetectable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? Detect(string file, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Detect(Stream stream, string file, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] magic = new byte[16];
|
||||
stream.Read(magic, 0, 16);
|
||||
|
||||
// XZip2.0
|
||||
// Found in the ".mez" files in IA item "Nova_RealArcadeCD_USA".
|
||||
if (magic.StartsWith(new byte?[] { 0x58, 0x5A, 0x69, 0x70, 0x32, 0x2E, 0x30 }))
|
||||
return "RealArcade Mezzanine";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,27 +12,19 @@ namespace BinaryObjectScanner.FileType
|
||||
public class SFFS : IExtractable, IDetectable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Detect(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Detect(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Detect(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Detect(Stream stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -51,27 +43,19 @@ namespace BinaryObjectScanner.FileType
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using ICSharpCode.SharpZipLib.Zip.Compression;
|
||||
using SabreTools.Compression.zlib;
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
@@ -13,27 +13,17 @@ namespace BinaryObjectScanner.FileType
|
||||
public class SGA : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -118,11 +108,7 @@ namespace BinaryObjectScanner.FileType
|
||||
return false;
|
||||
|
||||
// Get the files
|
||||
#if NET48
|
||||
object file;
|
||||
#else
|
||||
object? file;
|
||||
#endif
|
||||
switch (item.Model.Header?.MajorVersion)
|
||||
{
|
||||
case 4: file = (item.Model.Directory as SabreTools.Models.SGA.Directory4)?.Files?[index]; break;
|
||||
@@ -147,27 +133,16 @@ namespace BinaryObjectScanner.FileType
|
||||
}
|
||||
|
||||
// Loop through and get all parent directories
|
||||
#if NET48
|
||||
var parentNames = new List<string> { filename };
|
||||
#else
|
||||
var parentNames = new List<string?> { filename };
|
||||
#endif
|
||||
|
||||
// Get the parent directory
|
||||
var folder = default(object);
|
||||
switch (item.Model.Header?.MajorVersion)
|
||||
{
|
||||
#if NET48
|
||||
case 4: folder = (item.Model.Directory as SabreTools.Models.SGA.Directory4)?.Folders?.FirstOrDefault(f => index >= f.FileStartIndex && index <= f.FileEndIndex); break;
|
||||
case 5: folder = (item.Model.Directory as SabreTools.Models.SGA.Directory5)?.Folders?.FirstOrDefault(f => index >= f.FileStartIndex && index <= f.FileEndIndex); break;
|
||||
case 6: folder = (item.Model.Directory as SabreTools.Models.SGA.Directory6)?.Folders?.FirstOrDefault(f => index >= f.FileStartIndex && index <= f.FileEndIndex); break;
|
||||
case 7: folder = (item.Model.Directory as SabreTools.Models.SGA.Directory7)?.Folders?.FirstOrDefault(f => index >= f.FileStartIndex && index <= f.FileEndIndex); break;
|
||||
#else
|
||||
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;
|
||||
#endif
|
||||
default: return false;
|
||||
}
|
||||
|
||||
@@ -188,7 +163,16 @@ 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 = Path.Combine(filename, parentNamesArray[i]);
|
||||
}
|
||||
#else
|
||||
filename = Path.Combine(parentNames.Cast<string>().ToArray());
|
||||
#endif
|
||||
|
||||
// Get the file offset
|
||||
long fileOffset;
|
||||
@@ -244,15 +228,30 @@ namespace BinaryObjectScanner.FileType
|
||||
}
|
||||
else
|
||||
{
|
||||
// Decompress the data
|
||||
// Inflate the data into the buffer
|
||||
var zstream = new ZLib.z_stream_s();
|
||||
data = new byte[outputFileSize];
|
||||
Inflater inflater = new Inflater();
|
||||
inflater.SetInput(compressedData);
|
||||
inflater.Inflate(data);
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* payloadPtr = compressedData)
|
||||
fixed (byte* dataPtr = data)
|
||||
{
|
||||
zstream.next_in = payloadPtr;
|
||||
zstream.avail_in = (uint)compressedData.Length;
|
||||
zstream.total_in = (uint)compressedData.Length;
|
||||
zstream.next_out = dataPtr;
|
||||
zstream.avail_out = (uint)data.Length;
|
||||
zstream.total_out = 0;
|
||||
|
||||
ZLib.inflateInit_(zstream, ZLib.zlibVersion(), compressedData.Length);
|
||||
int zret = ZLib.inflate(zstream, 1);
|
||||
ZLib.inflateEnd(zstream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we have an invalid output directory
|
||||
if (string.IsNullOrWhiteSpace(outputDirectory))
|
||||
if (string.IsNullOrEmpty(outputDirectory))
|
||||
return false;
|
||||
|
||||
// Create the full output path
|
||||
@@ -267,10 +266,8 @@ namespace BinaryObjectScanner.FileType
|
||||
try
|
||||
{
|
||||
// Open the output file for writing
|
||||
using (Stream fs = File.OpenWrite(filename))
|
||||
{
|
||||
fs.Write(data, 0, data.Length);
|
||||
}
|
||||
using Stream fs = File.OpenWrite(filename);
|
||||
fs.Write(data, 0, data.Length);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.SevenZip;
|
||||
#endif
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
@@ -12,28 +14,22 @@ namespace BinaryObjectScanner.FileType
|
||||
public class SevenZip : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (stream == null)
|
||||
return null;
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
@@ -46,11 +42,22 @@ namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
// 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)
|
||||
@@ -67,6 +74,9 @@ namespace BinaryObjectScanner.FileType
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Tar;
|
||||
#endif
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
@@ -12,31 +14,22 @@ namespace BinaryObjectScanner.FileType
|
||||
public class TapeArchive : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (stream == null)
|
||||
return null;
|
||||
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
@@ -49,11 +42,23 @@ namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
// 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;
|
||||
|
||||
// TODO: Fix bug with extracting folders from tar.
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -70,6 +75,9 @@ namespace BinaryObjectScanner.FileType
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,27 +12,17 @@ namespace BinaryObjectScanner.FileType
|
||||
public class Textfile : IDetectable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Detect(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Detect(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Detect(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Detect(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Detect(Stream stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Files can be protected in multiple ways
|
||||
var protections = new List<string>();
|
||||
@@ -41,7 +31,11 @@ namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
// Load the current file content
|
||||
var fileContent = string.Empty;
|
||||
#if NET20 || NET35 || NET40
|
||||
using (var sr = new StreamReader(stream, Encoding.Default, true, 1024 * 1024))
|
||||
#else
|
||||
using (var sr = new StreamReader(stream, Encoding.Default, true, 1024 * 1024, true))
|
||||
#endif
|
||||
{
|
||||
fileContent = sr.ReadToEnd();
|
||||
}
|
||||
@@ -60,6 +54,28 @@ 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"))
|
||||
protections.Add("CopyKiller V3.62-V3.64");
|
||||
// Found in "autorun.dat" in CopyKiller versions 3.99 and 3.99a.
|
||||
else if (fileContent.Contains("CopyKiller V4 CD / DVD-Protection"))
|
||||
protections.Add("CopyKiller V3.99+");
|
||||
// Found in "engine.wzc" in CopyKiller versions 3.62 and 3.64.
|
||||
else if (fileContent.Contains("CopyKiller V3.6x Protection Engine"))
|
||||
protections.Add("CopyKiller V3.62-V3.64");
|
||||
// Found in "engine.wzc" in CopyKiller versions 3.99 and 3.99a.
|
||||
else if (fileContent.Contains("CopyKiller V3.99x Protection Engine"))
|
||||
protections.Add("CopyKiller V3.99+");
|
||||
|
||||
// Freelock
|
||||
// Found in "FILE_ID.DIZ" distributed with Freelock.
|
||||
if (fileContent.Contains("FREELOCK 1.0"))
|
||||
@@ -92,18 +108,56 @@ 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]".
|
||||
if (fileContent.Contains("Rainbow Sentinel Driver Help"))
|
||||
protections.Add("Rainbow Sentinel");
|
||||
// Found in "\disc4\cad\sdcc_200.zip\DISK1\_USER1.HDR\Language_Independent_Intel_32_Files\SNTNLUSB.INF" in "CICA 32 For Windows CD-ROM (Walnut Creek) (October 1999) (Disc 4).iso" in IA item "CICA_32_For_Windows_CD-ROM_Walnut_Creek_October_1999".
|
||||
if (fileContent.Contains("SNTNLUSB.SvcDesc=\"Rainbow Security Device\""))
|
||||
protections.Add("Rainbow Sentinel USB Driver");
|
||||
if (fileContent.Contains("SntUsb95.SvcDesc=\"Rainbow Security Device\""))
|
||||
protections.Add("Rainbow Sentinel USB Driver");
|
||||
|
||||
// Found in "OEMSETUP.INF" in BA entry "Autodesk AutoCAD LT 98 (1998) (CD) [English] [Dutch]".
|
||||
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.
|
||||
if (fileContent.Contains("<string>com.europevisionmacro.SafeDiscDVD</string>"))
|
||||
{
|
||||
if (fileContent.Contains("<string>2.90.032</string>"))
|
||||
protections.Add("SafeDiscDVD for Macintosh 2.90.032");
|
||||
else
|
||||
protections.Add("SafeDiscDVD for Macintosh (Unknown Version - Please report to us on GitHub)");
|
||||
}
|
||||
|
||||
// Found in "Info.plist" in Redump entry 89649.
|
||||
if (fileContent.Contains("<string>com.macrovisioneurope.SafeDiscLT</string>"))
|
||||
{
|
||||
// TODO: Investigate why "CFBundleGetInfoString" and "CFBundleShortVersionString" say version 2.70.020, but "CFBundleVersion" says version 2.70.010.
|
||||
if (fileContent.Contains("<string>2.70.020</string"))
|
||||
protections.Add("SafeDiscLT for Macintosh 2.70.020");
|
||||
else
|
||||
protections.Add("SafeDiscLT for Macintosh (Unknown Version - Please report to us on GitHub)");
|
||||
}
|
||||
|
||||
|
||||
// The full line from a sample is as follows:
|
||||
//
|
||||
// The files securom_v7_01.dat and securom_v7_01.bak have been created during the installation of a SecuROM protected application.
|
||||
@@ -127,7 +181,7 @@ namespace BinaryObjectScanner.FileType
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return string.Join(";", protections);
|
||||
return string.Join(";", [.. protections]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,27 +10,19 @@ namespace BinaryObjectScanner.FileType
|
||||
public class VBSP : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -115,7 +107,7 @@ namespace BinaryObjectScanner.FileType
|
||||
}
|
||||
|
||||
// If we have an invalid output directory
|
||||
if (string.IsNullOrWhiteSpace(outputDirectory))
|
||||
if (string.IsNullOrEmpty(outputDirectory))
|
||||
return false;
|
||||
|
||||
// Create the full output path
|
||||
|
||||
@@ -2,7 +2,7 @@ using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.IO;
|
||||
using SabreTools.IO.Extensions;
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
@@ -12,27 +12,19 @@ namespace BinaryObjectScanner.FileType
|
||||
public class VPK : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -120,7 +112,7 @@ namespace BinaryObjectScanner.FileType
|
||||
|
||||
// Get the archive filename
|
||||
string archiveFileName = item.ArchiveFilenames[directoryItem.DirectoryEntry.ArchiveIndex];
|
||||
if (string.IsNullOrWhiteSpace(archiveFileName))
|
||||
if (string.IsNullOrEmpty(archiveFileName))
|
||||
return false;
|
||||
|
||||
// If the archive doesn't exist
|
||||
@@ -132,7 +124,7 @@ namespace BinaryObjectScanner.FileType
|
||||
try
|
||||
{
|
||||
// Open the archive
|
||||
archiveStream = File.OpenRead(archiveFileName);
|
||||
archiveStream = File.Open(archiveFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
|
||||
// Seek to the data
|
||||
archiveStream.Seek(directoryItem.DirectoryEntry.EntryOffset, SeekOrigin.Begin);
|
||||
@@ -160,11 +152,11 @@ namespace BinaryObjectScanner.FileType
|
||||
|
||||
// Create the filename
|
||||
string filename = $"{directoryItem.Name}.{directoryItem.Extension}";
|
||||
if (!string.IsNullOrWhiteSpace(directoryItem.Path))
|
||||
if (!string.IsNullOrEmpty(directoryItem.Path))
|
||||
filename = Path.Combine(directoryItem.Path, filename);
|
||||
|
||||
// If we have an invalid output directory
|
||||
if (string.IsNullOrWhiteSpace(outputDirectory))
|
||||
if (string.IsNullOrEmpty(outputDirectory))
|
||||
return false;
|
||||
|
||||
// Create the full output path
|
||||
|
||||
@@ -10,27 +10,19 @@ namespace BinaryObjectScanner.FileType
|
||||
public class WAD : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -106,7 +98,7 @@ namespace BinaryObjectScanner.FileType
|
||||
string filename = $"{lump.Name}.lmp";
|
||||
|
||||
// If we have an invalid output directory
|
||||
if (string.IsNullOrWhiteSpace(outputDirectory))
|
||||
if (string.IsNullOrEmpty(outputDirectory))
|
||||
return false;
|
||||
|
||||
// Create the full output path
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Compressors.Xz;
|
||||
#endif
|
||||
|
||||
namespace BinaryObjectScanner.FileType
|
||||
{
|
||||
@@ -11,28 +13,19 @@ namespace BinaryObjectScanner.FileType
|
||||
public class XZ : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
// Create a temp output directory
|
||||
@@ -55,6 +48,9 @@ namespace BinaryObjectScanner.FileType
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,27 +11,19 @@ namespace BinaryObjectScanner.FileType
|
||||
public class XZP : IExtractable
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -116,7 +108,7 @@ namespace BinaryObjectScanner.FileType
|
||||
var filename = directoryItem.Name;
|
||||
|
||||
// If we have an invalid output directory
|
||||
if (string.IsNullOrWhiteSpace(outputDirectory))
|
||||
if (string.IsNullOrEmpty(outputDirectory))
|
||||
return false;
|
||||
|
||||
// Create the full output path
|
||||
|
||||
@@ -18,11 +18,7 @@ namespace BinaryObjectScanner.GameEngine
|
||||
public class RenderWare : IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace BinaryObjectScanner.GameEngine
|
||||
{
|
||||
/// <summary>
|
||||
/// This class exists for reflection purposes and should not be used
|
||||
/// </summary>
|
||||
public sealed class _DUMMY { }
|
||||
}
|
||||
@@ -1,13 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Utilities;
|
||||
using static BinaryObjectScanner.Utilities.Dictionary;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner
|
||||
{
|
||||
@@ -18,17 +15,11 @@ namespace BinaryObjectScanner
|
||||
/// <summary>
|
||||
/// Cache for all IPathCheck types
|
||||
/// </summary>
|
||||
#if NET48
|
||||
public static IEnumerable<IPathCheck> PathCheckClasses
|
||||
#else
|
||||
public static IEnumerable<IPathCheck?> PathCheckClasses
|
||||
#endif
|
||||
{
|
||||
get
|
||||
{
|
||||
if (pathCheckClasses == null)
|
||||
pathCheckClasses = InitCheckClasses<IPathCheck>();
|
||||
|
||||
pathCheckClasses ??= InitCheckClasses<IPathCheck>();
|
||||
return pathCheckClasses;
|
||||
}
|
||||
}
|
||||
@@ -40,11 +31,7 @@ namespace BinaryObjectScanner
|
||||
/// <summary>
|
||||
/// Cache for all IPathCheck types
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private static IEnumerable<IPathCheck> pathCheckClasses;
|
||||
#else
|
||||
private static IEnumerable<IPathCheck?>? pathCheckClasses;
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -56,24 +43,20 @@ namespace BinaryObjectScanner
|
||||
/// <param name="path">Path of the file or directory to check</param>
|
||||
/// <param name="scanner">Scanner object to use for options and scanning</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
#if NET48
|
||||
public static ConcurrentDictionary<string, ConcurrentQueue<string>> HandlePathChecks(string path, IEnumerable<string> files)
|
||||
#else
|
||||
public static ConcurrentDictionary<string, ConcurrentQueue<string>> HandlePathChecks(string path, IEnumerable<string>? files)
|
||||
#endif
|
||||
public static ProtectionDictionary HandlePathChecks(string path, IEnumerable<string>? files)
|
||||
{
|
||||
// Create the output dictionary
|
||||
var protections = new ConcurrentDictionary<string, ConcurrentQueue<string>>();
|
||||
var protections = new ProtectionDictionary();
|
||||
|
||||
// Preprocess the list of files
|
||||
files = files?.Select(f => f.Replace('\\', '/'))?.ToList();
|
||||
files = files?.Select(f => f.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar))?.ToList();
|
||||
|
||||
// Iterate through all checks
|
||||
Parallel.ForEach(PathCheckClasses, checkClass =>
|
||||
PathCheckClasses.IterateWithAction(checkClass =>
|
||||
{
|
||||
var subProtections = checkClass?.PerformCheck(path, files);
|
||||
if (subProtections != null)
|
||||
AppendToDictionary(protections, path, subProtections);
|
||||
protections.Append(path, subProtections);
|
||||
});
|
||||
|
||||
return protections;
|
||||
@@ -91,11 +74,7 @@ namespace BinaryObjectScanner
|
||||
/// <param name="stream">Stream to scan the contents of</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Set of protections in file, null on error</returns>
|
||||
#if NET48
|
||||
public static ConcurrentQueue<string> HandleDetectable(IDetectable impl, string fileName, Stream stream, bool includeDebug)
|
||||
#else
|
||||
public static ConcurrentQueue<string>? HandleDetectable(IDetectable impl, string fileName, Stream stream, bool includeDebug)
|
||||
#endif
|
||||
public static List<string>? HandleDetectable(IDetectable impl, string fileName, Stream stream, bool includeDebug)
|
||||
{
|
||||
var protection = impl.Detect(stream, fileName, includeDebug);
|
||||
return ProcessProtectionString(protection);
|
||||
@@ -104,16 +83,12 @@ namespace BinaryObjectScanner
|
||||
/// <summary>
|
||||
/// Handle files based on an IExtractable implementation
|
||||
/// </summary>
|
||||
/// <param name="impl">IDetectable class representing the file type</param>
|
||||
/// <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 NET48
|
||||
public static ConcurrentDictionary<string, ConcurrentQueue<string>> HandleExtractable(IExtractable impl, string fileName, Stream stream, Scanner scanner)
|
||||
#else
|
||||
public static ConcurrentDictionary<string, ConcurrentQueue<string>>? HandleExtractable(IExtractable impl, string fileName, Stream? stream, Scanner scanner)
|
||||
#endif
|
||||
public static ProtectionDictionary? HandleExtractable(IExtractable impl, string fileName, Stream? stream, Scanner scanner)
|
||||
{
|
||||
// If the extractable file itself fails
|
||||
try
|
||||
@@ -137,8 +112,184 @@ namespace BinaryObjectScanner
|
||||
}
|
||||
|
||||
// Prepare the returned protections
|
||||
StripFromKeys(subProtections, tempPath);
|
||||
PrependToKeys(subProtections, fileName);
|
||||
subProtections?.StripFromKeys(tempPath);
|
||||
subProtections?.PrependToKeys(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>
|
||||
public static ProtectionDictionary? HandleExtractable(IExtractableMSDOSExecutable impl, string fileName, MSDOS mz, Scanner scanner)
|
||||
{
|
||||
// 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
|
||||
subProtections?.StripFromKeys(tempPath);
|
||||
subProtections?.PrependToKeys(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>
|
||||
public static ProtectionDictionary? HandleExtractable(IExtractableLinearExecutable impl, string fileName, LinearExecutable lex, Scanner scanner)
|
||||
{
|
||||
// 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
|
||||
subProtections?.StripFromKeys(tempPath);
|
||||
subProtections?.PrependToKeys(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>
|
||||
public static ProtectionDictionary? HandleExtractable(IExtractableNewExecutable impl, string fileName, NewExecutable nex, Scanner scanner)
|
||||
{
|
||||
// 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
|
||||
subProtections?.StripFromKeys(tempPath);
|
||||
subProtections?.PrependToKeys(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>
|
||||
public static ProtectionDictionary? HandleExtractable(IExtractablePortableExecutable impl, string fileName, PortableExecutable pex, Scanner scanner)
|
||||
{
|
||||
// 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
|
||||
subProtections?.StripFromKeys(tempPath);
|
||||
subProtections?.PrependToKeys(fileName);
|
||||
return subProtections;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -155,23 +306,19 @@ namespace BinaryObjectScanner
|
||||
/// <param name="impl">IPathCheck class representing the file type</param>
|
||||
/// <param name="path">Path of the file or directory to check</param>
|
||||
/// <returns>Set of protections in path, null on error</returns>
|
||||
#if NET48
|
||||
private static ConcurrentQueue<string> PerformCheck(this IPathCheck impl, string path, IEnumerable<string> files)
|
||||
#else
|
||||
private static ConcurrentQueue<string>? PerformCheck(this IPathCheck impl, string? path, IEnumerable<string>? files)
|
||||
#endif
|
||||
private static List<string>? PerformCheck(this IPathCheck impl, string? path, IEnumerable<string>? files)
|
||||
{
|
||||
// If we have an invalid path
|
||||
if (string.IsNullOrWhiteSpace(path))
|
||||
if (string.IsNullOrEmpty(path))
|
||||
return null;
|
||||
|
||||
// Setup the output dictionary
|
||||
var protections = new ConcurrentQueue<string>();
|
||||
// Setup the list
|
||||
var protections = new List<string>();
|
||||
|
||||
// If we have a file path
|
||||
if (File.Exists(path))
|
||||
{
|
||||
var protection = impl.CheckFilePath(path);
|
||||
var protection = impl.CheckFilePath(path!);
|
||||
var subProtections = ProcessProtectionString(protection);
|
||||
if (subProtections != null)
|
||||
protections.AddRange(subProtections);
|
||||
@@ -180,7 +327,7 @@ namespace BinaryObjectScanner
|
||||
// If we have a directory path
|
||||
if (Directory.Exists(path) && files?.Any() == true)
|
||||
{
|
||||
var subProtections = impl.CheckDirectoryPath(path, files);
|
||||
var subProtections = impl.CheckDirectoryPath(path!, files);
|
||||
if (subProtections != null)
|
||||
protections.AddRange(subProtections);
|
||||
}
|
||||
@@ -195,33 +342,41 @@ namespace BinaryObjectScanner
|
||||
/// <summary>
|
||||
/// Initialize all implementations of a type
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private static IEnumerable<T> InitCheckClasses<T>()
|
||||
#else
|
||||
private static IEnumerable<T?> InitCheckClasses<T>()
|
||||
#endif
|
||||
{
|
||||
return InitCheckClasses<T>(typeof(GameEngine._DUMMY).Assembly)
|
||||
.Concat(InitCheckClasses<T>(typeof(Packer._DUMMY).Assembly))
|
||||
.Concat(InitCheckClasses<T>(typeof(Protection._DUMMY).Assembly));
|
||||
}
|
||||
private static IEnumerable<T?> InitCheckClasses<T>() =>
|
||||
InitCheckClasses<T>(Assembly.GetExecutingAssembly());
|
||||
|
||||
/// <summary>
|
||||
/// Initialize all implementations of a type
|
||||
/// </summary>
|
||||
#if NET48
|
||||
private static IEnumerable<T> InitCheckClasses<T>(Assembly assembly)
|
||||
#else
|
||||
private static IEnumerable<T?> InitCheckClasses<T>(Assembly assembly)
|
||||
#endif
|
||||
{
|
||||
return assembly.GetTypes()?
|
||||
.Where(t => t.IsClass && t.GetInterface(typeof(T).Name) != null)?
|
||||
#if NET48
|
||||
.Select(t => (T)Activator.CreateInstance(t)) ?? Array.Empty<T>();
|
||||
#else
|
||||
.Select(t => (T?)Activator.CreateInstance(t)) ?? Array.Empty<T>();
|
||||
#endif
|
||||
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
|
||||
@@ -233,28 +388,24 @@ namespace BinaryObjectScanner
|
||||
/// </summary>
|
||||
/// <param name="protection">Protection string to process</param>
|
||||
/// <returns>Set of protections parsed, null on error</returns>
|
||||
#if NET48
|
||||
private static ConcurrentQueue<string> ProcessProtectionString(string protection)
|
||||
#else
|
||||
private static ConcurrentQueue<string>? ProcessProtectionString(string? protection)
|
||||
#endif
|
||||
private static List<string>? ProcessProtectionString(string? protection)
|
||||
{
|
||||
// If we have an invalid protection string
|
||||
if (string.IsNullOrWhiteSpace(protection))
|
||||
if (string.IsNullOrEmpty(protection))
|
||||
return null;
|
||||
|
||||
// Setup the output queue
|
||||
var protections = new ConcurrentQueue<string>();
|
||||
var protections = new List<string>();
|
||||
|
||||
// If we have an indicator of multiple protections
|
||||
if (protection.Contains(";"))
|
||||
if (protection!.Contains(";"))
|
||||
{
|
||||
var splitProtections = protection.Split(';');
|
||||
protections.AddRange(splitProtections);
|
||||
}
|
||||
else
|
||||
{
|
||||
protections.Enqueue(protection);
|
||||
protections.Add(protection);
|
||||
}
|
||||
|
||||
return protections;
|
||||
|
||||
@@ -12,10 +12,6 @@
|
||||
/// <param name="fileContent">Byte array representing the file contents</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>String containing any protections found in the file</returns>
|
||||
#if NET48
|
||||
string CheckContents(string file, byte[] fileContent, bool includeDebug);
|
||||
#else
|
||||
string? CheckContents(string file, byte[] fileContent, bool includeDebug);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,7 @@ namespace BinaryObjectScanner.Interfaces
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Detected file or protection type, null on error</returns>
|
||||
/// <remarks>Ideally, this should just point to the other detect implementation.</remarks>
|
||||
#if NET48
|
||||
string Detect(string file, bool includeDebug);
|
||||
#else
|
||||
string? Detect(string file, bool includeDebug);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Check if a stream is detected as this file type
|
||||
@@ -27,10 +23,6 @@ namespace BinaryObjectScanner.Interfaces
|
||||
/// <param name="file">Path to the input file</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Detected file or protection type, null on error</returns>
|
||||
#if NET48
|
||||
string Detect(Stream stream, string file, bool includeDebug);
|
||||
#else
|
||||
string? Detect(Stream stream, string file, bool includeDebug);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,7 @@ namespace BinaryObjectScanner.Interfaces
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Path to extracted files, null on error</returns>
|
||||
/// <remarks>Ideally, this should just point to the other extract implementation.</remarks>
|
||||
#if NET48
|
||||
string Extract(string file, bool includeDebug);
|
||||
#else
|
||||
string? Extract(string file, bool includeDebug);
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Extract a stream to a temporary path, if possible
|
||||
@@ -29,10 +25,6 @@ namespace BinaryObjectScanner.Interfaces
|
||||
/// <param name="file">Path to the input file</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>Path to extracted files, null on error</returns>
|
||||
#if NET48
|
||||
string Extract(Stream stream, string file, bool includeDebug);
|
||||
#else
|
||||
string? Extract(Stream? stream, string file, bool includeDebug);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
19
BinaryObjectScanner/Interfaces/IExtractableNewExecutable.cs
Normal file
19
BinaryObjectScanner/Interfaces/IExtractableNewExecutable.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -14,10 +14,6 @@ namespace BinaryObjectScanner.Interfaces
|
||||
/// <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>
|
||||
#if NET48
|
||||
string CheckLinearExecutable(string file, LinearExecutable lex, bool includeDebug);
|
||||
#else
|
||||
string? CheckLinearExecutable(string file, LinearExecutable lex, bool includeDebug);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,6 @@ namespace BinaryObjectScanner.Interfaces
|
||||
/// <param name="mz">MSDOS 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>
|
||||
#if NET48
|
||||
string CheckMSDOSExecutable(string file, MSDOS mz, bool includeDebug);
|
||||
#else
|
||||
string? CheckMSDOSExecutable(string file, MSDOS mz, bool includeDebug);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,6 @@ namespace BinaryObjectScanner.Interfaces
|
||||
/// <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>
|
||||
#if NET48
|
||||
string CheckNewExecutable(string file, NewExecutable nex, bool includeDebug);
|
||||
#else
|
||||
string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BinaryObjectScanner.Interfaces
|
||||
{
|
||||
@@ -17,21 +16,13 @@ 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 NET48
|
||||
ConcurrentQueue<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
|
||||
/// </summary>
|
||||
/// <param name="path">Path to check for protection indicators</param>
|
||||
/// <remarks>This can do some limited content checking as well, but it's suggested to use a content check instead, if possible</remarks>
|
||||
#if NET48
|
||||
string CheckFilePath(string path);
|
||||
#else
|
||||
string? CheckFilePath(string path);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,6 @@ namespace BinaryObjectScanner.Interfaces
|
||||
/// <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>
|
||||
#if NET48
|
||||
string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug);
|
||||
#else
|
||||
string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,17 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
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 : IExtractable, IPortableExecutableCheck
|
||||
public class ASPack : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -33,7 +29,7 @@ namespace BinaryObjectScanner.Packer
|
||||
// {
|
||||
// var matchers = GenerateMatchers();
|
||||
// var match = MatchUtil.GetFirstMatch(file, pex.EntryPointRaw, matchers, includeDebug);
|
||||
// if (!string.IsNullOrWhiteSpace(match))
|
||||
// if (!string.IsNullOrEmpty(match))
|
||||
// return match;
|
||||
// }
|
||||
|
||||
@@ -46,7 +42,7 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
var matchers = GenerateMatchers();
|
||||
var match = MatchUtil.GetFirstMatch(file, adataSectionRaw, matchers, includeDebug);
|
||||
if (!string.IsNullOrWhiteSpace(match))
|
||||
if (!string.IsNullOrEmpty(match))
|
||||
return match;
|
||||
}
|
||||
}
|
||||
@@ -55,27 +51,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -90,7 +66,7 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
#region No Wildcards (Long)
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x92, 0x1A, 0x44, 0x00, 0xB8, 0x8C, 0x1A,
|
||||
@@ -99,7 +75,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x80, 0xBD, 0xC4, 0x1D, 0x44,
|
||||
}, "ASPack 1.00b -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0xD2, 0x2A, 0x44, 0x00, 0xB8, 0xCC, 0x2A,
|
||||
@@ -113,7 +89,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x44, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
|
||||
}, "ASPack 1.01b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0xD2, 0x2A, 0x44, 0x00, 0xB8, 0xCC, 0x2A,
|
||||
@@ -122,7 +98,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x80, 0xBD, 0x9C, 0x2E, 0x44
|
||||
}, "ASPack 1.01b -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x96, 0x78, 0x43, 0x00, 0xB8, 0x90, 0x78,
|
||||
@@ -136,7 +112,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x43, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
|
||||
}, "ASPack 1.02b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x96, 0x78, 0x43, 0x00, 0xB8, 0x90, 0x78,
|
||||
@@ -146,7 +122,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x15, 0xFE, 0x85, 0x74, 0x7C, 0x43
|
||||
}, "ASPack 1.02b -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x8A, 0x1C, 0x40, 0x00, 0xB9, 0x9E, 0x00,
|
||||
@@ -154,14 +130,14 @@ namespace BinaryObjectScanner.Packer
|
||||
0x8B, 0xF7, 0x33
|
||||
}, "ASPack 1.02b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x96, 0x78, 0x43, 0x00, 0xB8, 0x90, 0x78,
|
||||
0x43, 0x00, 0x03, 0xC5
|
||||
}, "ASPack 1.02b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0xAE, 0x98, 0x43, 0x00, 0xB8, 0xA8, 0x98,
|
||||
@@ -170,7 +146,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x80, 0xBD, 0x0E, 0x9D, 0x43
|
||||
}, "ASPack 1.03b -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0xCE, 0x3A, 0x44, 0x00, 0xB8, 0xC8, 0x3A,
|
||||
@@ -179,7 +155,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x80, 0xBD, 0xAC, 0x3E, 0x44
|
||||
}, "ASPack 1.05b -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0xEA, 0xA8, 0x43, 0x00, 0xB8, 0xE4, 0xA8,
|
||||
@@ -193,7 +169,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x43, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
|
||||
}, "ASPack 1.06.01b (DLL)"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0xEA, 0xA8, 0x43, 0x00, 0xB8, 0xE4, 0xA8,
|
||||
@@ -203,7 +179,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x15, 0xFE, 0x85, 0x6E, 0xAD, 0x43
|
||||
}, "ASPack 1.06.01b -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x3E, 0xD9, 0x43, 0x00, 0xB8, 0x38, 0xD9,
|
||||
@@ -217,7 +193,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x43, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
|
||||
}, "ASPack 1.07b (DLL)"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xEB, 0x03, 0x5D, 0xFF, 0xE5, 0xE8, 0xF8,
|
||||
0xFF, 0xFF, 0xFF, 0x81, 0xED, 0x1B, 0x6A, 0x44,
|
||||
@@ -225,7 +201,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x2B, 0x9D, 0x2A
|
||||
}, "ASPack 1.08"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x0A, 0x4A, 0x44, 0x00, 0xBB, 0x04, 0x4A,
|
||||
@@ -239,7 +215,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x53, 0x50, 0xFF, 0x95, 0x90, 0x51, 0x44, 0x00
|
||||
}, "ASPack 1.08.03"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x0A, 0x4A, 0x44, 0x00, 0xBB, 0x04, 0x4A,
|
||||
@@ -248,20 +224,20 @@ namespace BinaryObjectScanner.Packer
|
||||
0x00, 0x89, 0x9D, 0xBB, 0x4E
|
||||
}, "ASPack 1.08.03"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x0A, 0x4A, 0x44, 0x00, 0xBB, 0x04, 0x4A,
|
||||
0x44, 0x00, 0x03, 0xDD
|
||||
}, "ASPack 1.08.03"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x72, 0x05, 0x00, 0x00, 0xEB, 0x33,
|
||||
0x87, 0xDB, 0x90, 0x00
|
||||
}, "ASPack 2.00.01"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9, 0xEB,
|
||||
0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01, 0x00,
|
||||
@@ -269,34 +245,34 @@ namespace BinaryObjectScanner.Packer
|
||||
0xFF, 0x03, 0xDD, 0x81, 0xEB
|
||||
}, "ASPack 2.1"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xEB, 0x09,
|
||||
0x5D, 0x55, 0x81, 0xED, 0x39, 0x39, 0x44, 0x00,
|
||||
0xC3, 0xE9, 0x3D, 0x04, 0x00, 0x00
|
||||
}, "ASPack 2.11b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xEB, 0x09,
|
||||
0x5D, 0x55
|
||||
}, "ASPack 2.11b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xEB, 0x09,
|
||||
0x5D, 0x55, 0x81, 0xED, 0x39, 0x39, 0x44, 0x00,
|
||||
0xC3, 0xE9, 0x59, 0x04, 0x00, 0x00
|
||||
}, "ASPack 2.11c"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xCD, 0x20,
|
||||
0xE8, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x2B, 0xC9,
|
||||
0x58, 0x74, 0x02
|
||||
}, "ASPack 2.11d"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9, 0xEB,
|
||||
0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01
|
||||
@@ -306,7 +282,7 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
#region Wildcards (Long)
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, 0x3E, 0xD9, 0x43, null, 0xB8, 0x38, null,
|
||||
@@ -320,7 +296,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x43, null, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
|
||||
}, "ASPack 1.00b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, 0xD2, 0x2A, 0x44, null, 0xB8, 0xCC, 0x2A,
|
||||
@@ -329,7 +305,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x80, 0xBD, 0x9C, 0x2E, 0x44
|
||||
}, "ASPack 1.01b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, 0xCE, 0x3A, 0x44, null, 0xB8, 0xC8, 0x3A,
|
||||
@@ -338,7 +314,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x80, 0xBD, 0xAC, 0x3E, 0x44
|
||||
}, "ASPack 1.01b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, 0x3E, 0xD9, 0x43, 0x00, 0xB8, 0x38, null,
|
||||
@@ -352,13 +328,13 @@ namespace BinaryObjectScanner.Packer
|
||||
0x43, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
|
||||
}, "ASPack 1.02a -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, 0x06, null, null, null, 0x64, 0xA0, 0x23
|
||||
}, "ASPack 1.02a"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, 0x96, 0x78, 0x43, null, 0xB8, 0x90, 0x78,
|
||||
@@ -367,7 +343,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x80, 0xBD, 0x74, 0x7C, 0x43
|
||||
}, "ASPack 1.02b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, 0xAE, 0x98, 0x43, null, 0xB8, 0xA8, 0x98,
|
||||
@@ -376,7 +352,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x80, 0xBD, 0x0E, 0x9D, 0x43
|
||||
}, "ASPack 1.03b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, null, null, null, null, 0xE8, 0x0D, null,
|
||||
@@ -384,7 +360,7 @@ namespace BinaryObjectScanner.Packer
|
||||
null, null, null, null, null, null, null, 0x58
|
||||
}, "ASPack 1.03b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
|
||||
0xED, null, null, null, 0x00, 0xB8, null, null,
|
||||
@@ -393,7 +369,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x80, 0xBD, 0x08, 0x9D, null, 0x00, 0x00
|
||||
}, "ASPack 1.04b -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, null, null, null, null, 0xB8, null, null,
|
||||
@@ -402,7 +378,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x80, 0xBD, 0x08, 0x9D
|
||||
}, "ASPack 1.04b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, null, null, null, null, 0xB8, null, null,
|
||||
@@ -411,7 +387,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x80, 0xBD, 0x01, 0xDE
|
||||
}, "ASPack 1.04b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, 0xEA, 0xA8, 0x43, null, 0xB8, 0xE4, 0xA8,
|
||||
@@ -420,28 +396,28 @@ namespace BinaryObjectScanner.Packer
|
||||
0x80, 0xBD, 0x6E, 0xAD, 0x43
|
||||
}, "ASPack 1.06.1b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x90, 0x61, 0xBE, null, null, null, null, 0x8D,
|
||||
0xBE, null, null, null, null, 0x57, 0x83, 0xCD,
|
||||
0xFF
|
||||
}, "ASPack 1.06.1b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, null,
|
||||
null, null, null, null, null, 0xB8, null, null,
|
||||
null, null, 0x03, 0xC5
|
||||
}, "ASPack 1.07b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
|
||||
0xED, null, null, null, null, 0x60, 0xE8, 0x2B,
|
||||
0x03, 0x00, 0x00
|
||||
}, "ASPack 1.07b"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xEB, 0x0A, 0x5D, 0xEB, 0x02, 0xFF, 0x25,
|
||||
0x45, 0xFF, 0xE5, 0xE8, 0xE9, 0xE8, 0xF1, 0xFF,
|
||||
@@ -450,7 +426,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x2B, 0x9D
|
||||
}, "ASPack 1.08.01"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xEB, 0x0A, 0x5D, 0xEB, 0x02, 0xFF, 0x25,
|
||||
0x45, 0xFF, 0xE5, 0xE8, 0xE9, 0xE8, 0xF1, 0xFF,
|
||||
@@ -459,7 +435,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x2B, 0x9D
|
||||
}, "ASPack 1.08.01"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xEB, 0x0A, 0x5D, 0xEB, 0x02, 0xFF, 0x25,
|
||||
0x45, 0xFF, 0xE5, 0xE8, 0xE9, 0xE8, 0xF1, 0xFF,
|
||||
@@ -468,7 +444,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x2B, 0x9D, 0x72
|
||||
}, "ASPack 1.08.02"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, null,
|
||||
null, null, null, null, null, 0xBB, null, null,
|
||||
@@ -477,14 +453,14 @@ namespace BinaryObjectScanner.Packer
|
||||
0x00, 0x89, 0x9D, 0xBB, 0x4E
|
||||
}, "ASPack 1.08.03"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, null,
|
||||
null, null, null, null, null, 0xBB, null, null,
|
||||
null, null, 0x03, 0xDD
|
||||
}, "ASPack 1.08.03"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x55, 0x57, 0x51, 0x53, 0xE8, null, null, null,
|
||||
null, 0x5D, 0x8B, 0xC5, 0x81, 0xED, null, null,
|
||||
@@ -493,27 +469,27 @@ namespace BinaryObjectScanner.Packer
|
||||
null, 0x0F, 0xB6
|
||||
}, "ASPack 1.08.03"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE9, null, null, null, null, 0xEF, 0x40,
|
||||
0x03, 0xA7, 0x07, 0x8F, 0x07, 0x1C, 0x37, 0x5D,
|
||||
0x43, 0xA7, 0x04, 0xB9, 0x2C, 0x3A
|
||||
}, "ASPack 1.08.x"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xEB, 0x09,
|
||||
0x5D, 0x55, 0x81, 0xED, 0x39, 0x39, 0x44, 0x00,
|
||||
0xC3, 0xE9, null, 0x04, 0x00, 0x00
|
||||
}, "ASPack 2.11.x -> Alexey Solodovnikov"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
null, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9, 0xEB,
|
||||
0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01
|
||||
}, "ASPack 2.12 (without Poly) -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
null, 0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9,
|
||||
0xEB, 0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01,
|
||||
@@ -530,7 +506,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0xFF, 0x95, 0x48, 0x0F
|
||||
}, "ASPack 2.12b -> Solodovnikov Alexey"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9, 0xEB,
|
||||
0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01, 0x00,
|
||||
@@ -579,7 +555,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x08
|
||||
}, "ASPack 2.2 -> Alexey Solodovnikov & StarForce * 2009408"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
null, 0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9,
|
||||
0xEB, 0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01,
|
||||
@@ -592,7 +568,7 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
#region 2.xx (Long)
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0xA8, 0x03, 0x00, 0x00, 0x61, 0x75, 0x08, 0xB8,
|
||||
0x01, 0x00, 0x00, 0x00, 0xC2, 0x0C, 0x00, 0x68,
|
||||
@@ -601,7 +577,7 @@ namespace BinaryObjectScanner.Packer
|
||||
0x00, 0x51, 0x50, 0xFF, 0x95
|
||||
}, "ASPack 2.xx"),
|
||||
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0xA8, 0x03, null, null, 0x61, 0x75, 0x08, 0xB8,
|
||||
0x01, null, null, null, 0xC2, 0x0C, null, 0x68,
|
||||
@@ -614,55 +590,55 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
#region Short
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x75, 0x00, 0xE9 }, "ASPack 1.05b"),
|
||||
new(new byte?[] { 0x75, 0x00, 0xE9 }, "ASPack 1.05b"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x90, 0x75, 0x00, 0xE9 }, "ASPack 1.06.1b"),
|
||||
new(new byte?[] { 0x90, 0x90, 0x90, 0x75, 0x00, 0xE9 }, "ASPack 1.06.1b"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x75, 0x00, 0xE9 }, "ASPack 1.06.1b"),
|
||||
new(new byte?[] { 0x90, 0x90, 0x75, 0x00, 0xE9 }, "ASPack 1.06.1b"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x75, 0x00, 0xE9 }, "ASPack 1.06.1b"),
|
||||
new(new byte?[] { 0x90, 0x75, 0x00, 0xE9 }, "ASPack 1.06.1b"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x90, 0x75, null, 0xE9 }, "ASPack 1.07b"),
|
||||
new(new byte?[] { 0x90, 0x90, 0x90, 0x75, null, 0xE9 }, "ASPack 1.07b"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x75, null, 0xE9 }, "ASPack 1.07b"),
|
||||
new(new byte?[] { 0x90, 0x90, 0x75, null, 0xE9 }, "ASPack 1.07b"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x75, null, 0xE9 }, "ASPack 1.07b"),
|
||||
new(new byte?[] { 0x90, 0x75, null, 0xE9 }, "ASPack 1.07b"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x90, 0x75, 0x01, 0x90, 0xE9 }, "ASPack 1.08"),
|
||||
new(new byte?[] { 0x90, 0x90, 0x90, 0x75, 0x01, 0x90, 0xE9 }, "ASPack 1.08"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x90, 0x75, 0x01, 0xFF, 0xE9 }, "ASPack 1.08"),
|
||||
new(new byte?[] { 0x90, 0x90, 0x90, 0x75, 0x01, 0xFF, 0xE9 }, "ASPack 1.08"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x75, 0x01, 0xFF, 0xE9 }, "ASPack 1.08"),
|
||||
new(new byte?[] { 0x90, 0x90, 0x75, 0x01, 0xFF, 0xE9 }, "ASPack 1.08"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x75, 0x01, 0xFF, 0xE9 }, "ASPack 1.08"),
|
||||
new(new byte?[] { 0x90, 0x75, 0x01, 0xFF, 0xE9 }, "ASPack 1.08"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x90, 0x75, null, 0x90, 0xE9 }, "ASPack 1.08.01"),
|
||||
new(new byte?[] { 0x90, 0x90, 0x90, 0x75, null, 0x90, 0xE9 }, "ASPack 1.08.01"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x75, null, 0x90, 0xE9 }, "ASPack 1.08.01"),
|
||||
new(new byte?[] { 0x90, 0x90, 0x75, null, 0x90, 0xE9 }, "ASPack 1.08.01"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x75, null, 0x90, 0xE9 }, "ASPack 1.08.01"),
|
||||
new(new byte?[] { 0x90, 0x75, null, 0x90, 0xE9 }, "ASPack 1.08.01"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x75, 0x01, 0x90, 0xE9 }, "ASPack 1.08.02"),
|
||||
new(new byte?[] { 0x90, 0x90, 0x75, 0x01, 0x90, 0xE9 }, "ASPack 1.08.02"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x90, 0x75, 0x01, 0x90, 0xE9 }, "ASPack 1.08.02"),
|
||||
new(new byte?[] { 0x90, 0x75, 0x01, 0x90, 0xE9 }, "ASPack 1.08.02"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x60, 0xE8, 0x41, 0x06, 0x00, 0x00, 0xEB, 0x41 }, "ASPack 1.08.04"),
|
||||
new(new byte?[] { 0x60, 0xE8, 0x41, 0x06, 0x00, 0x00, 0xEB, 0x41 }, "ASPack 1.08.04"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x60, 0xE8, null, null, null, null, 0xEB }, "ASPack 1.08.04"),
|
||||
new(new byte?[] { 0x60, 0xE8, null, null, null, null, 0xEB }, "ASPack 1.08.04"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x60, 0xE8, 0x70, 0x05, 0x00, 0x00, 0xEB, 0x4C }, "ASPack 2.00.00"),
|
||||
new(new byte?[] { 0x60, 0xE8, 0x70, 0x05, 0x00, 0x00, 0xEB, 0x4C }, "ASPack 2.00.00"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x60, 0xE8, 0x48, 0x11, 0x00, 0x00, 0xC3, 0x83 }, "ASPack 2.00.00"),
|
||||
new(new byte?[] { 0x60, 0xE8, 0x48, 0x11, 0x00, 0x00, 0xC3, 0x83 }, "ASPack 2.00.00"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x60, 0xE8, 0x72, 0x05, 0x00, 0x00, 0xEB, 0x4C }, "ASPack 2.00.01"),
|
||||
new(new byte?[] { 0x60, 0xE8, 0x72, 0x05, 0x00, 0x00, 0xEB, 0x4C }, "ASPack 2.00.01"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x60, 0xE8, null, 0x05, 0x00, 0x00, 0xEB, 0x4C }, "ASPack 2.00.x -> Alexey Solodovnikov"),
|
||||
new(new byte?[] { 0x60, 0xE8, null, 0x05, 0x00, 0x00, 0xEB, 0x4C }, "ASPack 2.00.x -> Alexey Solodovnikov"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x60, 0xE9, 0x3D, 0x04, 0x00, 0x00 }, "ASPack 2.11"),
|
||||
new(new byte?[] { 0x60, 0xE9, 0x3D, 0x04, 0x00, 0x00 }, "ASPack 2.11"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x60, 0xE8, 0xF9, 0x11, 0x00, 0x00, 0xC3, 0x83 }, "ASPack 2.11"),
|
||||
new(new byte?[] { 0x60, 0xE8, 0xF9, 0x11, 0x00, 0x00, 0xC3, 0x83 }, "ASPack 2.11"),
|
||||
|
||||
new ContentMatchSet(new byte?[] { 0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81, 0xED }, "ASPack 1.02b/1.08.03"),
|
||||
new(new byte?[] { 0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81, 0xED }, "ASPack 1.02b/1.08.03"),
|
||||
|
||||
#endregion
|
||||
};
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
@@ -8,14 +6,10 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
// TODO: Verify that all versions are detected
|
||||
public class AdvancedInstaller : IExtractable, IPortableExecutableCheck
|
||||
public class AdvancedInstaller : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -34,27 +28,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
using System.IO;
|
||||
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 : IExtractable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// 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/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
@@ -8,14 +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 : IExtractable, IPortableExecutableCheck
|
||||
public class AutoPlayMediaStudio : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -38,27 +33,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -68,12 +43,12 @@ namespace BinaryObjectScanner.Packer
|
||||
// Check the product version explicitly
|
||||
var version = pex.ProductVersion;
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return version;
|
||||
return version!;
|
||||
|
||||
// Check the internal versions
|
||||
version = pex.GetInternalVersion();
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return version;
|
||||
return version!;
|
||||
|
||||
return "(Unknown Version)";
|
||||
}
|
||||
|
||||
@@ -3,8 +3,9 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using ICSharpCode.SharpZipLib.Zip.Compression;
|
||||
using SabreTools.Compression.zlib;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
@@ -12,14 +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 : IExtractable, IPortableExecutableCheck
|
||||
public class CExe : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -34,7 +31,7 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x25, 0x57, 0x6F, 0xC1, 0x61, 0x36, 0x01, 0x92,
|
||||
0x61, 0x36, 0x01, 0x92, 0x61, 0x36, 0x01, 0x92,
|
||||
@@ -46,7 +43,7 @@ namespace BinaryObjectScanner.Packer
|
||||
};
|
||||
|
||||
var match = MatchUtil.GetFirstMatch(file, pex.StubExecutableData, matchers, includeDebug);
|
||||
if (!string.IsNullOrWhiteSpace(match))
|
||||
if (!string.IsNullOrEmpty(match))
|
||||
return match;
|
||||
}
|
||||
|
||||
@@ -54,35 +51,10 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Parse into an executable again for easier extraction
|
||||
var pex = PortableExecutable.Create(stream);
|
||||
if (pex == null)
|
||||
return null;
|
||||
|
||||
// Get the first resource of type 99 with index 2
|
||||
var payload = pex.FindResourceByNamedType("99, 2").FirstOrDefault();
|
||||
if (payload == null || payload.Length == 0)
|
||||
@@ -100,13 +72,35 @@ namespace BinaryObjectScanner.Packer
|
||||
try
|
||||
{
|
||||
// Inflate the data into the buffer
|
||||
Inflater inflater = new Inflater();
|
||||
inflater.SetInput(payload);
|
||||
var zstream = new ZLib.z_stream_s();
|
||||
data = new byte[payload.Length * 4];
|
||||
int read = inflater.Inflate(data);
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* payloadPtr = payload)
|
||||
fixed (byte* dataPtr = data)
|
||||
{
|
||||
zstream.next_in = payloadPtr;
|
||||
zstream.avail_in = (uint)payload.Length;
|
||||
zstream.total_in = (uint)payload.Length;
|
||||
zstream.next_out = dataPtr;
|
||||
zstream.avail_out = (uint)data.Length;
|
||||
zstream.total_out = 0;
|
||||
|
||||
ZLib.inflateInit_(zstream, ZLib.zlibVersion(), payload.Length);
|
||||
int zret = ZLib.inflate(zstream, 1);
|
||||
ZLib.inflateEnd(zstream);
|
||||
}
|
||||
}
|
||||
|
||||
// Trim the buffer to the proper size
|
||||
data = new ReadOnlySpan<byte>(data, 0, read).ToArray();
|
||||
uint read = zstream.total_out;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
data = new ReadOnlySpan<byte>(data, 0, (int)read).ToArray();
|
||||
#else
|
||||
var temp = new byte[read];
|
||||
Array.Copy(data, 0, temp, 0, read);
|
||||
data = temp;
|
||||
#endif
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -115,7 +109,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, LZ is used via the Windows API
|
||||
// Otherwise, LZ is used
|
||||
else
|
||||
{
|
||||
try
|
||||
|
||||
35
BinaryObjectScanner/Packer/DotFuscator.cs
Normal file
35
BinaryObjectScanner/Packer/DotFuscator.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
public class DotFuscator : 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 .text section strings, if they exist
|
||||
var strs = pex.GetFirstSectionStrings(".text");
|
||||
if (strs != null)
|
||||
{
|
||||
if (strs.Any(s => s.Contains("DotfuscatorAttribute")))
|
||||
return "dotFuscator";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
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 : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// TODO: Detect version
|
||||
// TODO: Further refine checks using https://github.com/horsicq/Detect-It-Easy/blob/075a70b1484d1d84d1dc37c86aac16188d5a84e7/db/PE/NetReactor.2.sg and https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
// Get the .text section, if it exists
|
||||
if (pex.ContainsSection(".text"))
|
||||
{
|
||||
var textData = pex.GetFirstSectionData(".text");
|
||||
if (textData != null)
|
||||
{
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
// Adapted from https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar and confirmed to work with "KalypsoLauncher.dll" from Redump entry 95617.
|
||||
// <PrivateImplementationDetails>{[8]-[4]-[4]-[4]-[12]}
|
||||
new(new byte?[]
|
||||
{
|
||||
0x3C, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65,
|
||||
0x49, 0x6D, 0x70, 0x6C, 0x65, 0x6D, 0x65, 0x6E,
|
||||
0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 0x65,
|
||||
0x74, 0x61, 0x69, 0x6C, 0x73, 0x3E, 0x7B, null,
|
||||
null, null, null, null, null, null, null, 0x2D,
|
||||
null, null, null, null, 0x2D, null, null, null,
|
||||
null, 0x2D, null, null, null, null, 0x2D, null,
|
||||
null, null, null, null, null, null, null, null,
|
||||
null, null, null, 0x7D
|
||||
}, ".NET Reactor"),
|
||||
|
||||
// Modified from the previous detection to detect a presumably newer version of .NET Reactor found in "KalypsoLauncher.dll" version 2.0.4.2.
|
||||
// TODO: Check if this can/should be made more specific.
|
||||
// <PrivateImplementationDetails>.RSA
|
||||
new(new byte?[]
|
||||
{
|
||||
0x3C, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65,
|
||||
0x49, 0x6D, 0x70, 0x6C, 0x65, 0x6D, 0x65, 0x6E,
|
||||
0x74, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x44, 0x65,
|
||||
0x74, 0x61, 0x69, 0x6C, 0x73, 0x3E, 0x00, 0x52,
|
||||
0x53, 0x41
|
||||
}, ".NET Reactor"),
|
||||
|
||||
// Adapted from https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar and confirmed to work with "KalypsoLauncher.dll" from Redump entry 95617.
|
||||
// 3{.[9].-.[9].-.[9].}
|
||||
new(new byte?[]
|
||||
{
|
||||
0x33, 0x7B, 0x00, null, null, null, null, null,
|
||||
null, null, null, null, 0x00, 0x2D, 0x00, null,
|
||||
null, null, null, null, null, null, null, null,
|
||||
0x00, 0x2D, 0x00, null, null, null, null, null,
|
||||
null, null, null, null, 0x00, 0x2D, 0x00, null,
|
||||
null, null, null, null, null, null, null, null,
|
||||
0x00, 0x7D, 0x00
|
||||
}, ".NET Reactor (Unconfirmed - Please report to us on GitHub)"),
|
||||
|
||||
// Adapted from https://github.com/cod3nym/detection-rules/blob/main/yara/dotnet/obf_net_reactor.yar and confirmed to work with "KalypsoLauncher.dll" from Redump entry 95617.
|
||||
// <Module>{[8]-[4]-[4]-[4]-[12]}
|
||||
new(new byte?[]
|
||||
{
|
||||
0x3C, 0x4D, 0x6F, 0x64, 0x75, 0x6C, 0x65, 0x3E,
|
||||
0x7B, null, null, null, null, null, null, null,
|
||||
null, 0x2D, null, null, null, null, 0x2D, null,
|
||||
null, null, null, 0x2D, null, null, null, null,
|
||||
0x2D, null, null, null, null, null, null, null,
|
||||
null, null, null, null, null, 0x7D
|
||||
}, ".NET Reactor (Unconfirmed - Please report to us on GitHub)")
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(file, textData, matchers, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
// TODO: Add extraction
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
@@ -10,14 +10,10 @@ 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, IExtractable, IPortableExecutableCheck
|
||||
public class EXEStealth : IContentCheck, IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug)
|
||||
#else
|
||||
public string? CheckContents(string file, byte[] fileContent, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// TODO: Obtain a sample to find where this string is in a typical executable
|
||||
if (includeDebug)
|
||||
@@ -25,7 +21,7 @@ namespace BinaryObjectScanner.Packer
|
||||
var contentMatchSets = new List<ContentMatchSet>
|
||||
{
|
||||
// ??[[__[[_ + (char)0x00 + {{ + (char)0x0 + (char)0x00 + {{ + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x0 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + ?;??;??
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x3F, 0x3F, 0x5B, 0x5B, 0x5F, 0x5F, 0x5B, 0x5B,
|
||||
0x5F, 0x00, 0x7B, 0x7B, 0x00, 0x00, 0x7B, 0x7B,
|
||||
@@ -42,11 +38,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -83,27 +75,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -11,14 +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 : IExtractable, IPortableExecutableCheck
|
||||
public class EmbeddedExecutable : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -33,33 +29,12 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Parse into an executable again for easier extraction
|
||||
var pex = PortableExecutable.Create(stream);
|
||||
if (pex?.ResourceData == null)
|
||||
// If there are no resources
|
||||
if (pex.ResourceData == null)
|
||||
return null;
|
||||
|
||||
// Get the resources that have an executable signature
|
||||
@@ -86,11 +61,8 @@ namespace BinaryObjectScanner.Packer
|
||||
tempFile = Path.Combine(tempPath, tempFile);
|
||||
|
||||
// Write the resource data to a temp file
|
||||
using (var tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
|
||||
{
|
||||
if (tempStream != null)
|
||||
tempStream.Write(data, 0, data.Length);
|
||||
}
|
||||
using var tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
|
||||
tempStream?.Write(data, 0, data.Length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
@@ -8,14 +6,10 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class GenteeInstaller : IExtractable, IPortableExecutableCheck
|
||||
public class GenteeInstaller : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -37,27 +31,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
@@ -10,14 +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 : IExtractable, IPortableExecutableCheck
|
||||
public class HyperTechCrackProof : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -36,27 +31,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,28 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
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 : IExtractable, INewExecutableCheck, IPortableExecutableCheck
|
||||
public class InnoSetup : IExtractablePortableExecutable, INewExecutableCheck, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Check for "Inno" in the reserved words
|
||||
if (nex.Model.Stub?.Header?.Reserved2?[4] == 0x6E49 && nex.Model.Stub?.Header?.Reserved2?[5] == 0x6F6E)
|
||||
{
|
||||
string version = GetOldVersion(file, nex);
|
||||
if (!string.IsNullOrWhiteSpace(version))
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return $"Inno Setup {version}";
|
||||
|
||||
return "Inno Setup (Unknown Version)";
|
||||
@@ -32,11 +28,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -62,27 +54,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -101,7 +73,7 @@ namespace BinaryObjectScanner.Packer
|
||||
var matchers = new List<ContentMatchSet>
|
||||
{
|
||||
// "rDlPtS02" + (char)0x87 + "eVx"
|
||||
new ContentMatchSet(new byte?[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x32, 0x87, 0x65, 0x56, 0x78 }, "1.2.16 or earlier"),
|
||||
new(new byte?[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x32, 0x87, 0x65, 0x56, 0x78 }, "1.2.16 or earlier"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(file, data, matchers, false) ?? "Unknown 1.X";
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
@@ -7,14 +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 : IExtractable, IPortableExecutableCheck
|
||||
public class InstallAnywhere : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -33,27 +28,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -63,7 +38,7 @@ namespace BinaryObjectScanner.Packer
|
||||
// Check the internal versions
|
||||
var version = pex.GetInternalVersion();
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return version;
|
||||
return version!;
|
||||
|
||||
return "(Unknown Version)";
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
@@ -8,15 +6,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 : IExtractable, IPortableExecutableCheck
|
||||
public class InstallerVISE : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
//TODO: Add exact version detection for Windows builds, make sure versions before 3.X are detected as well, and detect the Mac builds.
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -35,27 +29,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction, seems to primarily use MSZip compression.
|
||||
public class IntelInstallationFramework : IExtractable, IPortableExecutableCheck
|
||||
public class IntelInstallationFramework : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -38,27 +33,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
@@ -8,14 +7,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 : IExtractable, IPortableExecutableCheck
|
||||
public class MicrosoftCABSFX : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -52,36 +47,16 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private string GetVersion(PortableExecutable pex)
|
||||
{
|
||||
// Check the internal versions
|
||||
var version = pex.GetInternalVersion();
|
||||
if (!string.IsNullOrWhiteSpace(version))
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return $"v{version}";
|
||||
|
||||
return string.Empty;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
@@ -7,14 +5,10 @@ using SabreTools.Serialization.Wrappers;
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
public class NSIS : IExtractable, IPortableExecutableCheck
|
||||
public class NSIS : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -22,7 +16,7 @@ namespace BinaryObjectScanner.Packer
|
||||
return null;
|
||||
|
||||
var description = pex.AssemblyDescription;
|
||||
if (!string.IsNullOrWhiteSpace(description) && description.StartsWith("Nullsoft Install System"))
|
||||
if (!string.IsNullOrEmpty(description) && description!.StartsWith("Nullsoft Install System"))
|
||||
return $"NSIS {description.Substring("Nullsoft Install System".Length).Trim()}";
|
||||
|
||||
// Get the .data/DATA section strings, if they exist
|
||||
@@ -37,27 +31,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
@@ -14,15 +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 : IExtractable, IPortableExecutableCheck
|
||||
public class NeoLite : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
// TODO: Find samples of NeoLite 1.X.
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -41,28 +36,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// TODO: Add extraction
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Better version detection - https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
// TODO: Add extraction
|
||||
public class PECompact : IExtractable, IPortableExecutableCheck
|
||||
public class PECompact : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -46,27 +41,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class PEtite : IExtractable, IPortableExecutableCheck
|
||||
public class PEtite : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -29,27 +24,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
@@ -8,14 +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 : IExtractable, IPortableExecutableCheck
|
||||
public class SetupFactory : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -43,42 +38,22 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private string GetVersion(PortableExecutable pex)
|
||||
{
|
||||
// Check the product version explicitly
|
||||
var version = pex.ProductVersion;
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return version;
|
||||
return version!;
|
||||
|
||||
// Check the internal versions
|
||||
version = pex.GetInternalVersion();
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return version;
|
||||
return version!;
|
||||
|
||||
return "(Unknown Version)";
|
||||
}
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.SevenZip;
|
||||
using SharpCompress.Readers;
|
||||
#endif
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
public class SevenZipSFX : IExtractable, IPortableExecutableCheck
|
||||
public class SevenZipSFX : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -50,29 +51,59 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
#if NET462_OR_GREATER || NETCOREAPP
|
||||
try
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
using (SevenZipArchive sevenZipFile = SevenZipArchive.Open(file, new ReaderOptions() { LookForHeader = true }))
|
||||
{
|
||||
foreach (var entry in sevenZipFile.Entries)
|
||||
{
|
||||
try
|
||||
{
|
||||
// If the entry is a directory
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
// If the entry has an invalid key
|
||||
if (entry.Key == null)
|
||||
continue;
|
||||
|
||||
// If we have a partial entry due to an incomplete multi-part archive, skip it
|
||||
if (!entry.IsComplete)
|
||||
continue;
|
||||
|
||||
string tempFile = Path.Combine(tempPath, entry.Key);
|
||||
var directoryName = Path.GetDirectoryName(tempFile);
|
||||
if (directoryName != null && !Directory.Exists(directoryName))
|
||||
Directory.CreateDirectory(directoryName);
|
||||
entry.WriteToFile(tempFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.IO;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
@@ -6,14 +5,10 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class Shrinker : IExtractable, IPortableExecutableCheck
|
||||
public class Shrinker : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -30,27 +25,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
@@ -10,18 +9,14 @@ namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class UPX : IExtractable, IPortableExecutableCheck
|
||||
public class UPX : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
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/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -68,27 +63,7 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -3,20 +3,18 @@ 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 : IExtractable, IPortableExecutableCheck
|
||||
public class WinRARSFX : IExtractablePortableExecutable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -35,48 +33,40 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, 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 }))
|
||||
using (RarArchive rarFile = RarArchive.Open(file, new ReaderOptions() { LookForHeader = true }))
|
||||
{
|
||||
if (!zipFile.IsComplete)
|
||||
if (!rarFile.IsComplete)
|
||||
return null;
|
||||
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
foreach (var entry in zipFile.Entries)
|
||||
foreach (var entry in rarFile.Entries)
|
||||
{
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
// 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)
|
||||
@@ -93,6 +83,9 @@ namespace BinaryObjectScanner.Packer
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,28 +4,29 @@ 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 : IExtractable, INewExecutableCheck, IPortableExecutableCheck
|
||||
public class WinZipSFX : IExtractableNewExecutable, IExtractablePortableExecutable, INewExecutableCheck, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// 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)
|
||||
@@ -33,18 +34,14 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
// Try to get a known version
|
||||
var version = GetNEHeaderVersion(nex);
|
||||
if (!string.IsNullOrWhiteSpace(version))
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return $"WinZip SFX {version}";
|
||||
|
||||
return $"WinZip SFX Unknown Version (16-bit)";
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -55,7 +52,7 @@ namespace BinaryObjectScanner.Packer
|
||||
if (pex.Model.ExportTable?.ExportDirectoryTable != null)
|
||||
{
|
||||
var version = GetPEExportDirectoryVersion(pex);
|
||||
if (!string.IsNullOrWhiteSpace(version))
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return $"WinZip SFX {version}";
|
||||
}
|
||||
|
||||
@@ -69,48 +66,47 @@ 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/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
public string? Extract(string file, NewExecutable nex, bool includeDebug)
|
||||
=> Extract(file, includeDebug);
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
=> Extract(file, includeDebug);
|
||||
|
||||
/// <summary>
|
||||
/// Handle common extraction between executable types
|
||||
/// </summary>
|
||||
public static string? Extract(string file, 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.
|
||||
// Create a temp output directory
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (ZipArchive zipFile = ZipArchive.Open(file))
|
||||
{
|
||||
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 we have a directory, skip it
|
||||
// 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)
|
||||
@@ -118,15 +114,18 @@ namespace BinaryObjectScanner.Packer
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
#else
|
||||
return null;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -134,11 +133,7 @@ namespace BinaryObjectScanner.Packer
|
||||
/// </summary>
|
||||
/// TODO: Reduce the checks to only the ones that differ between versions
|
||||
/// TODO: Research to see if the versions are embedded elsewhere in these files
|
||||
#if NET48
|
||||
private string GetNEHeaderVersion(NewExecutable nex)
|
||||
#else
|
||||
private string? GetNEHeaderVersion(NewExecutable nex)
|
||||
#endif
|
||||
private static string? GetNEHeaderVersion(NewExecutable nex)
|
||||
{
|
||||
#region 2.0 Variants
|
||||
|
||||
@@ -696,11 +691,7 @@ namespace BinaryObjectScanner.Packer
|
||||
/// Get the version from the PE export directory table value combinations
|
||||
/// </summary>
|
||||
/// TODO: Research to see if the versions are embedded elsewhere in these files
|
||||
#if NET48
|
||||
private string GetPEExportDirectoryVersion(PortableExecutable pex)
|
||||
#else
|
||||
private string? GetPEExportDirectoryVersion(PortableExecutable pex)
|
||||
#endif
|
||||
private static string? GetPEExportDirectoryVersion(PortableExecutable pex)
|
||||
{
|
||||
string sfxFileName = pex.Model.ExportTable?.ExportDirectoryTable?.Name ?? string.Empty;
|
||||
uint sfxTimeDateStamp = pex.Model.ExportTable?.ExportDirectoryTable?.TimeDateStamp ?? uint.MaxValue;
|
||||
@@ -711,37 +702,23 @@ namespace BinaryObjectScanner.Packer
|
||||
|| sfxFileName == "WZIPSE32.exe" || sfxFileName == "SI32LPG.SFX"
|
||||
|| sfxFileName == "ST32E.WZE")
|
||||
{
|
||||
switch (sfxTimeDateStamp)
|
||||
return sfxTimeDateStamp switch
|
||||
{
|
||||
case 842636344:
|
||||
return "2.0 (32-bit)";
|
||||
case 865370756:
|
||||
return "2.1 RC2 (32-bit)";
|
||||
case 869059925:
|
||||
return "2.1 (32-bit)";
|
||||
case 979049321:
|
||||
return "2.2.4003";
|
||||
case 1149714685:
|
||||
return "3.0.7158";
|
||||
case 1185211734:
|
||||
return "3.1.7556";
|
||||
case 1185211920:
|
||||
return "3.1.7556";
|
||||
case 1235490556:
|
||||
return "4.0.8421";
|
||||
case 1235490757:
|
||||
return "4.0.8421";
|
||||
case 1235490687:
|
||||
return "4.0.8421"; // 3.1.8421.0, SI32LPG?
|
||||
case 1257193383:
|
||||
return "4.0.8672"; // 3.1.8672.0
|
||||
case 1257193543:
|
||||
return "4.0.8672";
|
||||
case 1470410848:
|
||||
return "4.0.12218"; // 4.0.1221.0
|
||||
default:
|
||||
return $"{assemblyVersion} (32-bit)";
|
||||
}
|
||||
842636344 => "2.0 (32-bit)",
|
||||
865370756 => "2.1 RC2 (32-bit)",
|
||||
869059925 => "2.1 (32-bit)",
|
||||
979049321 => "2.2.4003",
|
||||
1149714685 => "3.0.7158",
|
||||
1185211734 => "3.1.7556",
|
||||
1185211920 => "3.1.7556",
|
||||
1235490556 => "4.0.8421",
|
||||
1235490757 => "4.0.8421",
|
||||
1235490687 => "4.0.8421",// 3.1.8421.0, SI32LPG?
|
||||
1257193383 => "4.0.8672",// 3.1.8672.0
|
||||
1257193543 => "4.0.8672",
|
||||
1470410848 => "4.0.12218",// 4.0.1221.0
|
||||
_ => $"{assemblyVersion} (32-bit)",
|
||||
};
|
||||
}
|
||||
|
||||
// Personal Edition
|
||||
@@ -749,152 +726,90 @@ namespace BinaryObjectScanner.Packer
|
||||
|| sfxFileName == "wzsepe32.exe" || sfxFileName == "SI32PE.SFX"
|
||||
|| sfxFileName == "SI32LPE.SFX")
|
||||
{
|
||||
switch (sfxTimeDateStamp)
|
||||
return sfxTimeDateStamp switch
|
||||
{
|
||||
case 845061601:
|
||||
return "Personal Edition (32-bit)"; // TODO: Find version
|
||||
case 868303343:
|
||||
return "Personal Edition (32-bit)"; // TODO: Find version
|
||||
case 868304170:
|
||||
return "Personal Edition (32-bit)"; // TODO: Find version
|
||||
case 906039079:
|
||||
return "Personal Edition 2.2.1260 (32-bit)";
|
||||
case 906040543:
|
||||
return "Personal Edition 2.2.1260 (32-bit)";
|
||||
case 908628435:
|
||||
return "Personal Edition 2.2.1285 (32-bit)";
|
||||
case 908628785:
|
||||
return "Personal Edition 2.2.1285 (32-bit)";
|
||||
case 956165981:
|
||||
return "Personal Edition 2.2.3063";
|
||||
case 956166038:
|
||||
return "Personal Edition 2.2.3063";
|
||||
case 1006353695:
|
||||
return "Personal Edition 2.2.4325";
|
||||
case 1006353714:
|
||||
return "Personal Edition 2.2.4325"; // 8.1.0.0
|
||||
case 1076515698:
|
||||
return "Personal Edition 2.2.6028";
|
||||
case 1076515784:
|
||||
return "Personal Edition 2.2.6028"; // 9.0.6028.0
|
||||
case 1092688561:
|
||||
return "Personal Edition 2.2.6224";
|
||||
case 1092688645:
|
||||
return "Personal Edition 2.2.6224"; // 9.0.6224.0
|
||||
case 1125074095:
|
||||
return "Personal Edition 2.2.6604";
|
||||
case 1125074162:
|
||||
return "Personal Edition 2.2.6604"; // 10.0.6604.0
|
||||
case 1130153399:
|
||||
return "Personal Edition 2.2.6663";
|
||||
case 1130153428:
|
||||
return "Personal Edition 2.2.6663"; // 10.0.6663.0
|
||||
case 1149714176:
|
||||
return "Personal Edition 3.0.7158";
|
||||
case 1163137967:
|
||||
return "Personal Edition 3.0.7305";
|
||||
case 1163137994:
|
||||
return "Personal Edition 3.0.7313"; // 11.0.7313.0
|
||||
case 1176345383:
|
||||
return "Personal Edition 3.0.7452";
|
||||
case 1176345423:
|
||||
return "Personal Edition 3.1.7466"; // 11.1.7466.0
|
||||
case 1184106698:
|
||||
return "Personal Edition 3.1.7556";
|
||||
case 1207280880:
|
||||
return "Personal Edition 4.0.8060"; // 2.3.7382.0
|
||||
case 1207280892:
|
||||
return "Personal Edition 4.0.8094"; // 11.2.8094.0
|
||||
case 1220904506:
|
||||
return "Personal Edition 4.0.8213"; // 2.3.7382.0
|
||||
case 1220904518:
|
||||
return "Personal Edition 4.0.8252"; // 12.0.8252.0
|
||||
case 1235490648:
|
||||
return "Personal Edition 4.0.8421"; // 3.1.8421.0
|
||||
case 1242049399:
|
||||
return "Personal Edition 4.0.8497"; // 12.1.8497.0
|
||||
case 1257193469:
|
||||
return "Personal Edition 4.0.8672"; // 3.1.8672.0, SI32LPE?
|
||||
default:
|
||||
return $"Personal Edition {assemblyVersion} (32-bit)";
|
||||
}
|
||||
845061601 => "Personal Edition (32-bit)",// TODO: Find version
|
||||
868303343 => "Personal Edition (32-bit)",// TODO: Find version
|
||||
868304170 => "Personal Edition (32-bit)",// TODO: Find version
|
||||
906039079 => "Personal Edition 2.2.1260 (32-bit)",
|
||||
906040543 => "Personal Edition 2.2.1260 (32-bit)",
|
||||
908628435 => "Personal Edition 2.2.1285 (32-bit)",
|
||||
908628785 => "Personal Edition 2.2.1285 (32-bit)",
|
||||
956165981 => "Personal Edition 2.2.3063",
|
||||
956166038 => "Personal Edition 2.2.3063",
|
||||
1006353695 => "Personal Edition 2.2.4325",
|
||||
1006353714 => "Personal Edition 2.2.4325",// 8.1.0.0
|
||||
1076515698 => "Personal Edition 2.2.6028",
|
||||
1076515784 => "Personal Edition 2.2.6028",// 9.0.6028.0
|
||||
1092688561 => "Personal Edition 2.2.6224",
|
||||
1092688645 => "Personal Edition 2.2.6224",// 9.0.6224.0
|
||||
1125074095 => "Personal Edition 2.2.6604",
|
||||
1125074162 => "Personal Edition 2.2.6604",// 10.0.6604.0
|
||||
1130153399 => "Personal Edition 2.2.6663",
|
||||
1130153428 => "Personal Edition 2.2.6663",// 10.0.6663.0
|
||||
1149714176 => "Personal Edition 3.0.7158",
|
||||
1163137967 => "Personal Edition 3.0.7305",
|
||||
1163137994 => "Personal Edition 3.0.7313",// 11.0.7313.0
|
||||
1176345383 => "Personal Edition 3.0.7452",
|
||||
1176345423 => "Personal Edition 3.1.7466",// 11.1.7466.0
|
||||
1184106698 => "Personal Edition 3.1.7556",
|
||||
1207280880 => "Personal Edition 4.0.8060",// 2.3.7382.0
|
||||
1207280892 => "Personal Edition 4.0.8094",// 11.2.8094.0
|
||||
1220904506 => "Personal Edition 4.0.8213",// 2.3.7382.0
|
||||
1220904518 => "Personal Edition 4.0.8252",// 12.0.8252.0
|
||||
1235490648 => "Personal Edition 4.0.8421",// 3.1.8421.0
|
||||
1242049399 => "Personal Edition 4.0.8497",// 12.1.8497.0
|
||||
1257193469 => "Personal Edition 4.0.8672",// 3.1.8672.0, SI32LPE?
|
||||
_ => $"Personal Edition {assemblyVersion} (32-bit)",
|
||||
};
|
||||
}
|
||||
|
||||
// Software Installation
|
||||
else if (sfxFileName == "VW95SRE.SFX" || sfxFileName == "SI32E.SFX"
|
||||
|| sfxFileName == "SI32E.WZE")
|
||||
{
|
||||
switch (sfxTimeDateStamp)
|
||||
return sfxTimeDateStamp switch
|
||||
{
|
||||
case 842636381:
|
||||
return "Software Installation 2.0 (32-bit)";
|
||||
case 865370800:
|
||||
return "Software Installation 2.1 RC2 (32-bit)";
|
||||
case 869059963:
|
||||
return "Software Installation 2.1 (32-bit)";
|
||||
case 893107697:
|
||||
return "Software Installation 2.2.1110 (32-bit)";
|
||||
case 952007369:
|
||||
return "Software Installation 2.2.3063";
|
||||
case 1006352634:
|
||||
return "Software Installation 2.2.4325"; // +Personal Edition?
|
||||
case 979049345:
|
||||
return "Software Installation 2.2.4403";
|
||||
case 1026227373:
|
||||
return "Software Installation 2.2.5196"; // +Personal Edition?
|
||||
case 1090582390:
|
||||
return "Software Installation 2.2.6202"; // +Personal Edition?
|
||||
case 1149714757:
|
||||
return "Software Installation 3.0.7158";
|
||||
case 1154357628:
|
||||
return "Software Installation 3.0.7212";
|
||||
case 1175234637:
|
||||
return "Software Installation 3.0.7454";
|
||||
case 1185211802:
|
||||
return "Software Installation 3.1.7556";
|
||||
case 1470410906:
|
||||
return "Software Installation 4.0.12218"; // 4.0.1221.0
|
||||
default:
|
||||
return $"Software Installation {assemblyVersion} (32-bit)";
|
||||
}
|
||||
842636381 => "Software Installation 2.0 (32-bit)",
|
||||
865370800 => "Software Installation 2.1 RC2 (32-bit)",
|
||||
869059963 => "Software Installation 2.1 (32-bit)",
|
||||
893107697 => "Software Installation 2.2.1110 (32-bit)",
|
||||
952007369 => "Software Installation 2.2.3063",
|
||||
1006352634 => "Software Installation 2.2.4325",// +Personal Edition?
|
||||
979049345 => "Software Installation 2.2.4403",
|
||||
1026227373 => "Software Installation 2.2.5196",// +Personal Edition?
|
||||
1090582390 => "Software Installation 2.2.6202",// +Personal Edition?
|
||||
1149714757 => "Software Installation 3.0.7158",
|
||||
1154357628 => "Software Installation 3.0.7212",
|
||||
1175234637 => "Software Installation 3.0.7454",
|
||||
1185211802 => "Software Installation 3.1.7556",
|
||||
1470410906 => "Software Installation 4.0.12218",// 4.0.1221.0
|
||||
_ => $"Software Installation {assemblyVersion} (32-bit)",
|
||||
};
|
||||
}
|
||||
|
||||
switch (sfxFileName)
|
||||
return sfxFileName switch
|
||||
{
|
||||
// Standard
|
||||
case "VW95SE.SFX":
|
||||
return "Unknown Version (32-bit)"; // TODO: Find starting version
|
||||
case "ST32E.SFX":
|
||||
return "Unknown Version (32-bit)"; // TODO: Find starting version
|
||||
case "WZIPSE32.exe":
|
||||
return "Unknown Version (32-bit)"; // TODO: Find starting version
|
||||
case "SI32LPG.SFX":
|
||||
return "Unknown Version (32-bit)"; // TODO: Find starting version
|
||||
case "ST32E.WZE":
|
||||
return "Unknown Version (32-bit)"; // TODO: Find starting version
|
||||
|
||||
"VW95SE.SFX" => "Unknown Version (32-bit)",// TODO: Find starting version
|
||||
"ST32E.SFX" => "Unknown Version (32-bit)",// TODO: Find starting version
|
||||
"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
|
||||
case "VW95LE.SFX":
|
||||
return "Unknown Version before Personal Edition Build 1285 (32-bit)";
|
||||
case "PE32E.SFX":
|
||||
return "Unknown Version after Personal Edition Build 1285 (32-bit)";
|
||||
case "wzsepe32.exe":
|
||||
return "Unknown Version Personal Edition (32-bit)"; // TODO: Find starting version
|
||||
case "SI32PE.SFX":
|
||||
return "Unknown Version Personal Edition (32-bit)"; // TODO: Find starting version
|
||||
case "SI32LPE.SFX":
|
||||
return "Unknown Version Personal Edition (32-bit)"; // TODO: Find starting version
|
||||
|
||||
"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
|
||||
case "VW95SRE.SFX":
|
||||
return "Unknown Version before Software Installation 2.1 (32-bit)";
|
||||
case "SI32E.SFX":
|
||||
return "Unknown Version after Software Installation 2.1 (32-bit)";
|
||||
case "SI32E.WZE":
|
||||
return "Unknown Version Software Installation (32-bit)"; // TODO: Find starting version
|
||||
}
|
||||
|
||||
return null;
|
||||
"VW95SRE.SFX" => "Unknown Version before Software Installation 2.1 (32-bit)",
|
||||
"SI32E.SFX" => "Unknown Version after Software Installation 2.1 (32-bit)",
|
||||
"SI32E.WZE" => "Unknown Version Software Installation (32-bit)",// TODO: Find starting version
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,22 +3,20 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.IO;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
using Wise = WiseUnpacker.WiseUnpacker;
|
||||
using WiseUnpacker;
|
||||
using WiseUnpacker.EWISE;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
|
||||
public class WiseInstaller : IExtractable, INewExecutableCheck, IPortableExecutableCheck
|
||||
public class WiseInstaller : IExtractableNewExecutable, IExtractablePortableExecutable, INewExecutableCheck, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// If we match a known header
|
||||
if (MatchesNEVersion(nex) != null)
|
||||
@@ -34,21 +32,17 @@ namespace BinaryObjectScanner.Packer
|
||||
var neMatchSets = new List<ContentMatchSet>
|
||||
{
|
||||
// WiseInst
|
||||
new ContentMatchSet(new byte?[] { 0x57, 0x69, 0x73, 0x65, 0x49, 0x6E, 0x73, 0x74 }, "Wise Installation Wizard Module"),
|
||||
new(new byte?[] { 0x57, 0x69, 0x73, 0x65, 0x49, 0x6E, 0x73, 0x74 }, "Wise Installation Wizard Module"),
|
||||
|
||||
// WiseMain
|
||||
new ContentMatchSet(new byte?[] { 0x57, 0x69, 0x73, 0x65, 0x4D, 0x61, 0x69, 0x6E }, "Wise Installation Wizard Module"),
|
||||
new(new byte?[] { 0x57, 0x69, 0x73, 0x65, 0x4D, 0x61, 0x69, 0x6E }, "Wise Installation Wizard Module"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(file, data, neMatchSets, includeDebug);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -81,41 +75,138 @@ namespace BinaryObjectScanner.Packer
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, NewExecutable nex, bool includeDebug)
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
try
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
public string? Extract(string file, PortableExecutable pex, bool includeDebug)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Try to parse as a New Executable
|
||||
var nex = NewExecutable.Create(stream);
|
||||
if (nex != null)
|
||||
return ExtractNewExecutable(nex, file, includeDebug);
|
||||
// Get the matching PE format
|
||||
var format = GetPEFormat(pex);
|
||||
if (format == null)
|
||||
return null;
|
||||
|
||||
// Try to parse as a Portable Executable
|
||||
var pex = PortableExecutable.Create(stream);
|
||||
if (pex != null)
|
||||
return ExtractPortableExecutable(pex, file, includeDebug);
|
||||
// Get the overlay data for easier reading
|
||||
int overlayOffset = 0, dataStart = 0;
|
||||
var overlayData = pex.OverlayData;
|
||||
if (overlayData == null)
|
||||
return null;
|
||||
|
||||
return null;
|
||||
// Skip over the additional DLL name, if we expect it
|
||||
if (format.Dll)
|
||||
{
|
||||
// Read the name length
|
||||
byte dllNameLength = overlayData.ReadByte(ref overlayOffset);
|
||||
dataStart++;
|
||||
|
||||
// Read the name, if it exists
|
||||
if (dllNameLength != 0)
|
||||
{
|
||||
// Ignore the name for now
|
||||
_ = overlayData.ReadBytes(ref overlayOffset, dllNameLength);
|
||||
dataStart += dllNameLength;
|
||||
|
||||
// Named DLLs also have a DLL length that we ignore
|
||||
_ = overlayData.ReadUInt32(ref overlayOffset);
|
||||
dataStart += 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if flags are consistent
|
||||
if (!format.NoCrc)
|
||||
{
|
||||
// Unlike WiseUnpacker, we ignore the flag value here
|
||||
_ = overlayData.ReadUInt32(ref overlayOffset);
|
||||
}
|
||||
|
||||
// Ensure that we have an archive end
|
||||
if (format.ArchiveEnd > 0)
|
||||
{
|
||||
overlayOffset = (int)(dataStart + format.ArchiveEnd);
|
||||
int archiveEndLoaded = overlayData.ReadInt32(ref overlayOffset);
|
||||
if (archiveEndLoaded != 0)
|
||||
format.ArchiveEnd = archiveEndLoaded;
|
||||
}
|
||||
|
||||
// Skip to the start of the archive
|
||||
overlayOffset = (int)(dataStart + format.ArchiveStart);
|
||||
|
||||
// Skip over the initialization text, if we expect it
|
||||
if (format.InitText)
|
||||
{
|
||||
int initTextLength = overlayData.ReadByte(ref overlayOffset);
|
||||
_ = overlayData.ReadBytes(ref overlayOffset, initTextLength);
|
||||
}
|
||||
|
||||
// Cache the current offset in the overlay as the "start of data"
|
||||
int offsetReal = overlayOffset;
|
||||
|
||||
// If the first entry is PKZIP, we assume it's an embedded zipfile
|
||||
var magic = overlayData.ReadBytes(ref overlayOffset, 4); overlayOffset -= 4;
|
||||
bool pkzip = magic?.StartsWith(new byte?[] { (byte)'P', (byte)'K' }) ?? false;
|
||||
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
// 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 tempPath;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -129,11 +220,7 @@ namespace BinaryObjectScanner.Packer
|
||||
/// </summary>
|
||||
/// <param name="nex">New executable to check</param>
|
||||
/// <returns>True if it matches a known version, false otherwise</returns>
|
||||
#if NET48
|
||||
private FormatProperty MatchesNEVersion(NewExecutable nex)
|
||||
#else
|
||||
private FormatProperty? MatchesNEVersion(NewExecutable nex)
|
||||
#endif
|
||||
{
|
||||
// TODO: Offset is _not_ the EXE header address, rather where the data starts. Fix this.
|
||||
switch (nex.Model.Stub?.Header?.NewExeHeaderAddr)
|
||||
@@ -190,11 +277,7 @@ namespace BinaryObjectScanner.Packer
|
||||
/// </summary>
|
||||
/// <param name="pex">Portable executable to check</param>
|
||||
/// <returns>True if it matches a known version, false otherwise</returns>
|
||||
#if NET48
|
||||
private FormatProperty GetPEFormat(PortableExecutable pex)
|
||||
#else
|
||||
private FormatProperty? GetPEFormat(PortableExecutable pex)
|
||||
#endif
|
||||
{
|
||||
if (pex.OverlayAddress == 0x6e00
|
||||
&& pex.GetFirstSection(".text")?.VirtualSize == 0x3cf4
|
||||
@@ -233,210 +316,5 @@ namespace BinaryObjectScanner.Packer
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to extract Wise data from a New Executable
|
||||
/// </summary>
|
||||
/// <param name="nex">New executable to check</param>
|
||||
/// <param name="file">Path to the input file</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>True if it matches a known version, false otherwise</returns>
|
||||
#if NET48
|
||||
private string ExtractNewExecutable(NewExecutable nex, string file, bool includeDebug)
|
||||
#else
|
||||
private string? ExtractNewExecutable(NewExecutable nex, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
try
|
||||
{
|
||||
// TODO: Try to find where the file data lives and how to get it
|
||||
Wise unpacker = new Wise();
|
||||
if (!unpacker.ExtractTo(file, tempPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to extract Wise data from a Portable Executable
|
||||
/// </summary>
|
||||
/// <param name="pex">Portable executable to check</param>
|
||||
/// <param name="file">Path to the input file</param>
|
||||
/// <param name="includeDebug">True to include debug data, false otherwise</param>
|
||||
/// <returns>True if it matches a known version, false otherwise</returns>
|
||||
#if NET48
|
||||
private string ExtractPortableExecutable(PortableExecutable pex, string file, bool includeDebug)
|
||||
#else
|
||||
private string? ExtractPortableExecutable(PortableExecutable pex, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get the matching PE format
|
||||
var format = GetPEFormat(pex);
|
||||
if (format == null)
|
||||
return null;
|
||||
|
||||
// Get the overlay data for easier reading
|
||||
int overlayOffset = 0, dataStart = 0;
|
||||
var overlayData = pex.OverlayData;
|
||||
if (overlayData == null)
|
||||
return null;
|
||||
|
||||
// Skip over the additional DLL name, if we expect it
|
||||
if (format.Dll)
|
||||
{
|
||||
// Read the name length
|
||||
byte dllNameLength = overlayData.ReadByte(ref overlayOffset);
|
||||
dataStart++;
|
||||
|
||||
// Read the name, if it exists
|
||||
if (dllNameLength != 0)
|
||||
{
|
||||
// Ignore the name for now
|
||||
_ = overlayData.ReadBytes(ref overlayOffset, dllNameLength);
|
||||
dataStart += dllNameLength;
|
||||
|
||||
// Named DLLs also have a DLL length that we ignore
|
||||
_ = overlayData.ReadUInt32(ref overlayOffset);
|
||||
dataStart += 4;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if flags are consistent
|
||||
if (!format.NoCrc)
|
||||
{
|
||||
// Unlike WiseUnpacker, we ignore the flag value here
|
||||
_ = overlayData.ReadUInt32(ref overlayOffset);
|
||||
}
|
||||
|
||||
// Ensure that we have an archive end
|
||||
if (format.ArchiveEnd > 0)
|
||||
{
|
||||
overlayOffset = dataStart + format.ArchiveEnd;
|
||||
int archiveEndLoaded = overlayData.ReadInt32(ref overlayOffset);
|
||||
if (archiveEndLoaded != 0)
|
||||
format.ArchiveEnd = archiveEndLoaded;
|
||||
}
|
||||
|
||||
// Skip to the start of the archive
|
||||
overlayOffset = dataStart + format.ArchiveStart;
|
||||
|
||||
// Skip over the initialization text, if we expect it
|
||||
if (format.InitText)
|
||||
{
|
||||
int initTextLength = overlayData.ReadByte(ref overlayOffset);
|
||||
_ = overlayData.ReadBytes(ref overlayOffset, initTextLength);
|
||||
}
|
||||
|
||||
// Cache the current offset in the overlay as the "start of data"
|
||||
int offsetReal = overlayOffset;
|
||||
|
||||
// If the first entry is PKZIP, we assume it's an embedded zipfile
|
||||
var magic = overlayData.ReadBytes(ref overlayOffset, 4); overlayOffset -= 4;
|
||||
bool pkzip = magic?.StartsWith(new byte?[] { (byte)'P', (byte)'K' }) ?? false;
|
||||
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
// If we have DEFLATE -- TODO: Port implementation here or use DeflateStream
|
||||
else
|
||||
{
|
||||
Wise unpacker = new Wise();
|
||||
if (!unpacker.ExtractTo(file, tempPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (includeDebug) Console.WriteLine(ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class representing the properties of each recognized Wise installer format
|
||||
/// </summary>
|
||||
/// <see href="https://github.com/mnadareski/WiseUnpacker/blob/master/WiseUnpacker/FormatProperty.cs"/>
|
||||
private class FormatProperty
|
||||
{
|
||||
/// <summary>
|
||||
/// Offset to the executable data
|
||||
/// </summary>
|
||||
public int ExecutableOffset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if this format includes a DLL at the start or not
|
||||
/// </summary>
|
||||
public bool Dll { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Offset within the data where the archive starts
|
||||
/// </summary>
|
||||
public int ArchiveStart { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Position in the archive head of the archive end
|
||||
/// </summary>
|
||||
public int ArchiveEnd { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Format includes initialization text
|
||||
/// </summary>
|
||||
public bool InitText { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Position of the filename within the data
|
||||
/// </summary>
|
||||
public int FilenamePosition { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Format does not include a CRC
|
||||
/// </summary>
|
||||
public bool NoCrc { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
/// <summary>
|
||||
/// This class exists for reflection purposes and should not be used
|
||||
/// </summary>
|
||||
public sealed class _DUMMY { }
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Packer
|
||||
{
|
||||
// TODO: Add extraction
|
||||
public class dotFuscator : IExtractable, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
if (sections == null)
|
||||
return null;
|
||||
|
||||
// Get the .text section strings, if they exist
|
||||
var strs = pex.GetFirstSectionStrings(".text");
|
||||
if (strs != null)
|
||||
{
|
||||
if (strs.Any(s => s.Contains("DotfuscatorAttribute")))
|
||||
return "dotFuscator";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
if (!File.Exists(file))
|
||||
return null;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||
{
|
||||
return Extract(fs, file, includeDebug);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string Extract(Stream stream, string file, bool includeDebug)
|
||||
#else
|
||||
public string? Extract(Stream? stream, string file, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
107
BinaryObjectScanner/Progress.cs
Normal file
107
BinaryObjectScanner/Progress.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
#if NET20 || NET35 || NET40
|
||||
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace System
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides an IProgress{T} that invokes callbacks for each reported progress value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Specifies the type of the progress report value.</typeparam>
|
||||
/// <remarks>
|
||||
/// Any handler provided to the constructor or event handlers registered with
|
||||
/// the <see cref="ProgressChanged"/> event are invoked through a
|
||||
/// <see cref="SynchronizationContext"/> instance captured
|
||||
/// when the instance is constructed. If there is no current SynchronizationContext
|
||||
/// at the time of construction, the callbacks will be invoked on the ThreadPool.
|
||||
/// </remarks>
|
||||
/// <see href="https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Progress.cs"/>
|
||||
public class Progress<T> : IProgress<T> where T : EventArgs
|
||||
{
|
||||
/// <summary>The synchronization context captured upon construction. This will never be null.</summary>
|
||||
private readonly SynchronizationContext? _synchronizationContext;
|
||||
/// <summary>The handler specified to the constructor. This may be null.</summary>
|
||||
private readonly Action<T>? _handler;
|
||||
/// <summary>A cached delegate used to post invocation to the synchronization context.</summary>
|
||||
private readonly SendOrPostCallback _invokeHandlers;
|
||||
|
||||
/// <summary>Initializes the <see cref="Progress{T}"/>.</summary>
|
||||
public Progress()
|
||||
{
|
||||
// Capture the current synchronization context.
|
||||
// If there is no current context, we use a default instance targeting the ThreadPool.
|
||||
_synchronizationContext = SynchronizationContext.Current ?? ProgressStatics.DefaultContext;
|
||||
Debug.Assert(_synchronizationContext != null);
|
||||
_invokeHandlers = new SendOrPostCallback(InvokeHandlers);
|
||||
}
|
||||
|
||||
/// <summary>Initializes the <see cref="Progress{T}"/> with the specified callback.</summary>
|
||||
/// <param name="handler">
|
||||
/// A handler to invoke for each reported progress value. This handler will be invoked
|
||||
/// in addition to any delegates registered with the <see cref="ProgressChanged"/> event.
|
||||
/// Depending on the <see cref="SynchronizationContext"/> instance captured by
|
||||
/// the <see cref="Progress{T}"/> at construction, it's possible that this handler instance
|
||||
/// could be invoked concurrently with itself.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentNullException">The <paramref name="handler"/> is null (<see langword="Nothing" /> in Visual Basic).</exception>
|
||||
public Progress(Action<T> handler) : this()
|
||||
{
|
||||
_handler = handler ?? throw new ArgumentNullException(nameof(handler));
|
||||
}
|
||||
|
||||
/// <summary>Raised for each reported progress value.</summary>
|
||||
/// <remarks>
|
||||
/// Handlers registered with this event will be invoked on the
|
||||
/// <see cref="SynchronizationContext"/> captured when the instance was constructed.
|
||||
/// </remarks>
|
||||
public event EventHandler<T>? ProgressChanged;
|
||||
|
||||
/// <summary>Reports a progress change.</summary>
|
||||
/// <param name="value">The value of the updated progress.</param>
|
||||
protected virtual void OnReport(T value)
|
||||
{
|
||||
// If there's no handler, don't bother going through the sync context.
|
||||
// Inside the callback, we'll need to check again, in case
|
||||
// an event handler is removed between now and then.
|
||||
Action<T>? handler = _handler;
|
||||
EventHandler<T>? changedEvent = ProgressChanged;
|
||||
if (handler != null || changedEvent != null)
|
||||
{
|
||||
// Post the processing to the sync context.
|
||||
// (If T is a value type, it will get boxed here.)
|
||||
_synchronizationContext?.Post(_invokeHandlers, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Reports a progress change.</summary>
|
||||
/// <param name="value">The value of the updated progress.</param>
|
||||
void IProgress<T>.Report(T value) { OnReport(value); }
|
||||
|
||||
/// <summary>Invokes the action and event callbacks.</summary>
|
||||
/// <param name="state">The progress value.</param>
|
||||
private void InvokeHandlers(object? state)
|
||||
{
|
||||
T value = (T)state!;
|
||||
|
||||
Action<T>? handler = _handler;
|
||||
EventHandler<T>? changedEvent = ProgressChanged;
|
||||
|
||||
handler?.Invoke(value);
|
||||
changedEvent?.Invoke(this, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Holds static values for <see cref="Progress{T}"/>.</summary>
|
||||
/// <remarks>This avoids one static instance per type T.</remarks>
|
||||
internal static class ProgressStatics
|
||||
{
|
||||
/// <summary>A default synchronization context that targets the ThreadPool.</summary>
|
||||
internal static readonly SynchronizationContext DefaultContext = new();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -3,6 +3,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Content;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
@@ -11,11 +12,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public class ActiveMARK : IContentCheck, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug)
|
||||
#else
|
||||
public string? CheckContents(string file, byte[] fileContent, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// TODO: Obtain a sample to find where this string is in a typical executable
|
||||
if (includeDebug)
|
||||
@@ -23,7 +20,7 @@ namespace BinaryObjectScanner.Protection
|
||||
var contentMatchSets = new List<ContentMatchSet>
|
||||
{
|
||||
// " " + (char)0xC2 + (char)0x16 + (char)0x00 + (char)0xA8 + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0xB8 + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0x86 + (char)0xC8 + (char)0x16 + (char)0x00 + (char)0x9A + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0x10 + (char)0xC2 + (char)0x16 + (char)0x00
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x20, 0xC2, 0x16, 0x00, 0xA8, 0xC1, 0x16, 0x00,
|
||||
0xB8, 0xC1, 0x16, 0x00, 0x86, 0xC8, 0x16, 0x00,
|
||||
@@ -38,11 +35,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using System.Collections.Concurrent;
|
||||
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
|
||||
@@ -20,11 +21,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public class AegiSoft : IPathCheck, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -55,7 +52,7 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// Found in "Asc001.dll", "Asc002.dll", "Asc003.dll", "Asc005.dll", "Asc006.exe", and "AscLM.cpl" (Redump entry 73521/IA item "Nova_HoyleCasino99USA").
|
||||
// ÿÿÿÿ\\.\ASCLM
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x5C, 0x5C, 0x2E, 0x5C,
|
||||
0x41, 0x53, 0x43, 0x4C, 0x4D
|
||||
@@ -63,7 +60,7 @@ namespace BinaryObjectScanner.Protection
|
||||
};
|
||||
|
||||
var match = MatchUtil.GetFirstMatch(file, dataSectionRaw, matchers, includeDebug);
|
||||
if (!string.IsNullOrWhiteSpace(match))
|
||||
if (!string.IsNullOrEmpty(match))
|
||||
return match;
|
||||
}
|
||||
|
||||
@@ -71,39 +68,31 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string> files)
|
||||
#else
|
||||
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#endif
|
||||
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// Found in Redump entry 73521/IA item "Nova_HoyleCasino99USA".
|
||||
new PathMatchSet(new PathMatch("AscLM.cpl", useEndsWith: true), "AegiSoft License Manager"),
|
||||
new PathMatchSet(new PathMatch("AscLM.vxd", useEndsWith: true), "AegiSoft License Manager"),
|
||||
new PathMatchSet(new PathMatch("AscLMd.vxd", useEndsWith: true), "AegiSoft License Manager"),
|
||||
new(new FilePathMatch("AscLM.cpl"), "AegiSoft License Manager"),
|
||||
new(new FilePathMatch("AscLM.vxd"), "AegiSoft License Manager"),
|
||||
new(new FilePathMatch("AscLMd.vxd"), "AegiSoft License Manager"),
|
||||
|
||||
// There are a few other files present, but the file names on their own may be too overmatching. Due to the small sample size, it's not sure if these files are always present together.
|
||||
// These files are "Asc001.dll", "Asc002.dll", "Asc003.dll", "Asc005.dll", and "Asc006.exe" (Found in Redump entry 73521/IA item "Nova_HoyleCasino99USA").
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files ?? System.Array.Empty<string>(), matchers, any: true);
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckFilePath(string path)
|
||||
#else
|
||||
public string? CheckFilePath(string path)
|
||||
#endif
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// Found in Redump entry 73521/IA item "Nova_HoyleCasino99USA".
|
||||
new PathMatchSet(new PathMatch("AscLM.cpl", useEndsWith: true), "AegiSoft License Manager"),
|
||||
new PathMatchSet(new PathMatch("AscLM.vxd", useEndsWith: true), "AegiSoft License Manager"),
|
||||
new PathMatchSet(new PathMatch("AscLMd.vxd", useEndsWith: true), "AegiSoft License Manager"),
|
||||
new(new FilePathMatch("AscLM.cpl"), "AegiSoft License Manager"),
|
||||
new(new FilePathMatch("AscLM.vxd"), "AegiSoft License Manager"),
|
||||
new(new FilePathMatch("AscLMd.vxd"), "AegiSoft License Manager"),
|
||||
|
||||
// There are a few other files present, but the file names on their own may be too overmatching. Due to the small sample size, it's not sure if these files are always present together.
|
||||
// These files are "Asc001.dll", "Asc002.dll", "Asc003.dll", "Asc005.dll", and "Asc006.exe" (Found in Redump entry 73521/IA item "Nova_HoyleCasino99USA").
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Paths;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
@@ -16,30 +16,22 @@ namespace BinaryObjectScanner.Protection
|
||||
public class AlphaDVD : IPathCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public ConcurrentQueue<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>
|
||||
{
|
||||
new PathMatchSet(new PathMatch("PlayDVD.exe", useEndsWith: true), "Alpha-DVD (Unconfirmed - Please report to us on Github)"),
|
||||
new(new FilePathMatch("PlayDVD.exe"), "Alpha-DVD (Unconfirmed - Please report to us on Github)"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files ?? System.Array.Empty<string>(), matchers, any: true);
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckFilePath(string path)
|
||||
#else
|
||||
public string? CheckFilePath(string path)
|
||||
#endif
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
new PathMatchSet(new PathMatch("PlayDVD.exe", useEndsWith: true), "Alpha-DVD (Unconfirmed - Please report to us on Github"),
|
||||
new(new FilePathMatch("PlayDVD.exe"), "Alpha-DVD (Unconfirmed - Please report to us on Github"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(path, matchers, any: true);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
@@ -44,11 +43,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public class AlphaROM : IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// TODO: Add support for detecting Alpha-ROM found in older games made with the RealLive engine.
|
||||
// TODO: Add version detection for Alpha-ROM.
|
||||
@@ -75,6 +70,12 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
if (strs.Any(s => s.Contains("This Game is Japan Only")))
|
||||
return "Alpha-ROM";
|
||||
// Found in "Filechk.exe" in Redump entry 115358.
|
||||
if (strs.Any(s => s.Contains("AlphaCheck.exe")))
|
||||
return "Alpha-ROM";
|
||||
// Found in "Uninstall.exe" in Redump entry 115358.
|
||||
if (strs.Any(s => s.Contains("AlphaCheck.dat")))
|
||||
return "Alpha-ROM";
|
||||
}
|
||||
|
||||
// Get the overlay data, if it exists
|
||||
|
||||
60
BinaryObjectScanner/Protection/Armadillo.cs
Normal file
60
BinaryObjectScanner/Protection/Armadillo.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using System.Linq;
|
||||
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 : 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Paths;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
@@ -13,48 +13,40 @@ namespace BinaryObjectScanner.Protection
|
||||
public class Bitpool : IPathCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public ConcurrentQueue<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>
|
||||
{
|
||||
new PathMatchSet(new PathMatch("bitpool.rsc", useEndsWith: true), "Bitpool"),
|
||||
new PathMatchSet(new FilePathMatch("CD.IDX"), "Bitpool"),
|
||||
new(new FilePathMatch("bitpool.rsc"), "Bitpool"),
|
||||
new(new FilePathMatch("CD.IDX"), "Bitpool"),
|
||||
|
||||
// Completely empty file present on multiple discs with Bitpool (Redump entries 52626 and 50229).
|
||||
new PathMatchSet(new PathMatch("LEADOUT.OFS", useEndsWith: true), "Bitpool"),
|
||||
new(new FilePathMatch("LEADOUT.OFS"), "Bitpool"),
|
||||
|
||||
// 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 PathMatchSet(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 ?? System.Array.Empty<string>(), matchers, any: true);
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckFilePath(string path)
|
||||
#else
|
||||
public string? CheckFilePath(string path)
|
||||
#endif
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
new PathMatchSet(new PathMatch("bitpool.rsc", useEndsWith: true), "Bitpool"),
|
||||
new PathMatchSet(new FilePathMatch("CD.IDX"), "Bitpool"),
|
||||
new(new FilePathMatch("bitpool.rsc"), "Bitpool"),
|
||||
new(new FilePathMatch("CD.IDX"), "Bitpool"),
|
||||
|
||||
// Completely empty file present on multiple discs with Bitpool (Redump entries 52626 and 50229).
|
||||
new PathMatchSet(new PathMatch("LEADOUT.OFS", useEndsWith: true), "Bitpool"),
|
||||
new(new FilePathMatch("LEADOUT.OFS"), "Bitpool"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(path, matchers, any: true);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Paths;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
@@ -41,11 +41,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public class ByteShield : IPortableExecutableCheck, IPathCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -134,36 +130,28 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public ConcurrentQueue<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.
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
new PathMatchSet(new PathMatch("Byteshield.dll", useEndsWith: true), "ByteShield Component Module"),
|
||||
new PathMatchSet(new PathMatch("Byteshield.ini", useEndsWith: true), "ByteShield"),
|
||||
new(new FilePathMatch("Byteshield.dll"), "ByteShield Component Module"),
|
||||
new(new FilePathMatch("Byteshield.ini"), "ByteShield"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files ?? System.Array.Empty<string>(), matchers, any: true);
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckFilePath(string path)
|
||||
#else
|
||||
public string? CheckFilePath(string path)
|
||||
#endif
|
||||
{
|
||||
// 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.
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
new PathMatchSet(new PathMatch("Byteshield.dll", useEndsWith: true), "ByteShield Component Module"),
|
||||
new PathMatchSet(new PathMatch("Byteshield.ini", useEndsWith: true), "ByteShield"),
|
||||
new(new FilePathMatch("Byteshield.dll"), "ByteShield Component Module"),
|
||||
new(new FilePathMatch("Byteshield.ini"), "ByteShield"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(path, matchers, any: true);
|
||||
|
||||
@@ -6,11 +6,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public class CDCheck : IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
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
|
||||
@@ -67,11 +67,7 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// TODO: Investigate reference to "CD32COPS.DLL" in "WETFLIPP.QZ_" in IA item "Triada_Russian_DVD_Complete_Collection_of_Erotic_Games".
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckContents(string file, byte[] fileContent, bool includeDebug)
|
||||
#else
|
||||
public string? CheckContents(string file, byte[] fileContent, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// TODO: Obtain a sample to find where this string is in a typical executable
|
||||
if (includeDebug)
|
||||
@@ -80,14 +76,14 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// TODO: Remove from here once it's confirmed that no PE executables contain this string
|
||||
// CD-Cops, ver.
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x43, 0x44, 0x2D, 0x43, 0x6F, 0x70, 0x73, 0x2C,
|
||||
0x20, 0x20, 0x76, 0x65, 0x72, 0x2E, 0x20
|
||||
}, GetVersion, "CD-Cops (Unconfirmed - Please report to us on Github)"),
|
||||
|
||||
// // DVD-Cops, ver.
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x44, 0x56, 0x44, 0x2D, 0x43, 0x6F, 0x70, 0x73,
|
||||
0x2C, 0x20, 0x20, 0x76, 0x65, 0x72, 0x2E, 0x20
|
||||
@@ -101,11 +97,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// TODO: Don't read entire file
|
||||
var data = nex.ReadArbitraryRange();
|
||||
@@ -117,7 +109,7 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// CD-Cops, ver.
|
||||
// Found in "h3blade.exe" in Redump entry 85077.
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x43, 0x44, 0x2D, 0x43, 0x6F, 0x70, 0x73, 0x2C,
|
||||
0x20, 0x20, 0x76, 0x65, 0x72, 0x2E, 0x20
|
||||
@@ -149,11 +141,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -167,14 +155,14 @@ namespace BinaryObjectScanner.Protection
|
||||
{
|
||||
// WEBCOPS
|
||||
// Found in "HyperBowl.C_S" in https://web.archive.org/web/20120616074941/http://icm.games.tucows.com/files2/HyperDemo-109a.exe.
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x57, 0x45, 0x42, 0x43, 0x4F, 0x50, 0x53
|
||||
}, "WEB-Cops")
|
||||
};
|
||||
|
||||
var match = MatchUtil.GetFirstMatch(file, pex.StubExecutableData, matchers, includeDebug);
|
||||
if (!string.IsNullOrWhiteSpace(match))
|
||||
if (!string.IsNullOrEmpty(match))
|
||||
return match;
|
||||
}
|
||||
|
||||
@@ -194,11 +182,7 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public ConcurrentQueue<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>
|
||||
@@ -207,23 +191,19 @@ 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 PathMatchSet(new PathMatch("CDCOPS.DLL", useEndsWith: true), "CD-Cops"),
|
||||
new PathMatchSet(new PathMatch(".W_X", matchExact: true, useEndsWith: true), "CD/DVD-Cops"),
|
||||
new PathMatchSet(new PathMatch(".QZ_", matchExact: true, useEndsWith: true), "CD/DVD-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"),
|
||||
|
||||
new PathMatchSet(new PathMatch(".GZ_", matchExact: true, useEndsWith: true), "CD-Cops (Unconfirmed - Please report to us on Github)"),
|
||||
new PathMatchSet(new PathMatch(".Qz", matchExact: true, useEndsWith: true), "CD-Cops (Unconfirmed - Please report to us on Github)"),
|
||||
new(new PathMatch(".GZ_", matchExact: true, useEndsWith: true), "CD-Cops (Unconfirmed - Please report to us on Github)"),
|
||||
new(new PathMatch(".Qz", matchExact: true, useEndsWith: true), "CD-Cops (Unconfirmed - Please report to us on Github)"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files ?? System.Array.Empty<string>(), matchers, any: true);
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckFilePath(string path)
|
||||
#else
|
||||
public string? CheckFilePath(string path)
|
||||
#endif
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
@@ -231,28 +211,30 @@ 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 PathMatchSet(new PathMatch("CDCOPS.DLL", useEndsWith: true), "CD-Cops"),
|
||||
new PathMatchSet(new PathMatch(".W_X", matchExact: true, useEndsWith: true), "CD/DVD-Cops"),
|
||||
new PathMatchSet(new PathMatch(".QZ_", matchExact: true, useEndsWith: true), "CD/DVD-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"),
|
||||
|
||||
new PathMatchSet(new PathMatch(".GZ_", matchExact: true, useEndsWith: true), "CD-Cops (Unconfirmed - Please report to us on Github)"),
|
||||
new PathMatchSet(new PathMatch(".Qz", matchExact: true, useEndsWith: true), "CD-Cops (Unconfirmed - Please report to us on Github)"),
|
||||
new(new PathMatch(".GZ_", matchExact: true, useEndsWith: true), "CD-Cops (Unconfirmed - Please report to us on Github)"),
|
||||
new(new PathMatch(".Qz", matchExact: true, useEndsWith: true), "CD-Cops (Unconfirmed - Please report to us on Github)"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(path, matchers, any: true);
|
||||
}
|
||||
|
||||
#if NET48
|
||||
public static string GetVersion(string file, byte[] fileContent, List<int> positions)
|
||||
#else
|
||||
public static string? GetVersion(string file, byte[]? fileContent, List<int> positions)
|
||||
#endif
|
||||
{
|
||||
// If we have no content
|
||||
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
|
||||
if (version[0] == 0x00)
|
||||
return string.Empty;
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using BinaryObjectScanner.Interfaces;
|
||||
using SabreTools.Matching;
|
||||
using SabreTools.Matching.Paths;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace BinaryObjectScanner.Protection
|
||||
@@ -24,11 +24,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public class CDGuard : IPathCheck, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -59,32 +55,24 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string> files)
|
||||
#else
|
||||
public ConcurrentQueue<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
#endif
|
||||
public IEnumerable<string> CheckDirectoryPath(string path, IEnumerable<string>? files)
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// Found in Redump entry 97142.
|
||||
new PathMatchSet(new PathMatch("cdguard.dll", useEndsWith: true), "CD-Guard Copy Protection System"),
|
||||
new(new FilePathMatch("cdguard.dll"), "CD-Guard Copy Protection System"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files ?? System.Array.Empty<string>(), matchers, any: true);
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckFilePath(string path)
|
||||
#else
|
||||
public string? CheckFilePath(string path)
|
||||
#endif
|
||||
{
|
||||
var matchers = new List<PathMatchSet>
|
||||
{
|
||||
// Found in Redump entry 97142.
|
||||
new PathMatchSet(new PathMatch("cdguard.dll", useEndsWith: true), "CD-Guard Copy Protection System"),
|
||||
new(new FilePathMatch("cdguard.dll"), "CD-Guard Copy Protection System"),
|
||||
};
|
||||
|
||||
return MatchUtil.GetFirstMatch(path, matchers, any: true);
|
||||
|
||||
@@ -7,11 +7,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public class CDKey : IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
using System.Collections.Concurrent;
|
||||
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
|
||||
@@ -27,11 +28,7 @@ namespace BinaryObjectScanner.Protection
|
||||
public class CDLock : IPathCheck, IPortableExecutableCheck
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#else
|
||||
public string? CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
|
||||
#endif
|
||||
{
|
||||
// Get the sections from the executable, if possible
|
||||
var sections = pex.Model.SectionTable;
|
||||
@@ -47,7 +44,7 @@ namespace BinaryObjectScanner.Protection
|
||||
// Found in game executables protected with CD-Lock (Redump entries 24287 and 31615).
|
||||
// TODO: Check for possible false postives (Redump entry 97942).
|
||||
// 2 + (char)0xF2 + (char)0x02 + (char)0x82 + (char)0xC3 + (char)0xBC + (char)0x0B + $ + (char)0x99 + (char)0xAD + 'C + (char)0xE4 + (char)0x9D + st + (char)0x99 + (char)0xFA + 2$ + (char)0x9D + )4 + (char)0xFF + t
|
||||
new ContentMatchSet(new byte?[]
|
||||
new(new byte?[]
|
||||
{
|
||||
0x32, 0xF2, 0x02, 0x82, 0xC3, 0xBC, 0x0B, 0x24,
|
||||
0x99, 0xAD, 0x27, 0x43, 0xE4, 0x9D, 0x73, 0x74,
|
||||
@@ -57,7 +54,7 @@ namespace BinaryObjectScanner.Protection
|
||||
};
|
||||
|
||||
var match = MatchUtil.GetFirstMatch(file, dataSectionRaw, matchers, includeDebug);
|
||||
if (!string.IsNullOrWhiteSpace(match))
|
||||
if (!string.IsNullOrEmpty(match))
|
||||
return match;
|
||||
}
|
||||
|
||||
@@ -65,38 +62,30 @@ namespace BinaryObjectScanner.Protection
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public ConcurrentQueue<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 PathMatchSet(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).
|
||||
};
|
||||
|
||||
return MatchUtil.GetAllMatches(files ?? System.Array.Empty<string>(), matchers, any: true);
|
||||
return MatchUtil.GetAllMatches(files, matchers, any: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
#if NET48
|
||||
public string CheckFilePath(string path)
|
||||
#else
|
||||
public string? CheckFilePath(string path)
|
||||
#endif
|
||||
{
|
||||
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 PathMatchSet(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).
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user